From 22b2a193d3c6e13474b1cb844d9f6e30bb22ab4f Mon Sep 17 00:00:00 2001 From: Michael Jennings Date: Tue, 17 Aug 1999 23:01:18 +0000 Subject: [PATCH] Initial import of Eterm 0.8.9 sources SVN revision: 38 --- .cvsignore | 17 + COPYING | 340 ++ CVS-README | 11 + ChangeLog | 1627 ++++++++ Eterm.spec.in | 79 + Makefile.am | 7 + README | 124 + ReleaseNotes | 413 ++ acconfig.h | 293 ++ acl.m4 | 249 ++ autogen.sh | 52 + bg/Makefile.am | 42 + bg/Makefile.in | 252 ++ bg/README.backgrounds | 34 + bg/scale/.cvsignore | 4 + bg/tile/.cvsignore | 4 + configure.in | 387 ++ debian/README.debian | 12 + debian/changelog | 137 + debian/control | 17 + debian/copyright | 8 + debian/dirs | 5 + debian/doc-base | 10 + debian/docs | 1 + debian/menu | 2 + debian/postinst | 29 + debian/postrm | 9 + debian/rules | 94 + debian/shlibs.local | 1 + doc/.cvsignore | 4 + doc/Eterm.1.in | 1263 +++++++ doc/Eterm.tcap | 44 + doc/Eterm.ti | 147 + doc/Eterm_reference.html | 1469 ++++++++ doc/FAQ.html | 534 +++ doc/Makefile.am | 14 + install-sh | 238 ++ libmej/Makefile.am | 12 + libmej/Makefile.in | 372 ++ libmej/debug.c | 55 + libmej/debug.h | 36 + libmej/global.h | 47 + libmej/mem.c | 407 ++ libmej/mem.h | 82 + libmej/snprintf.c | 519 +++ libmej/strings.c | 568 +++ libmej/strings.h | 106 + libmej/strptime.c | 272 ++ libmej/strptime.h | 76 + missing | 188 + mkinstalldirs | 32 + reformat-code | 9 + src/.cvsignore | 10 + src/Eterm.xpm | 822 ++++ src/Makefile.am | 30 + src/activeconfig.c | 623 +++ src/activeconfig.h | 106 + src/activeeterm.c | 390 ++ src/activeeterm.h | 48 + src/activetags.c | 524 +++ src/activetags.h | 182 + src/command.c | 7123 +++++++++++++++++++++++++++++++++++ src/command.h | 122 + src/debug.h | 105 + src/eterm_imlib.h | 26 + src/feature.h.in | 527 +++ src/graphics.c | 556 +++ src/graphics.h | 63 + src/graphics/.cvsignore | 2 + src/graphics/Makefile.am | 11 + src/graphics/README | 1 + src/graphics/data | 4000 ++++++++++++++++++++ src/graphics/grxlib.c | 169 + src/graphics/grxlib.h | 28 + src/graphics/qplot.c | 257 ++ src/grkelot.c | 389 ++ src/grkelot.h | 38 + src/grx.h | 53 + src/main.c | 479 +++ src/main.h | 304 ++ src/menubar.c | 2567 +++++++++++++ src/menubar.h | 126 + src/misc.c | 379 ++ src/misc.h | 38 + src/netdisp.c | 148 + src/options.c | 3637 ++++++++++++++++++ src/options.h | 107 + src/pixmap.c | 1611 ++++++++ src/pixmap.h | 89 + src/profile.h | 80 + src/screen.c | 3294 ++++++++++++++++ src/screen.h | 261 ++ src/scrollbar.c | 539 +++ src/scrollbar.h | 91 + src/system.c | 99 + src/system.h | 21 + src/threads.c | 219 ++ src/threads.h | 33 + src/utmp.c | 502 +++ stamp-h.in | 1 + themes/Eterm/.cvsignore | 1 + themes/Eterm/Eterm.menu | 192 + themes/Eterm/MAIN.in | 203 + themes/Makefile.am | 25 + themes/Makefile.in | 238 ++ themes/active.tags | 187 + themes/chooser/.cvsignore | 1 + themes/chooser/MAIN.in | 203 + themes/chooser/chooser.menu | 502 +++ themes/emacs/.cvsignore | 1 + themes/emacs/MAIN.in | 203 + themes/emacs/emacs.menu | 269 ++ themes/irc/.cvsignore | 1 + themes/irc/MAIN.in | 203 + themes/irc/irc.menu | 223 ++ themes/mutt/.cvsignore | 1 + themes/mutt/MAIN.in | 203 + themes/mutt/mutt.menu | 243 ++ themes/tn3270/.cvsignore | 1 + themes/tn3270/MAIN.in | 236 ++ themes/trans/.cvsignore | 1 + themes/trans/MAIN.in | 219 ++ themes/trans/trans.menu | 195 + utils/Esetroot.c | 233 ++ utils/Etbg.c | 68 + utils/Etcolors.sh | 76 + utils/Etmenu.sh | 36 + utils/Makefile.am | 15 + utils/Makefile.in | 405 ++ 129 files changed, 45968 insertions(+) create mode 100644 .cvsignore create mode 100644 COPYING create mode 100644 CVS-README create mode 100644 ChangeLog create mode 100644 Eterm.spec.in create mode 100644 Makefile.am create mode 100644 README create mode 100644 ReleaseNotes create mode 100644 acconfig.h create mode 100644 acl.m4 create mode 100755 autogen.sh create mode 100644 bg/Makefile.am create mode 100644 bg/Makefile.in create mode 100644 bg/README.backgrounds create mode 100644 bg/scale/.cvsignore create mode 100644 bg/tile/.cvsignore create mode 100644 configure.in create mode 100644 debian/README.debian create mode 100644 debian/changelog create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/dirs create mode 100644 debian/doc-base create mode 100644 debian/docs create mode 100644 debian/menu create mode 100644 debian/postinst create mode 100644 debian/postrm create mode 100644 debian/rules create mode 100644 debian/shlibs.local create mode 100644 doc/.cvsignore create mode 100644 doc/Eterm.1.in create mode 100644 doc/Eterm.tcap create mode 100644 doc/Eterm.ti create mode 100644 doc/Eterm_reference.html create mode 100644 doc/FAQ.html create mode 100644 doc/Makefile.am create mode 100644 install-sh create mode 100644 libmej/Makefile.am create mode 100644 libmej/Makefile.in create mode 100644 libmej/debug.c create mode 100644 libmej/debug.h create mode 100644 libmej/global.h create mode 100644 libmej/mem.c create mode 100644 libmej/mem.h create mode 100644 libmej/snprintf.c create mode 100644 libmej/strings.c create mode 100644 libmej/strings.h create mode 100644 libmej/strptime.c create mode 100644 libmej/strptime.h create mode 100644 missing create mode 100644 mkinstalldirs create mode 100755 reformat-code create mode 100644 src/.cvsignore create mode 100644 src/Eterm.xpm create mode 100644 src/Makefile.am create mode 100644 src/activeconfig.c create mode 100644 src/activeconfig.h create mode 100644 src/activeeterm.c create mode 100644 src/activeeterm.h create mode 100644 src/activetags.c create mode 100644 src/activetags.h create mode 100644 src/command.c create mode 100644 src/command.h create mode 100644 src/debug.h create mode 100644 src/eterm_imlib.h create mode 100644 src/feature.h.in create mode 100644 src/graphics.c create mode 100644 src/graphics.h create mode 100644 src/graphics/.cvsignore create mode 100644 src/graphics/Makefile.am create mode 100644 src/graphics/README create mode 100644 src/graphics/data create mode 100644 src/graphics/grxlib.c create mode 100644 src/graphics/grxlib.h create mode 100644 src/graphics/qplot.c create mode 100644 src/grkelot.c create mode 100644 src/grkelot.h create mode 100644 src/grx.h create mode 100644 src/main.c create mode 100644 src/main.h create mode 100644 src/menubar.c create mode 100644 src/menubar.h create mode 100644 src/misc.c create mode 100644 src/misc.h create mode 100644 src/netdisp.c create mode 100644 src/options.c create mode 100644 src/options.h create mode 100644 src/pixmap.c create mode 100644 src/pixmap.h create mode 100644 src/profile.h create mode 100644 src/screen.c create mode 100644 src/screen.h create mode 100644 src/scrollbar.c create mode 100644 src/scrollbar.h create mode 100644 src/system.c create mode 100644 src/system.h create mode 100644 src/threads.c create mode 100644 src/threads.h create mode 100644 src/utmp.c create mode 100644 stamp-h.in create mode 100644 themes/Eterm/.cvsignore create mode 100644 themes/Eterm/Eterm.menu create mode 100644 themes/Eterm/MAIN.in create mode 100644 themes/Makefile.am create mode 100644 themes/Makefile.in create mode 100644 themes/active.tags create mode 100644 themes/chooser/.cvsignore create mode 100644 themes/chooser/MAIN.in create mode 100644 themes/chooser/chooser.menu create mode 100644 themes/emacs/.cvsignore create mode 100644 themes/emacs/MAIN.in create mode 100644 themes/emacs/emacs.menu create mode 100644 themes/irc/.cvsignore create mode 100644 themes/irc/MAIN.in create mode 100644 themes/irc/irc.menu create mode 100644 themes/mutt/.cvsignore create mode 100644 themes/mutt/MAIN.in create mode 100644 themes/mutt/mutt.menu create mode 100644 themes/tn3270/.cvsignore create mode 100644 themes/tn3270/MAIN.in create mode 100644 themes/trans/.cvsignore create mode 100644 themes/trans/MAIN.in create mode 100644 themes/trans/trans.menu create mode 100644 utils/Esetroot.c create mode 100644 utils/Etbg.c create mode 100755 utils/Etcolors.sh create mode 100755 utils/Etmenu.sh create mode 100644 utils/Makefile.am create mode 100644 utils/Makefile.in diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 0000000..dc23e77 --- /dev/null +++ b/.cvsignore @@ -0,0 +1,17 @@ +config.log +config.sub +config.cache +config.guess +configure +ltconfig +ltmain.sh +Makefile +Makefile.in +aclocal.m4 +config.status +config.h +libtool +stamp-h +move-themes +Eterm.spec +config.h.in diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..a3f6b12 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE 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. + + END OF TERMS AND CONDITIONS + + Appendix: 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 +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This 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 Library General +Public License instead of this License. diff --git a/CVS-README b/CVS-README new file mode 100644 index 0000000..5783488 --- /dev/null +++ b/CVS-README @@ -0,0 +1,11 @@ +As of 31 August 1998, Eterm is now available via anonymous CVS from +anoncvs.gnome.org. If you don't know how to use CVS, don't use it. +The authors, of course, don't guarantee anything whatsoever about +Eterm being functional; we guarantee even less if you get it from +CVS. We will try to remember to test things before we commit them, +but we make no promises. :-) + +Happy terming! + +mej + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..49de670 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,1627 @@ +ChangeLog +========= + +This file contains a listing of modifications to Eterm in CVS on a per-commit +basis. Dates are included, as are nicknames/names/initials for the persons +making the changes. + + +Thu Sep 3 17:27:35 CDT 1998 Michael Jennings + + Removed RELNOTES.Eterm and split it into README and ChangeLog. I also + fixed options.c so that keysym definitions are at least accepted. Now + I'll have to find a tn3270 to test with. :-) + +------------------------------------------------------------------------------- +Thu Sep 3 17:57:38 CDT 1998 Michael Jennings + + Added the trans theme and fixed doc/Makefile.in to remove Esetroot on + "make distclean" + +------------------------------------------------------------------------------- +Thu Sep 3 18:36:10 CDT 1998 Michael Jennings + + Added the --shade option to replace the DARKEN_TRANSPARENCY #define. + +------------------------------------------------------------------------------- +Thu Sep 3 20:28:22 CDT 1998 Michael Jennings + + Fixed problems compiling with MENUBAR_MAX == 0 and without pixmap + support and/or transparency support. + + Some unneeded code was removed from main.c as well. + + Added the --enable-menus (or --disable-menus) option to the configure + script to automatically disable menubar support. + +------------------------------------------------------------------------------- +Fri Sep 4 11:28:30 CDT 1998 Michael Jennings + + Added in the Eterm man page Shaleh fixed up for us. + Thanks Shaleh! + + Also updated the doc/FAQ.html file with the latest FAQ from the web. + +------------------------------------------------------------------------------- +Fri Sep 4 11:36:33 CDT 1998 Michael Jennings + + Ripped the RELNOTES.Eterm stuff out of ChangeLog and put it in + ReleaseNotes. I decided not to use the name RELNOTES because it does + annoying things with trying to Tab-complete "README". =) From now on, + ChangeLog will be the detail and RELNOTES will be the summary. + +------------------------------------------------------------------------------- +Fri Sep 4 13:24:49 CDT 1998 Michael Jennings + + Fixed a bug mandrake pointed out where supplying a pixmap would kill + a transparent Eterm. + +-------------------------------------------------------------------------------- +Fri Sep 4 13:47:32 CDT 1998 Michael Jennings + + Fixed the bug pointed out by technoir that made transparent Eterms + flicker when there were two on the desktop at the same time and one was + moving. + +------------------------------------------------------------------------------- +Fri Sep 4 15:42:55 CDT 1998 Michael Jennings + + Fixed scrollbar_floating with transparency so that the root image + shows through underneath the scrollbar. The effect is really sweet. :) + +-------------------------------------------------------------------------------- +Fri Sep 4 16:22:29 CDT 1998 Michael Jennings + + Fixed scrollbar_floating without transparency so that it shows the + background color instead of white. + +------------------------------------------------------------------------------- +Fri Sep 4 18:48:08 CDT 1998 Michael Jennings + + Added the --tint option. Specify a shade of tinting for a pseudo- + transparent Eterm. It implies --shade. Choices are red, green, blue, + purple, orange, or yellow. + +------------------------------------------------------------------------------- +Fri Sep 4 19:31:18 CDT 1998 Michael Jennings + + Fixed a stupid mistake in doing the tinting. Also enabled "yes" and + "no" as valid boolean values. + +------------------------------------------------------------------------------- +Fri Sep 4 21:34:09 CDT 1998 Michael Jennings + + Fixed the color names. Thanks to technoir for assistance with this. + Choices are now red, green, blue, cyan, magenta, yellow. + +------------------------------------------------------------------------------- +Sat Sep 5 14:28:18 1998 sdh + + Apply focus color change to menubar and scrollbars. Remove old + code that was surrounded by CHANGE_SCROLLCOLOR_ON_FOCUS. Toss + update flag that was exported by scrollbar.h and let menubar.c & + scrollbar.c track focus independently. Old code was doing a bunch + of XCreateGC's without ever freeing the gc. Still a bit kludgy, + but no more so than the shadow color code for the menu/scroll bar. + + New config option, unfocusedscrollbar . Command line + option --unfocused-scrollbar-color . Add config entry to + themes/Eterm/MAIN. + + Turn on CHANGE_SCROLLCOLOR_ON_FOCUS by default in feature.h. + + Add color init entry for menuTextColor def_colorName (main.c). + + Why does menubar.c use the global Attributes exported by main.c? + +------------------------------------------------------------------------------- +Tue Sep 8 13:50:10 CDT 1998 Michael Jennings + + Updated the menubar files to take advantage of some of the newer + background images in the collection. Also removed the pixmap menu from + the "trans" theme since it's all ignored anyway. + +------------------------------------------------------------------------------- +Tue Sep 8 15:14:00 CDT 1998 Michael Jennings + + Cleaned up the changes made by "sdh" (whoever that is). :-) If the + unfocused color is not defined, it will revert to the scrollbar color, + creating a way to "turn the option off," so to speak. It also makes + sure that people who don't want to see the difference don't see it. + + Added autogen.sh for the tragically habitual. ;-) + + By the way, a few pointers for those messing with Eterm. For one, + feature.h is created from feature.h.in, so changing feature.h does + not affect the final distributed form of Eterm. I had to update + src/feature.h.in to define CHANGE_SCROLLCOLOR_ON_FOCUS in order to see + the changes take effect. For two, if you change the MAIN.in for Eterm, + please change the other themes too. + +------------------------------------------------------------------------------- +Tue Sep 8 17:16:34 CDT 1998 Michael Jennings + + Fixed transparency so that it works on any desktop, not just the root. + Only works with E, so non-E users are S.O.L. (Sorry, that's life.) + Thanks to raster for helping me with this. :-) + +------------------------------------------------------------------------------- +Tue Sep 8 20:52:18 CDT 1998 Michael Jennings + + Added a new feature. This was requested by Nick Vargish + . Basically, the new option --watch-bg (or config + file toggle "watch_bg") tells Eterm to keep track of the mod time of + the background pixmap. If the pixmap changes, Eterm updates and + redraws the background. When coupled with an outside program, this + can produce cycling and/or animated backgrounds. + + NOTE: This feature is highly experimental. It can crash Eterm if not + done properly and carefully. In fact, at this point it's more of a + demonstration/proof-of-concept than a feature. If there is enough + interest, I will internalize more of it. + +------------------------------------------------------------------------------- +Sun Sep 13 13:18:31 CDT 1998 Michael Jennings + + Fixed the scrollbar_floating option with transparency (again). sdh's + changes on 9/5 screwed it up. The pixmap now shows through once again. + And there was much rejoicing. + +------------------------------------------------------------------------------- +Sun Sep 13 16:08:06 CDT 1998 Michael Jennings + + Added .cvsignore files. + +------------------------------------------------------------------------------- +Mon Sep 14 10:11:41 CDT 1998 Michael Jennings + + Fixed a bug pointed out by Hans Engren which kept + Eterm and Esetroot from working under certain conditions. + +------------------------------------------------------------------------------- +Mon Sep 14 11:38:06 CDT 1998 Michael Jennings + + Final documentation cleanups before the release of 0.8.6. + +------------------------------------------------------------------------------- +Mon Sep 14 12:04:43 CDT 1998 Michael Jennings + + Final compilation cleanups before release of 0.8.6. With this commit, + CVS will contain the release version of 0.8.6. + +------------------------------------------------------------------------------- +Mon Sep 14 12:58:32 CDT 1998 Michael Jennings + + Installed 0.8.7 into CVS. This release has some major changes in it. + For one, Eterm now uses automake and libtool. The old libmej is now + built as a shared library as well as a static one. Also, everything + but the main() function has been moved into a library, libEterm. Since + most people use lots of Eterms at once, creating a shared library will + reduce the text segment of each Eterm significantly, saving quite a bit + of memory per Eterm. + +------------------------------------------------------------------------------- +Tue Sep 15 13:10:20 CDT 1998 Michael Jennings + + Fixed a bug compiling on Linux. (Damn Linux having dprintf!) ;-P + +------------------------------------------------------------------------------- +Tue Sep 15 13:23:00 CDT 1998 Michael Jennings + + Fixed another bug on Linux, this time with linking Esetroot. + +------------------------------------------------------------------------------- +Tue Sep 15 14:10:05 CDT 1998 Michael Jennings + + Removed MIN_ANCHOR_SIZE and added -a (--min-anchor-size) option. It + is 0 by default so ppl won't complain about the scroll-up "bug". + +------------------------------------------------------------------------------- +Tue Sep 15 15:03:57 CDT 1998 Michael Jennings + + Changed the pixmap setting code in Esetroot so it will (hopefully) work + better. Geez, if everyone would just use Enlightenment, it would save + me so much grief.... ;-) + +------------------------------------------------------------------------------- +Tue Sep 15 16:00:26 CDT 1998 Michael Jennings + + Fixed the scaling problem in Esetroot pointed out by technoir thanks + to some code swiped from Enlightenment. I also nuked the code that + was killing Enlightenment when running Esetroot. (Not an E bug, just + lame code.) =P + +------------------------------------------------------------------------------- +Tue Sep 15 17:25:53 CDT 1998 Michael Jennings + + Choosing a pixmap in a transparent Eterm now works. I also renamed + StrSep() to strsep() and changed configure.in to check for strsep(). + That allowed me to remove some really annoying #ifdef's in command.c. + +------------------------------------------------------------------------------- +Tue Sep 15 17:59:24 CDT 1998 Michael Jennings + + Added initial support for an escape code sequence set to mess with the + various transparency options. It doesn't work yet, so don't bother + trying to use it. Some of it will even crash Eterm at this point, but + I'm going home anyway. :-) + +------------------------------------------------------------------------------- +Wed Sep 16 11:42:16 CDT 1998 Michael Jennings + + Initial work on a patch for CygWin32 support. Also updated autogen.sh + to create libtool stuff. + +------------------------------------------------------------------------------- +Wed Sep 16 15:25:32 CDT 1998 Michael Jennings + + Fixed some misc. problems with the new escape sequences. Toggling + transparency on and off now works (more or less). At least stuff won't + crash. :-) Still some kinks to iron out, as always. + +------------------------------------------------------------------------------- +Wed Sep 16 17:21:52 CDT 1998 Michael Jennings + + Fixed the escape sequence for Pixmap -> None (again). Also made the + transparency toggle work for not having a pixmap. + +------------------------------------------------------------------------------- +Wed Sep 16 18:20:47 CDT 1998 Michael Jennings + + Updated the default themes to include the Trans menu. + +------------------------------------------------------------------------------- +Thu Sep 17 13:05:30 CDT 1998 Michael Jennings + + Hack for newer Linux versions in which the real uid must be nonzero to + open the display. + +------------------------------------------------------------------------------- +Thu Sep 17 13:50:50 CDT 1998 Michael Jennings + + Moved the #define for the Linux fix into config.h + +------------------------------------------------------------------------------- +Thu Sep 17 16:59:17 CDT 1998 Michael Jennings + + This version has a working CygWin32 port! :-) Some minor hacking may + still be required. + + Also included a test for something with transparency. + +------------------------------------------------------------------------------- +Thu Sep 17 17:29:39 CDT 1998 Michael Jennings + + Changed code to use setres*id() functions if they are there (Linux and + HP-UX only AFAIK). This is a vast security improvement for Linux. + +------------------------------------------------------------------------------- +Thu Sep 17 17:49:19 CDT 1998 Michael Jennings + + Hopefully fixed privileges() for systems without setres*id() or saved + uids. + +------------------------------------------------------------------------------- +Thu Sep 17 17:58:17 CDT 1998 Michael Jennings + + More .cvsignore entries. + +------------------------------------------------------------------------------- +Thu Sep 17 19:03:22 CDT 1998 Michael Jennings + + Changed the --watch-bg option to --watch-pixmap, which will hopefully + make it less tempting for people to think it has something to do with + transparency. + + Also added the --watch-desktop option which causes Eterm to monitor + the desktop pixmap for changes and update accordingly. It doesn't + cause flicker like it used to. + +------------------------------------------------------------------------------- +Thu Sep 17 19:36:56 CDT 1998 Michael Jennings + + Some config file parser cleanups and additions to the trans theme. + +------------------------------------------------------------------------------- +Thu Sep 17 20:03:57 CDT 1998 Michael Jennings + + Makefile and theme cleanups. + +------------------------------------------------------------------------------- +Thu Sep 17 20:45:03 CDT 1998 Michael Jennings + + Fixed a major bug which caused Eterm to seg fault in trans theme. + +------------------------------------------------------------------------------- +Thu Sep 17 20:56:33 CDT 1998 Michael Jennings + + Fixed another seg fault bug, this time with changing the pixmap via + escape sequence. Doh! + +------------------------------------------------------------------------------- +Thu Sep 17 21:03:34 CDT 1998 Michael Jennings + + Changed the scrollbar_floating attribute back on for the trans theme. + Geez, is there no end to the stuff I've screwed up today?? =P + +------------------------------------------------------------------------------- +Fri Sep 18 09:33:30 CDT 1998 Michael Jennings + + Added some checks to autogen.sh + +------------------------------------------------------------------------------- +Fri Sep 18 11:18:59 CDT 1998 Michael Jennings + + Put in the #define IMLIB_TRANS, which will make Eterm use Imlib to do + the transparency stuff. There's a problem with it, though, either in + Imlib_create_image_from_drawable() or the way I'm calling it. For + obvious reasons, it's off by default. + +------------------------------------------------------------------------------- +Fri Sep 18 16:39:15 CDT 1998 Michael Jennings + + As expected, raster's imlib fix corrected the problem. Imlib + transparency rendering now works as expected. It is still off by + default since tinting and shading aren't in yet. + + Also in this commit is a "fix" to autogen.sh. I got complaints (well, + actually one complaint) about autogen.sh not running configure, so now + it does. IMHO, this behavior is incorrect, as the function of autogen + should be to GENerate the AUTOconf/AUTOmake stuff, not run it. But + since "all the other apps in cvs" run configure, for the sake of + standardization and nothing more, I'll do it. + +------------------------------------------------------------------------------- +Mon Sep 21 15:45:17 CDT 1998 Michael Jennings + + Fixed the aforementioned memory leak as well as some others. Dangling + pointers were cut in half. :) + + Imlib transparency still needs to be worked on (read: sped up). One + thing at a time though. + + I also fixed some duplicate rendering that was going on with + pseudo-transparency. + +------------------------------------------------------------------------------- +Mon Sep 21 16:10:46 CDT 1998 Michael Jennings + + Fixed the transparency toggle. + +------------------------------------------------------------------------------- +Mon Sep 21 17:05:31 CDT 1998 Michael Jennings + + Fixed bug in Imlib transparency code. + +------------------------------------------------------------------------------- +Mon Sep 21 19:46:44 CDT 1998 Michael Jennings + + Looks like Imlib-based transparency is working now. It only reads the + desktop image once. After that, it uses the same desktop pixmap + throughout. So startup is much slower, but through the rest of the + run it's much faster. + +------------------------------------------------------------------------------- +Mon Sep 21 20:53:44 CDT 1998 Michael Jennings + + Added --shade-pct. When Imlib-based transparency is enabled, you can + specify a percentage by which to shade the background (0 being no + shading, 100 being all black, not to mention rather pointless). + +------------------------------------------------------------------------------- +Tue Sep 22 10:41:32 CDT 1998 Michael Jennings + + With Imlib-based transparency, Eterm now takes --tint as a numerical + option. You specify a 24-bit RGB mask for colored tinting, such as + "--tint 0xffafaf" for a deep red tint or "--tint 0xefefff" for a slight + blue tint. + +------------------------------------------------------------------------------- +Tue Sep 22 14:48:03 CDT 1998 Michael Jennings + + Fixed a bug in non-Imlib-based transparency. I also made preparations + for letting non-Imlib-based transparency do shading percentages and + tinting masks. Works on 8bpp, but since that's the only thing I can + test, I'll wait until tomorrow and make sure the other pixel depths + work before I go further. + + Imlib-based transparency is pretty slow, but there's more that can be + done with it as far as RGB curves and stuff, so I plan to keep support + for it in there. But I'd stick to using Xlib-based transparency for + now. + +------------------------------------------------------------------------------- +Tue Sep 22 18:28:49 CDT 1998 Michael Jennings + + Fixed the menubar code so that the menus aren't clipped by the window + or screen edge. There's still one small problem, but I'll look at that + later. :) + +------------------------------------------------------------------------------- +Tue Sep 22 21:20:16 CDT 1998 Michael Jennings + + If root_pixmap() returns None, transparency gets turned off instead of + rendering on a null pixmap. + +------------------------------------------------------------------------------- +Wed Sep 23 10:26:01 CDT 1998 Michael Jennings + + Fixed that one last menubar bug. + +------------------------------------------------------------------------------- +Wed Sep 23 11:46:44 CDT 1998 Michael Jennings + + Fixed a segfault in Esetroot. Also fixed --watch-desktop to work + again (just for you, Nat). ;-) + +------------------------------------------------------------------------------- +Wed Sep 23 19:07:11 CDT 1998 Michael Jennings + + Some bug fixes pertaining to root_pixmap() failing, transparency and + background pixmaps coinciding, etc. + + Also changed the shell_expand() function in options.c so that \' + within single quotes would insert a single quote. This differs from + the shell behavior, but I prefer it. :) + +------------------------------------------------------------------------------- +Thu Sep 24 17:14:29 CDT 1998 Michael Jennings + + Fixed a bug with tiling pixmaps in transparency code. (Didn't do it + the way raster wanted it, but it works for now. I'll make it better + later. Unless raster wants to patch it....) :-) + + Fixed a bug building without CHANGE_SCROLLCOLOR_ON_FOCUS support. + + Changed config file magic numbers to "Eterm-0.8". + + The latter two are thanks to Casey Zacek + +------------------------------------------------------------------------------- +Fri Sep 25 22:32:30 CDT 1998 Michael Jennings + + Fixed a bug in Esetroot.c and the CUTCHARS default in src/feature.h.in + +------------------------------------------------------------------------------- +Fri Sep 25 22:35:44 CDT 1998 Michael Jennings + + Missed another typo in Esetroot.c + +------------------------------------------------------------------------------- +Sat Sep 26 21:11:48 EDT 1998 mandrake + + cleaned up a lot of stuff so it compiles a little cleaner. + +------------------------------------------------------------------------------- +Tue Sep 29 14:04:39 CDT 1998 Michael Jennings + + Fixed utmp.c for OpenBSD thanks to Jason Ish + +------------------------------------------------------------------------------- +Tue Sep 29 17:14:11 CDT 1998 Michael Jennings + + Removed the variables mandrake commented out, except for the one that + was still needed. I uncommented that one and put it in #ifdef's to + fix the compiler warnings. + +------------------------------------------------------------------------------- +Thu Oct 8 15:24:10 CDT 1998 Michael Jennings + + Some transparency speed-ups (I hope). Still trying to figure out why + I'm not getting ReparentNotify events. =P Also fixed the bug mandrake + pointed out with transparency and the desktop dragbar under E. + + Also some fixes from Fritz Mueller for X + servers which lie about pixel depth and for a bug in Eterm's magic + number checker. + +------------------------------------------------------------------------------- +Thu Oct 8 15:29:01 CDT 1998 Michael Jennings + + Correct order: Compile FIRST, commit SECOND. Doh!! =P + +------------------------------------------------------------------------------- +Fri Oct 9 12:06:10 CDT 1998 Michael Jennings + + Added --with-debugging[=num] to support debugging levels up through 5. + + Also added stack trace dump if the OS supports it. In order of + preference, the methods are: U_STACK_TRACE() (on HP-UX in libcl), + pstack (on Solaris), gdb, dbx. + +------------------------------------------------------------------------------- +Fri Oct 9 12:18:32 CDT 1998 Michael Jennings + + Oops, forgot to add libmej/snprintf.c to the repository. =P + +------------------------------------------------------------------------------- +Sun Oct 11 17:35:18 CDT 1998 Michael Jennings + + Fixed autogen.sh so that VERSION was defined again. Apparently + running autoheader before other stuff in autogen.sh is a Bad Thing. + +------------------------------------------------------------------------------- +Tue Oct 13 17:38:30 CDT 1998 Michael Jennings + + If the desktop pixmap goes away (which happens if you're on another + desktop for awhile), we'll just use the old one until it comes back. + + Also added Id strings to all C files. + +------------------------------------------------------------------------------- +Tue Oct 13 18:18:03 CDT 1998 Michael Jennings + + Added Id strings to the Makefile.am files, src/feature.h.in, + configure.in, and autogen.sh. Also added an entry to keep CVS quiet. + +------------------------------------------------------------------------------- +Wed Oct 14 12:55:13 CDT 1998 Michael Jennings + + Fixed the bug with dragging a transparent Eterm across E's desktop + dragbar. It reparents to the root window for a bit, but once you drop + the window, it changes backdrops right on cue. Also works when moving + Eterm windows between desktops. Note that this requires the use of + the -W (--watch-desktop) option. + +------------------------------------------------------------------------------- +Wed Oct 14 13:02:37 CDT 1998 Michael Jennings + + Nuked some leftover code from testing. (oops) + +------------------------------------------------------------------------------- +Wed Oct 14 14:49:01 CDT 1998 Michael Jennings + + Added some debugging code to Esetroot.c and added the -x switch to turn + on debugging. Hopefully this will help me track down the DISPLAY bug. + +------------------------------------------------------------------------------- +Wed Oct 14 14:54:46 CDT 1998 Michael Jennings + + Blah. Forgot to "if (debug)" out a couple lines. =P + +------------------------------------------------------------------------------- +Mon Oct 19 15:33:48 CDT 1998 Michael Jennings + + Fixed transparency stuff so it wouldn't take up mondo CPU time. Since + we're getting events for other windows now, we need to make sure we + only act on events that are ours. + + Also fixed scrollbar coloring in transparent mode. + +------------------------------------------------------------------------------- +Mon Oct 19 17:03:47 CDT 1998 Michael Jennings + + New features courtesy a patch from James Antill + as described here: + + \e[9n prints the pixmap filename in the title bar. In transparency + mode, prints transparency info to the title bar. + + --home-on-input option which split off part of --home-on-echo + + Replaced "strncasecmp(buff, "string ", num)" with macro. + +------------------------------------------------------------------------------- +Wed Oct 21 11:11:04 CDT 1998 Michael Jennings + + Fixed a bug with -W and -x together. + +------------------------------------------------------------------------------- +Wed Oct 21 12:26:53 CDT 1998 Michael Jennings + + Final documentation cleanups for 0.8.7 release tomorrow. Barring bug + fixes in the next 24 hours or so, this is 0.8.7 as it will be released + sometime tomorrow morning. + +------------------------------------------------------------------------------- +Thu Oct 22 23:38:47 PDT 1998 Manish Singh + + * strings.c, strings.h: make everything consistent + +------------------------------------------------------------------------------- +Mon Oct 26 22:26:47 CST 1998 Michael Jennings + + Major changes to the man page. Hopefully people who actually bother + to read the man page will find it easier to mess with the MAIN file. + +------------------------------------------------------------------------------- +Mon Nov 2 13:24:21 CST 1998 Michael Jennings + + Lots of changes here. This is the first commit of 0.8.8. The new + features are: + + --shade now takes a percentage of shading. 0% is no shading, 100% is + all black, and anything in between goes. Percent sign optional. + + --tint now takes a 24-bit hexadecimal mask. 0xffffff is no tinting, + 0x000000 is black, and anything in between goes. It will also take + decimal or octal if you *really* have the urge, but hex is the most + readable. + + -V (--menubar-move) now allows dragging the menubar to move the + window. It is on by default if the -x (--borderless) option is used, + and off by default otherwise. + + The transparency/shading/tinting escape sequences now work. + + FORCE_BACKSPACE and FORCE_DELETE have been fixed. + + KS_DELETE (the strings associated with pressing the Delete key) is + now set to ^? by default. + + -N (--anim) options for background pixmap cycling. Syntax is + " ..." where is the delay in + seconds between updates and is either "0 0 " or + "-1 -1 " or "". This feature should still be considered + beta. + + --with-cc argument to configure for forcing a build with an alternative + compiler (for those who have pgcc but want to use gcc, etc.). + +------------------------------------------------------------------------------- +Mon Nov 2 16:11:37 CST 1998 Michael Jennings + + Feh. Got rid of the warning in command.c. Chalk that one up to + laziness on my part. =P + +------------------------------------------------------------------------------- +Tue Nov 3 19:56:15 CST 1998 Michael Jennings + + Added an optional boolean parameter to ESC ] 6 ; 0 escape sequence. + Also added code to clear the shading/tinting when loading a new + pixmap. This will be an option soon, but not tonight. + +------------------------------------------------------------------------------- +Thu Nov 5 19:17:58 CST 1998 Michael Jennings + + Added support for the old color strings to the escape sequence handler + for tinting. They won't work on the command line, though. + + xerror_handler() will no longer exit Eterm. We'll see how that goes. + + New --disable-stack-trace option to configure to disable stack + tracing on abnormal termination. + +------------------------------------------------------------------------------- +Fri Nov 6 09:26:38 CST 1998 Michael Jennings + + Shading and tinting were broken for 2 days, and nobody told me. Feh. + +------------------------------------------------------------------------------- +Mon Nov 9 15:38:11 CST 1998 Michael Jennings + + No, I said *don't* exit on X errors. And I meant it. Really. + +------------------------------------------------------------------------------- +Mon Nov 9 20:00:08 CST 1998 Michael Jennings + + Added src/Eterm.xpm as the default Eterm icon pixmap. + + Added the -I/--icon parameters to specify an alternate icon pixmap. + The attribute "icon " is valid in the pixmaps context of the + config file. + + Note that -I used to be --print-pipe. Not any more. + +------------------------------------------------------------------------------- +Tue Nov 10 11:47:42 CST 1998 Michael Jennings + + Fixed a bug when no background image was specified. Dunno how on + earth that happened.... + + When Eterm gets the escape sequence to change the title, it will also + change the icon name. Not compliant with other terms, but I don't + care. What mandrake wants, mandrake gets. ;-) Besides, sometimes you + have to violate standards in favor of useability. This is one of + those times. + + When an icon is specified, use XGetIconSizes() to pick a size for it. + When using the default, it's 64x64. The WM can cope. :-) + + No, mandrake, it's still not ICCCM, but I'm working on it. :-) + + And no, raster, it doesn't snapshot the window. I'll leave that one + to you to write. You can thank me later. >:) + +------------------------------------------------------------------------------- +Tue Nov 10 20:11:54 CST 1998 Michael Jennings + + Now the hosts in the chooser theme change the title bar instead of the + menubar title, thanks to a new extended menubar function called + "apptitle:". See themes/chooser/chooser.menu for an example of it in + action. + + Kterm (Kanji Eterm) now supports multi-byte fonts in the menubar, + thanks to Sung-Hyun Nam . + +------------------------------------------------------------------------------- +Wed Nov 11 12:18:00 CST 1998 Michael Jennings + + Wheee. Minor bug fix. Also redid the cvs_ident string declarations + to make egcs happy. =P + +------------------------------------------------------------------------------- +Thu Nov 12 16:33:17 KST 1998 Sung-Hyun Nam + + KANJI: Minor memory leak fix. Change XLOCALE stuff. + +------------------------------------------------------------------------------- +Thu Nov 12 03:10:50 EST 1998 Gerald Britton + + Esetroot.c: Fixed an X server memory leak. + +------------------------------------------------------------------------------- +Thu Nov 12 08:54:58 CST 1998 Michael Jennings + + Reverted Gerald's change. Been there, done that. It kills E. Sorry, + but if the X server doesn't work right, that's not my problem. I'm + not going to kill E over it. Tough break. + +------------------------------------------------------------------------------- +Mon Nov 16 19:31:29 CST 1998 Michael Jennings + + Finally got around to doing that icon window thing to make mandrake + and ICCCM (the next-to-worst acronym in history, second only to i18n) + happy. Are we there yet? + +------------------------------------------------------------------------------- +Tue Nov 17 11:17:57 CST 1998 Michael Jennings + + Fixes for Digital UNIX from . These were all "Stupid + KainX" bugs that I didn't catch because GNU's cpp is more forgiving + than most vendors' cpp's. + +------------------------------------------------------------------------------- +Tue Nov 24 13:39:34 CST 1998 Michael Jennings + + This is the Correct (tm) fix to the memory leak pointed out by + Gerald. He and I had a pow-wow of sorts via e-mail with Nat and + raster, and this is the solution that wasn't crapped on by anyone. + :-) + + Just to document what we came up with.... Esetroot sets the + _XROOTPMAP_ID property as always, but now it sets a companion property + as well, ESETROOT_PMAP_ID. Both are set to the same pixmap ID. When + Esetroot runs, it checks to see if _XROOTPMAP_ID == ESETROOT_PMAP_ID, + and if so, it knows that it set the pixmap itself and can safely do + an XKillClient() on it. If they are not equal, calling XKillClient() + would kill the application which did set it, most likely a window + manager like Enlightenment or the patched versions of AfterStep or + WindowMaker. + + No window manager code changes should be necessary. If, however, + a person were to write a "helper app" that sets the background (like + Esetroot does), further memory leaks could be avoided by having that + program set/change ESETROOT_PMAP_ID. + +------------------------------------------------------------------------------- +Tue Nov 24 16:26:22 CST 1998 Michael Jennings + + Added -center (-c) option to Esetroot for centering the pixmap. Most + of these changes are from a patch submitted by Ralph Giles + . + +------------------------------------------------------------------------------- +Tue Nov 24 20:05:05 CST 1998 Michael Jennings + + Some fairly useless stuff that I really don't even want to document + for fear it might actually get used, and people will expect more out + of it than they should. If you really wanna know, diff it. :) + +------------------------------------------------------------------------------- +Tue Nov 24 21:48:24 CST 1998 Michael Jennings + + New feature. --pause will make Eterm wait for a keypress when the + child process exits. Useful most often in combination with -e. + + Also removed all traces of --watch-pixmap. Good riddance. -N + (--anim) is much smoother and less bug-prone. + +------------------------------------------------------------------------------- +Wed Nov 25 11:47:05 CST 1998 Michael Jennings + + Some bug fixes in the ongoing saga of KainX vs. The Solaris 7 64-Bit + Kernel. + +------------------------------------------------------------------------------- +Fri Dec 4 16:11:03 CST 1998 Michael Jennings + + Ok, this should make Eterm compliant with the GNU FHS. I also did a + LOT of futzing around with configure.in, so if I broke something in + doing either of these things, please let me know. + +------------------------------------------------------------------------------- +Fri Dec 4 19:45:39 CST 1998 Michael Jennings + + Feh. Thanks Pavlov. :-) + +------------------------------------------------------------------------------- +Mon Dec 7 18:04:09 CST 1998 Michael Jennings + + FreeBSD fixes, fixes for building without Imlib support (oops), and + fixes for the RPATH problem with Debian and autofs. Thanks to Murray + Stokely for continued help on the FreeBSD front. + +------------------------------------------------------------------------------- +Tue Dec 8 12:10:55 CST 1998 Michael Jennings + + Another of the Eterm-specific escape sequences. This one is \e]6;3\a + which will force Eterm to update the pseudo-transparent background. + To those who've complained about -W making things too slow...Merry + Christmas. :-) + +------------------------------------------------------------------------------- +Tue Dec 8 16:55:44 CST 1998 Michael Jennings + + Another oopsie from the December 4th changes. + +------------------------------------------------------------------------------- +Fri Dec 18 13:44:04 CST 1998 Michael Jennings + + The long awaited selection options. There are two new options here. + The first, --xterm-select, duplicates xterm's treatment of cutchars + (which is broken, IMHO, but some people want it). The second, + --select-line, causes Eterm to select the whole line on a triple-click. + The default is now to select only to the end of the line plus the + current word. The corresponding config file attributes, xterm_select + and select_line, both go in the toggles context. + +------------------------------------------------------------------------------- +Mon Dec 28 18:20:01 CST 1998 Michael Jennings + + From the Trying-to-Please-All-the-People-All-the-Time department... + %random() seeds based on process ID *and* time(NULL) now. Feh. + +------------------------------------------------------------------------------- +Tue Dec 29 16:52:34 CST 1998 Michael Jennings + + A new Eterm feature. This one is called "Viewport Mode." It is + toggled on by the --viewport-mode parameter or the viewport_mode + attribute in the toggles section. The basic concept is that the + background of the Eterm window becomes a viewport to a background + image. Kinda like pseudo-transparency, but not related to the desktop + in any way. As you move the Eterm window, the background moves too. + Scaled pixmaps are scaled up to the size of the desktop, and a portion + shows through as the background. + + Okay, so it's kinda hard to describe. :-) Just try it and see. I + recommend getting several of them open at once using the same scaled + image. The effect is interesting. :-) + + Shading and tinting don't yet work with it, but I'm getting there. At + least it won't crash your X server, like it did mine earlier. :-) + + Credit to es9 on IRC for the idea. + +------------------------------------------------------------------------------- +Tue Dec 29 17:12:57 CST 1998 Michael Jennings + + And Tynian said, "Let there be Debian Stuff." And there was Debian + Stuff. And it was good. + +------------------------------------------------------------------------------- +Tue Dec 29 17:51:21 CST 1998 Michael Jennings + + Viewport + shading/tinting escape sequences is fixed. I also fixed a + bug with shading/tinting. + +------------------------------------------------------------------------------- +Wed Dec 30 12:07:18 CST 1998 Michael Jennings + + Added an Eterm.spec.in file as submitted by techn0ir, with a couple + minor changes. I know nothing about this file, so I have no clue how + well it will work, if at all. + + configure.in now generates Eterm.spec from Eterm.spec.in to do + automatic version updating. + + Minor changes to the Description section in the Debian stuff. + + AUTHOR'S NOTE: None of the RPM/DEB information contained herein was + authored by me. I have no idea whether or not it will work; I rely on + the package maintainers for that. Though the authors recognize the + utility and necessity of binary distributions for the various flavors + of UNIX, we cannot in good conscious support any binary packages + ourselves, for the simple reason that we don't know them all, and thus + cannot support them all. Out of fairness, if we can't support them + all, we shouldn't support any of them. Furthermore, binary + distributions (especially when packaged by people other than the OS + distributors) tend to be quirky, and we cannot support all these + quirks ourselves. So let me make it clear once again that any RPM's + and DEB's of Eterm that may exist are supported ONLY by their + respective maintainers, NOT by the authors of Eterm. Any problems + which arise with these packaged distributions should be directed to + the package maintainer. + + With that said, we would also like to extend our thanks to the + various package maintainers, with special mention of Brian Almeida + and Sean Perry , for their + continued support and assistance with packaged Eterm distributions. + +------------------------------------------------------------------------------- +Thu Dec 31 16:15:09 CST 1998 Michael Jennings + + www.eterm.org is now alive and kicking. All pointers to + www.tcserv.com have been changed to point to the new URL. + +------------------------------------------------------------------------------- +Mon Jan 4 13:32:32 CST 1999 Michael Jennings + + Hopefully fixed a bug with backquote commands that don't return any + output. + + Hopefully fixed a bug with shell_expand() being called with a NULL. + In the process, I added some ASSERT() macros which may or may not be + portable. If they are, I will replace all assert() calls with them. + If not, I'll nuke the one I put in. :) + + There seems to be a bug in main_loop() at command.c:4668 that has been + uncovered by one person's mutt. I added some debugging stuff to help + track it down. + +------------------------------------------------------------------------------- +Mon Jan 4 14:31:06 CST 1999 Michael Jennings + + Stupid KainX error #13,471.8: Don't use macros you don't have. + +------------------------------------------------------------------------------- +Mon Jan 4 16:30:54 CST 1999 Michael Jennings + + Work-around for what is either a bug or unexpected behavior in + Enlightenment. Other WM's leave coordinate setting for negative + geometries up to the app. Enlightenment seems to do it itself. So if + Eterm is running under Enlightenment, it will not do the offsetting + itself. + + I'm curious to know if this is a bug in E or in everybody else. :) + +------------------------------------------------------------------------------- +Fri Jan 8 14:40:36 CST 1999 Michael Jennings + + Documentation updates for 0.8.8. Wheeeeee. :) + +------------------------------------------------------------------------------- +Mon Jan 11 14:30:02 CST 1999 Michael Jennings + + Use Imlib_best_color_match() for all colors we allocate so that we + coexist peacefully with Imlib, E, Netscape, et al. This should make + raster's day a little brighter.... =) + +------------------------------------------------------------------------------- +Mon Jan 11 16:12:35 CST 1999 Michael Jennings + + Fixed typos in MAIN.in files. + +------------------------------------------------------------------------------- +Mon Jan 11 16:34:41 CST 1999 Michael Jennings + + Long-awaited transparency improvement for tiled desktops. Let's hope + it doesn't break anything. + +------------------------------------------------------------------------------- +Tue Jan 12 13:17:41 CST 1999 Michael Jennings + + Integrate random background functionality into Eterm distribution. + +------------------------------------------------------------------------------- +Thu Jan 21 10:49:02 CST 1999 Michael Jennings + + Add some more verbose output when color allocation fails. + +------------------------------------------------------------------------------- +Thu Jan 21 10:55:02 CST 1999 Michael Jennings + + Yes, Virginia, there is a 0.8.9. Back to adding features. Ugh. =) + +------------------------------------------------------------------------------- +Thu Jan 21 14:17:15 CST 1999 Michael Jennings + + More for 0.8.9.... + +------------------------------------------------------------------------------- +Thu Jan 21 15:15:52 CST 1999 Michael Jennings + + Mouse wheel support. Does it work? I dunno, since I don't have a + wheeled mouse and can't test it, but it should. + +------------------------------------------------------------------------------- +Thu Jan 21 17:59:47 CST 1999 Michael Jennings + + New --version option to display compile-time #define's. Also + switched --help output to stdout instead of stderr (people were + complaining about not being able to grep it...apparently + "Eterm --help 2>&1 | grep foo" was too much work). + +------------------------------------------------------------------------------- +Thu Jan 28 11:58:26 CST 1999 Michael Jennings + + Fixed typos in MAIN files. + + Also, there's code in command.c to attempt to set the desktop on which + to open in Enlightenment. It's commented out because it doesn't work + and I'm not sure why. =} + +------------------------------------------------------------------------------- +Thu Jan 28 12:29:20 CST 1999 Michael Jennings + + An attempt at a fix, or at least to help find the bug. + +------------------------------------------------------------------------------- +Tue Feb 2 15:10:43 CST 1999 Michael Jennings + + Tinting and shading speedups (about 30%) thanks to a patch from + Michael Pearson . + +------------------------------------------------------------------------------- +Tue Feb 2 23:27:20 CST 1999 Michael Jennings + + You want scrollbars? We've got scrollbars. :) + + New --scrollbar-type option. Takes a string parameter, one of + "xterm", "next", or "motif". I'm sure we can all guess what it does. + :-) + + More work on this tomorrow, but I need sleep. + +------------------------------------------------------------------------------- +Wed Feb 3 10:43:45 CST 1999 Michael Jennings + + Fixed a bug with tiled desktop pixmaps and shading/tinting. Thanks to + t'Sade and Michael Pearson + for helping me track this down. + +------------------------------------------------------------------------------- +Wed Feb 3 12:26:20 CST 1999 Michael Jennings + + The resize-to-crash bug has *finally* been squashed once and for all, + thanks to a patch from Sebastien van Klinkenberg . + Thanks Sebastien!! + +------------------------------------------------------------------------------- +Wed Feb 3 14:55:26 CST 1999 Michael Jennings + + scrollbar_type now works in the attributes context of the MAIN file. + + New option --scrollbar-width (and scrollbar_width in the attributes + context in the MAIN file). Takes a positive integer and specifies + scrollbar width (in pixels). + + Always update the background on startup. This will help in cases of + override_redirect (-x), no window manager, or a buggy window manager + (reported with Window Maker 0.50.2). + +------------------------------------------------------------------------------- +Mon Feb 8 12:16:38 CST 1999 Michael Jennings + + Fix for a tiny hiccup. + +------------------------------------------------------------------------------- +Thu Feb 11 19:39:00 CST 1999 Michael Jennings + + Ctrl-Click behavior has changed. Ctrl+Button1 now does the old raise- + and-steal-focus thing. Ctrl+Button2 toggles the scrollbar. Ctrl+ + Button3 toggles the menubar. These behaviors can all be turned off in + src/feature.h but are on by default. + +------------------------------------------------------------------------------- +Thu Feb 11 22:32:15 CST 1999 Michael Jennings + + Added the --menubar boolean option to toggle whether or not the + menubar is visible on startup. There's also the "menubar" attribute + in the toggles section, or you can put a boolean value after the + filename for the "menu" attribute (e.g., "menu Eterm.menu off"). The + visibility of the menubar can subsequently be toggled by the escape + sequence or by Ctrl+Button3 on the term window. + +------------------------------------------------------------------------------- +Thu Feb 11 23:34:10 CST 1999 Michael Jennings + + Added support for popup scrollbars (i.e., the scrollbar goes away + when Eterm loses focus, and comes back when Eterm regains focus). + This is the --scrollbar-popup option or the "scrollbar_popup" + attribute in the toggles context. Idea courtesy Rahsheen Porter + . Thanks! + + Also, thanks to OctobrX for the menubar ideas above. + +------------------------------------------------------------------------------- +Mon Feb 15 19:38:54 CST 1999 Michael Jennings + + New -D (--desktop) option (and "desktop" attribute in the "attributes" + context) to choose what desktop to load on. NOTE: This requires a + GNOME-compliant window manager which supports the _WIN_WORKSPACE + property as defined by http://www.gnome.org/devel/gnomewm/. + + No, I will NOT use the Eterm*desktop Xrdb resource. Read the FAQ for + info on why I refuse to use Xrdb in any way, shape, or form. I would + rather wait for other WM's to reach the 21st century. (Enlightenment, + of course, is already compliant.) + + Also changed some short options for stuff that is never used, namely + the -D, -U, -B, and -A options for the pixmapped scrollbar that we + don't even have. =) -D became --desktop, and -B became + --scrollbar-type. + + Muchas gracias to raster for his assistance with + the desktop thing. + +------------------------------------------------------------------------------- +Mon Feb 15 20:00:59 CST 1999 Michael Jennings + + Work around a nasty Solaris X bug in _XFlushInt(), called by + XUnmapWindow(). If we're not unmapped after 3 seconds, call _exit(). + If _exit() isn't around, use abort(). + +------------------------------------------------------------------------------- +Tue Feb 16 11:21:59 CST 1999 Michael Jennings + + Implemented scrollbar type and width changing via an escape sequence, + namely "\e]6;10;;\a". is either "xterm", "next", + "motif", or blank. is a positive integer of reasonable value + or blank. Leaving both values blank does nothing. + +------------------------------------------------------------------------------- +Wed Feb 17 18:54:44 CST 1999 Michael Jennings + + Two whole days' worth of work here. I added bunches of escape + sequences. You can now set, configure, or toggle just about every + part of Eterm via escape sequences, and have the changes live-updated. + Look at src/command.c starting at line 6136 for the individual + sequences. There's oodles. You can change scrollbar type, width, + and location. You can change screens. You can change selection + behavior. You can even move Eterm to a new desktop. All via escape + sequences. + + Along with this, I redid all the *.menu files. They are now much + more organized. They also have support for all (if not *all*, nearly + so) the escape-code-configurable aspects of Eterm. + + Look for a GUI theme generator/configuration applet (gtk+-based) in + the near (?) future that will take advantage of this. =) + + Also, no more trying to load the CVS directory as a background pixmap. + =} + +------------------------------------------------------------------------------- +Thu Feb 18 10:26:56 CST 1999 Michael Jennings + + Patch from John Ellson . Render style was not + getting properly reset for line wrapping. His patched fixed extra + underscores...I also fixed the other stuff, including rev. video. + + Patch from Ryan Murray to add an rpath to + Esetroot when linking. + + Thanks guys! + +------------------------------------------------------------------------------- +Thu Feb 18 14:06:05 CST 1999 Michael Jennings + + Dammit. I hate stupid bugs, and this is a big one. Re-enable our + own system() call, this time one that works. If you setuid Eterm, you + NEED this fix ASAP. 'Nuff said. + +------------------------------------------------------------------------------- +Tue Mar 2 14:31:03 CST 1999 Michael Jennings + + Applied and corrected patch from Alexander Savelyev + for supporting DESTDIR and for utmp on BSDI. + + Also fixed Esetroot for systems where root visual != highest visual. + Thanks to Tomas Ogren for the patch. + +------------------------------------------------------------------------------- +Tue Mar 2 17:27:22 CST 1999 Michael Jennings + + The -C (--console) switch works again, at least on Solaris and Linux. + +------------------------------------------------------------------------------- +Wed Mar 3 09:44:21 CST 1999 Michael Jennings + + Debian info updates from Brian M. Almeida + +------------------------------------------------------------------------------- +Wed Mar 3 17:58:55 CST 1999 Michael Jennings + + Reformatted code using new script, aptly-named "reformat-code," which + calls indent. Now if only there were a few more indent options, like + one to keep the brace and the end of the function definition, and one + to force a blank line *before* the declaration section. + + Also lots of utmp.c cleanups, including one that should fix the dying + on glibc 2.1. + +------------------------------------------------------------------------------- +Wed Mar 3 18:04:49 CST 1999 Michael Jennings + + Oops, forgot some Debian files. + +------------------------------------------------------------------------------- +Thu Mar 11 14:30:53 CST 1999 Michael Jennings + + Changed the default colors from names to rgb values (failsafe), and + modified almost all of them to match colors Netscape uses. + +------------------------------------------------------------------------------- +Thu Mar 11 15:51:05 CST 1999 Michael Jennings + + Remove move-themes.in from distribution list. + +------------------------------------------------------------------------------- +Sun Mar 14 12:32:36 CST 1999 Michael Jennings + + By popular demand, the bright blue scrollbar/menubar scheme has been + nixed in favor of a red/gray scheme that blends with the ShinyMetal + Enlightenment theme. I originally chose the blue to match the window + border color in my StarTrek theme for E 0.10+. I guess it was time + for a change.... =) + +------------------------------------------------------------------------------- +Tue Mar 16 09:21:53 CST 1999 Michael Jennings + + Checkpoint commit. We're on our way to making debugging output a dual + compile- and run-time option. + +------------------------------------------------------------------------------- +Tue Mar 16 17:34:35 CST 1999 Michael Jennings + + . in config search path can cause nasty, hard-to-find weirdness. So + I nixed it. I apologize in advance if you used it, but if you did, + you probably have bigger problems. + +------------------------------------------------------------------------------- +Wed Mar 17 16:59:25 CST 1999 Michael Jennings + + Completely redid all the debugging stuff to facilitate the creation + of a run-time option for it. The option isn't there yet; that comes + next. + +------------------------------------------------------------------------------- +Thu Mar 18 14:24:48 CST 1999 Michael Jennings + + Finally fixed a long-standing font alignment problem in the menubar + when using nexus, shine, and similar fonts with 0 descent. I then + nixed the lame hackish work-around I put in awhile back so I could + ignore it for a bit longer. =) + +------------------------------------------------------------------------------- +Thu Mar 18 18:05:30 CST 1999 Michael Jennings + + Fixed another long-standing problem, this time with the placement and + appearance of the menubar arrows, especially when --border-width is + used. + +------------------------------------------------------------------------------- +Fri Mar 19 12:15:35 CST 1999 Michael Jennings + + New --debug option to vary the level of debugging output shown. Valid + values are integers 0 through DEBUG, where DEBUG is the value you set + when calling ./configure with --with-debugging=N. + +------------------------------------------------------------------------------- +Fri Mar 19 17:34:52 CST 1999 Michael Jennings + + Implemented two new escape codes. One is a simple "exit" feature than + can be used from the menubar. The other is a feature to save the + current settings to a given file. I added these two sequences to the + menubar files. The sequence for saving settings defaults to saving to + the current theme, which is the behavior most users would expect. + + WARNING: This saves *everything*, so if you have randomized + backgrounds, tints, etc., DON'T use this! They will go away! + + I haven't tested the save thing very thoroughly, so I'm not sure *all* + the current settings save properly.... =) + +------------------------------------------------------------------------------- +Fri Mar 19 18:20:28 CST 1999 Michael Jennings + + After further consideration, added a routine to create a backup of the + current MAIN file before overwriting it. The backup is named with a + timestamp, as in "MAIN.YYYYMMDD.HHMMSS", so as not to conflict with + any other backup files. + +------------------------------------------------------------------------------- +Mon Mar 22 10:23:58 CST 1999 Michael Jennings + + Changed configure.in so that the default level of debugging support + compiled in is 4 (the maximum level that does not sync X events). The + run-time default is still 0, however. + +------------------------------------------------------------------------------- +Tue Mar 23 18:16:40 CST 1999 Michael Jennings + + Whoops. Inverted one set of arrows too many. =) + +------------------------------------------------------------------------------- +Tue Mar 23 18:50:36 CST 1999 Michael Jennings + + Added support in the options macros for specifying a variable to which + the bitmask should be applied. (The variable Options had always been + used before.) This will enable the manipulation of multiple bitmask + variables via command-line options with no additional code needed. + +------------------------------------------------------------------------------- +Tue Mar 23 19:43:38 CST 1999 Michael Jennings + + Added long-awaited options to set the keypad and cursor key modes on + startup. + + --app-keypad (or the "app_keypad" boolean attribute in the keyboard + context) will start in "application keypad" mode. NOTE: The new + default is to start in normal (numeric) keypad mode. + + --app-cursor (or the "app_cursor" boolean attribute in the keyboard + context) will start in "application cursor key" mode. The default + continues to be normal cursor key mode. + +------------------------------------------------------------------------------- +Tue Mar 23 21:28:57 CST 1999 Michael Jennings + + Nuked several bugs relating to printpipe. Also enabled it by default. + + Removed the forceable addition of the '-g' flag to CFLAGS if + debugging is enabled. + +------------------------------------------------------------------------------- +Fri Mar 26 17:54:03 CST 1999 Michael Jennings + + Lots of code cleanups here, plus a bugfix for menubars. I might have + done other stuff too, I forget.... =) + +------------------------------------------------------------------------------- +Fri Mar 26 19:07:15 CST 1999 Michael Jennings + + Added another little helper app. This one is doc/Etbg, written by + Brian McFee in a fit of boredom. Thanks keeb! + +------------------------------------------------------------------------------- +Fri Mar 26 22:08:45 CST 1999 Michael Jennings + + The rewrite of the Eterm Technical Reference. It's HTML now, and is + (at least to me) much more readable. I've still got lots to add, but + it's fleshed out enough to replace the old one now. + +------------------------------------------------------------------------------- +Mon Mar 29 11:25:24 CST 1999 Michael Jennings + + Oops. Forgot to add the Kanji stuff to main.h. Thanks to Sung-Hyun + Nam for catching this. + +------------------------------------------------------------------------------- +Mon Mar 29 19:37:38 CST 1999 Michael Jennings + + This is an attempt to fix X locale support, which was broken on Linux + (XFree86?). Please (!) let me know if I broke stuff, especially you + who use KANJI. + +------------------------------------------------------------------------------- +Mon Mar 29 20:19:29 CST 1999 Michael Jennings + + Pre-emptive Kanji fix. + +------------------------------------------------------------------------------- +Tue Mar 30 13:07:05 CST 1999 Michael Jennings + + More robust font set for XIC. Should be able to handle any charset. + +------------------------------------------------------------------------------- +Tue Mar 30 17:20:50 CST 1999 Michael Jennings + + Technical reference now includes complete documentation for all the + Eterm-specific escape sequences. + +------------------------------------------------------------------------------- +Wed Mar 31 18:47:18 CST 1999 Michael Jennings + + Added support for the "ESC ] {l|I|L} string ESC \" sequences, a la + dtterm. 'l' sets the title, 'I' sets the icon pixmap filename (or the + default Eterm icon if "string" is missing), and 'L' sets the icon + name. Thanks to Mark Bowyer for pointing + these out. + + Look for more dtterm sequence support coming soon. + +------------------------------------------------------------------------------- +Wed Mar 31 19:56:07 CST 1999 Michael Jennings + + More work on the Technical Reference. + +------------------------------------------------------------------------------- +Thu Apr 1 10:25:35 CST 1999 Michael Jennings + + At this point, the initial revision of the Eterm Technical Reference + is complete. I'm looking for comments, suggestions, errata, and so + forth. :-) + +------------------------------------------------------------------------------- +Thu Apr 1 10:37:57 CST 1999 Michael Jennings + + Some rearranging. Now doc/ just contains documentation. The utility + programs have been put in utils/. + +------------------------------------------------------------------------------- +Thu Apr 1 12:06:15 CST 1999 Michael Jennings + + New, improved color grid script, Etcolors.sh. + +------------------------------------------------------------------------------- +Thu Apr 1 12:40:15 CST 1999 Michael Jennings + + New, improved menu utility, Etmenu.sh. Modified utils/Makefile.am to + install these new utilities. + +------------------------------------------------------------------------------- +Thu Apr 1 17:48:47 CST 1999 Michael Jennings + + Doh! Man page booboo. Thanks to Jim Niemira for + pointing this out to me. + +------------------------------------------------------------------------------- +Mon Apr 5 14:18:09 CDT 1999 Michael Jennings + + Support several dtterm escape sequences for window operations. + Documentation is forthcoming. + +------------------------------------------------------------------------------- +Mon Apr 5 14:41:11 CDT 1999 Michael Jennings + + Added a rule to build an HTML-ized man page in doc/. + +------------------------------------------------------------------------------- +Mon Apr 5 14:55:41 CDT 1999 Michael Jennings + + Gah! I'd love to know who the idiot was who decided to put height + before width.... >:P + +------------------------------------------------------------------------------- +Mon Apr 5 15:15:42 CDT 1999 Michael Jennings + + Documentation for new window ops sequences: + + ESC [ n [ ; n [ ... ] ] t + + n == 1: Un-iconify window + n == 2: Iconify window + n == 3: Move window. Must by followed by ;x;y + n == 4: Resize window. Must by followed by ;height;width + n == 5: Raise window + n == 6: Lower window + n == 7: Refresh window + n == 8: Resize text area. Must by followed by ;height;width, with + height and width given in characters. + n == 13: Report window position + n == 14: Report window size in pixels + n == 18: Report text area size in characters + n == 20: Report icon name + n == 21: Report window title + +------------------------------------------------------------------------------- +Tue Apr 6 13:33:18 CDT 1999 Michael Jennings + + Added support for UNIX 98 pty's under glibc 2.1, thanks to a patch + from Mikolaj Habryn . + + Also added a new option to configure. Use --without-sense-of-humor + to disable the little libKenny joke (for the humorously-challenged). + Credit to Paula Bailey for the idea. + And this :-P is me sticking my tongue out at the people who made it + necessary! :-) + +------------------------------------------------------------------------------- +Wed Apr 7 10:14:00 CDT 1999 Michael Jennings + + Fixed several bugs related to the %include directive and magic number + version checking in the config file parser, thanks to a patch from + Boris Badenov . + + Also fixed a couple oversights in Makefile.am in doc/ and utils/, + pointed out by Sung-Hyun Nam . + + Thanks guys! :-) + +------------------------------------------------------------------------------- +Thu Apr 8 13:01:02 CDT 1999 Michael Jennings + + Trying to get pty code in order. There are some problems with glibc + 2.1 systems still. I totally rearranged the pty-finding code, so I + NEED lots of testing on this stuff. Let me know if I broke/fixed + anything. + +------------------------------------------------------------------------------- +Thu Apr 8 14:43:42 CDT 1999 Michael Jennings + + Still trying to get that pty code in order.... :( + +------------------------------------------------------------------------------- +Thu Apr 8 15:34:31 CDT 1999 Michael Jennings + + And again. + +------------------------------------------------------------------------------- +Thu Apr 8 16:21:21 CDT 1999 Michael Jennings + + Now that the pty problems seem to be fixed (at least on Solaris and + Linux), let's be a little more robust with failures. + +------------------------------------------------------------------------------- +Thu Apr 8 18:11:46 CDT 1999 Michael Jennings + + Fixed some assorted bugs and problems that occur when pixmaps.list is + not present. Also fixed a bug for output files that cannot be + created. + +------------------------------------------------------------------------------- +Thu Apr 15 16:01:03 CDT 1999 Michael Jennings + + The borderless Eterm options will now make Eterm set the MWM hints + so that the window manager will render it borderless. (If the WM + does not support the MWM hints, however, Eterm will fall back on the + traditional override_redirect behavior.) I've only tested this on + Enlightenment, but it should work for other window managers too. + +------------------------------------------------------------------------------- +Thu Apr 15 17:42:35 CDT 1999 Michael Jennings + + Added the type of each variable to the help output, as well as some + additional info on how to use the command-line options. You're + welcome, llane. :-) + +------------------------------------------------------------------------------- +Fri Apr 16 18:03:26 CDT 1999 Michael Jennings + + Added a -fit option to Esetroot which scales the image to fit the + screen while maintaining its true proportion. Thanks to Remo + Strotkamp for the idea and some code. + +------------------------------------------------------------------------------- +Mon Apr 19 13:55:09 CDT 1999 Michael Jennings + + Two bugfix patches. One is for compiling on SGI IRIX, thanks to + Kimball Thurston . The other was a fix for the + recently-discovered segfault problem. Thanks yet again to + Sebastien van Klinkenberg . :-) + +------------------------------------------------------------------------------- +Mon Apr 19 19:42:54 CDT 1999 Michael Jennings + + Two more bugfixes. Eterm now installs its X error handler earlier to + catch more errors without dying. Also, another patch from Sebastien + van Klinkenberg for the segfault bug. + +------------------------------------------------------------------------------- +Tue Apr 20 15:20:00 CDT 1999 Michael Jennings + + I think this fixes all remaining menu flickering problems. I also + removed a goto while I was at it, because goto's are evil. + +------------------------------------------------------------------------------- +Tue Apr 20 16:05:50 CDT 1999 Michael Jennings + + Added a new option. --select-trailing-spaces (or the attribute + select_trailing_spaces in the toggles context of the config file) + causes Eterm to keep spaces at the end of a line as part of the + selection. The new default behavior is to remove these trailing + spaces. If you select text in mutt (or other SLang programs), you + will thank me. + + Also did some options-related cleanups in preparation for release. + +------------------------------------------------------------------------------- +Wed Apr 21 09:58:36 CDT 1999 Michael Jennings + + This should take care of the man page for the release of 0.8.9. + +------------------------------------------------------------------------------- +Wed Apr 21 10:20:33 CDT 1999 Michael Jennings + + Added support, documentation, and .menu file entries for an escape + code to toggle the select-trailing-spaces feature. + +------------------------------------------------------------------------------- +Fri Apr 23 15:55:18 CDT 1999 Michael Jennings + + Support the omission of the operator in an xterm escape sequence. + Adding support for the dtterm stuff broke this. + +------------------------------------------------------------------------------- diff --git a/Eterm.spec.in b/Eterm.spec.in new file mode 100644 index 0000000..8c1f213 --- /dev/null +++ b/Eterm.spec.in @@ -0,0 +1,79 @@ +# Note that this is NOT a relocatable package +%define ver @VERSION@ +%define rel SNAP +%define prefix /usr + +Summary: Eterm Enlightened Terminal Emulator for X Windows +Name: Eterm +Version: %ver +Release: %rel +Copyright: GPL +Group: X11/Applications +Source: ftp://ftp.enlightenment.org/pub/Eterm/Eterm-%{ver}.tar.gz +BuildRoot: /tmp/Eterm-root +Packager: technoir +URL: http://e.themes.org/ +Requires: imlib >= 1.8 + +Docdir: %{prefix}/doc + +%description +Eterm is a color vt102 terminal emulator intended as an xterm replacement for users who want a term program integrated with Enlightenment, or simply want a little more "eye candy". Eterm uses Imlib for advanced graphic abilities. + +%changelog + +* Wed Dec 30 1998 mej + +- Added spec file. Created by techn0ir + + +%prep +%setup + +%build +# Optimize that damned code all the way +if [ ! -z "`echo -n ${RPM_OPT_FLAGS} | grep pentium`" ]; then + if [ ! -z `which egcs` ]; then + CC="egcs" + else + if [ ! -z `which pgcc` ]; then + CC="pgcc" + fi + fi + CFLAGS="${RPM_OPT_FLAGS}" +else + CFLAGS="${RPM_OPT_FLAGS}" +fi +if [ ! -f configure ]; then + CFLAGS="$RPM_OPT_FLAGS" ./autogen.sh --prefix=%prefix +else + CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%prefix +fi + +make + +%install +rm -rf $RPM_BUILD_ROOT + +make prefix=$RPM_BUILD_ROOT%{prefix} install + +%clean +rm -rf $RPM_BUILD_ROOT + +%post + +%postun + +%files +%defattr(-, root, root) + +%{prefix}/bin/* +%(prefix)/doc/* +%{prefix}/lib/* +%{prefix}/share/* +%{prefix}/man/* + + +%doc COPYING +%doc ChangeLog +%doc README diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..087c5e5 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,7 @@ +# $Id$ + +AUTOMAKE_OPTIONS = foreign + +SUBDIRS = libmej src themes utils doc bg + +EXTRA_DIST = README ReleaseNotes CVS-README COPYING ChangeLog autogen.sh diff --git a/README b/README new file mode 100644 index 0000000..6885156 --- /dev/null +++ b/README @@ -0,0 +1,124 @@ +Release notes for Eterm Development Release 0.8 +----------------------------------------------- + +Software Requirements +--------------------- +- The usual X11R6 stuff +- Rasterman's Imlib and the libraries it needs. Visit + http://www.labs.redhat.com/imlib/ for more information. +- Even though Eterm works with any window manager, you just might get extra + fancies by using the Enlightenment window manager from Rasterman and + Mandrake - http://www.enlightenment.org/ for more information. Now go see + what your desktop can look like with E. :) -vendu + +Documentation to read +--------------------- +- The FAQ at http://www.eterm.org/ +- Run "Eterm -h" - you'll see the command line options. + +ATTENTION! Active Tags Warning! +-------------------------------- + +NOTE: It looks like the latest resize-crashes happen in the active tags +code. We'll try to get this fixed as soon as possible. Until then, if you +want to use tags, you may want to see the FIXME notes in screen.c for what +NULL pointer checks to remove. + +Preliminary support for active tags by Nat Friedman has been added. +Thanks, Nat :) (http://dingus.mit.edu/ for more info) + +This will definitely need more work :) Sorry if it's buggy (I'd expect it +to be >:). -vendu + +Building Eterm 0.8 +------------------ + +From the toplevel Eterm source tree directory: + ./configure + make + +With better optimization flags + + - For gcc 2.7.2.1 and older: make "CFLAGS=-O2 -fno-strength-reduce" + - For Intel-based platforms with new gcc compilers: make "CFLAGS=-O2 -m486" + - For Intel-based platforms with new gcc compilers, more optimization: + make "CFLAGS=-O3 -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2" + - For Pentium machines with egcs or pgcc: + make "CFLAGS=-O6 -mpentium -malign-loops=2 -malign-jumps=2 -malign-functions=2" + - Eterm seems to compile OK with pgcc 1.0.1. DEFINITELY use the -malign + flags, they seem to speed things up quite considerably for Pentium + processors :) + +Installing Eterm +---------------- + +After performing the build step above, run: + make install + +Standard Disclaimer +------------------- + +The authors don't take any responsibility for any damage this program +may do. We are doing this in our spare time. If you don't like this +program, don't use it. + +Eterm is based on rxvt 2.21. This development release of Eterm +has been hacked together by Tuomo Venalainen (vendu@cc.hut.fi) +and Michael Jennings (mej@tcserv.com). Thanks to Rasterman +(aka Carsten Haitzler) and Michael Kellen, as well as to all the +other people who have provided patches. Thanks to all regulars +from the #E IRC channel for helping us test Eterm. + +The development of Eterm will be continued. The sources need to be +converted into human-readable format ;-). More features will be added +as well. We'll continue cleaning up and patching the sources to make +Eterm more robust, secure and portable. + +NOTE: Support for libXpm was dropped off in DR 0.3. Imlib does a much + better job at loading and scaling the background pixmaps. And hey, + it's Eterm, ya know :-) + +Future Plans +------------ + +There will be minimal further development on this incarnation of Eterm. +We have begun Project Resurrection, which is a complete rewrite of Eterm +with a completely different philosophy of design. Please visit +http://ganja.tky.hut.fi/Resurrection/ for more information. + +Notes +----- + +- In case you need utmp support, you'll have to run Eterm "setuid root" + As root, do: "chmod 4755 Eterm" Make SURE the Eterm binary is owned by + user=root, group=root (on BSD, i think it should be group=wheel): + + 1. chown root.root Eterm + 2. (BSD) chown root.wheel Eterm + + Note that in this version, utmp support will be turned on automagically + only on Linux and FreeBSD. If you want to try it on other platforms, + add -DUTMP_SUPPORT to your compilation flags. An example: + make "CFLAGS=-O -DUTMP_SUPPORT" + +- The only fonts I know that will display ANSI art correctly are Raster's + nexus and vga; +- If you want to use colorful ANSI prompts (at least bash can show them), + make sure to make them end with a new line character ('\n')> + +Development Notes +----------------- + +- ATTENTION! Ignore warnings like this: + options.c:1454: warning: unsigned int format, long unsigned int arg (arg 3) + - type casting or otherwise screwing around can break text colors bad :) +- The sources don't compile with the GCC profiling flag (-gp) yet; + +Troubleshooting +--------------- + +- See feature.h; +- In case you have problems, try commenting out #define NDEBUG in feature.h: + /* #define NDEBUG */ + +E-n-Joy! ;-) -- vendu & mej diff --git a/ReleaseNotes b/ReleaseNotes new file mode 100644 index 0000000..a8c8d77 --- /dev/null +++ b/ReleaseNotes @@ -0,0 +1,413 @@ +Release Notes +============= + +This document includes a summary of major changes for each revision of Eterm. + +Changes made to rxvt 2.21 include +--------------------------------- + +- Better (read: working) implementation of utmp logging and added security; + needs to be tested on different platforms; +- Support for Rasterman's Imlib - used for loading and scaling the background + pixmaps; +- The command line option -pixmap now takes '@' as the delimiter between + the pixmap name and geometry. The old delimiter, ';', is NOT supported + any more. It was UGLY. Period. ; +- A new command line option, --scale or -@, was added. It will scale the background + pixmap "to fit"; to fill the whole background of the Eterm window; +- The binary was renamed to Eterm; +- Several bug/annoyance fixes. For example, fixed a problem with DEBUG_UTMP + that printed garbage when running with the debugging messages enabled. + See also #define NDEBUG in feature.h; +- Minor speedups. + +More changes for 0.3 (included in some 0.2 versions), as described by Michael: + + - Installs signal handlers that, among other things, make core + dumps secure by revoking privs and changing its umask to 077. + It also prompts for whether or not it should dump core, timing + out after 10 seconds or if it gets a SIGT(STP|TIN|TOU) + - Changes stuff that said rxvt to Eterm (most places, but I probably + missed a few). + - Fixes SVR4/utmpx compile under HP-UX 10.X + +Utmp logging support was fixed to work on FreeBSD (tested on 2.1.5 and 2.2.2) +for 0.3a. Thanks to Brian Gottlieb for doing it. + +Changes made to 0.3b include a few portability additions and fixes (HP-UX, +OSF/1) and a few changed (commented out) #define's in feature.h. + +Eterm DR-0.4x included a number of patches for bold fonts, security, +utmp logging, etc. + +Several bugs were fixed for DR 0.5. Thanks to Michael Kellen for his +Solaris patch. + +Thanks go to Steve for his help with security. + +Changes in DR-0.6: +------------------ + + - Finally got the distribution tree cleaned up to remove most all traces + of left-over rxvt SPAM(tm). For now, however, credit for most of the + docs still remains with the rxvt people. + - No more .Xdefaults support. The X Resource Manager (Xrm) code has + several known security holes which make any program making + XGetDefault() calls insecure. Since Eterm generally runs as root, + this is unacceptable. So too is reading .Xdefaults directly, which + it had been doing up until now. From DR-0.6 on, it will read (in + proper Enlightened fashion) ~/.Eterm/MAIN, which will be a very + E-like config file. See doc/MAIN.dist for a sample. + - The config files support $ variable expansion, ~ expansion, single/double + quotes, and (if #defined) backquotes. PLEASE read the accompanying + notes in src/feature.h before #defining ALLOW_BACKQUOTE_EXEC. Also + supported is the %include macro. + +Changes in DR-0.6a: +------------------- + + - Lots of bug fixes: + - The font options now accept font names starting with '-' + - Intense colors are no longer off by one. + - Scrollbar and cursor color configuration options now work properly. + - Eterm now changes back to the original directory after searching for + a config file. + - Command line options now take precedence over config file options + - -h and --help now work properly, instead of asking for a string value + - MAIN.dist.in now contains a value for cut_chars that works right when + ALLOW_BACKQUOTE_EXEC is #defined. + - The "video reverse" in MAIN.dist.in is now "video normal", because I + got sick of people saying there was a bug in Eterm that caused their + foreground and background colors to be swapped. :^) More of a + cl00bie-didn't-read-the-comments fix than a bug fix.... ;) + + - New features: + - A "magic number"-like identifier that will prevent Enlightenment config + files from being read by Eterm. See doc/MAIN.dist for details. + - Secure execution of backquote commands in config files, even if Eterm + runs setuid/setgid. + - Invalid contexts are skipped entirely with only one error message. For + example, if you don't compile in kanji support, you'll only get one + warning instead of 5 or 6. + - -H and --home-on-echo options, which will cause Eterm to jump to the + bottom of the screen when something is echoed there, if you're viewing + the scrollback buffer. There is also a new attribute "home_on_echo" in + the toggles context of the config file for this option. Thanks to Casey + for his help with this. Just in time, Casey. :) + - There is now a script which randomly chooses a pixmap from ~/.Eterm/pix + that can be executed in your config file. This script requires the + dorand program (source provided) and can be found in doc/random_pixmap.sh + +Changes in DR-0.7: +------------------ + + - Theme support. The options were changed to -t and --theme. Consult the FAQ for + more info on themes. + - Alternate config file option. This has been integrated into theme support, but + can also work independently thereof. If you don't like the name MAIN for your + config file, or want to run a certain Eterm with a different config file, use + the -X or --config-file option. + - Borderless Eterm windows. Use the -x or --borderless option to get a borderless + Eterm. Remember, you'll want to specify a geometry, since you won't be able to + move it, and something to exec. If your window manager supports it, it is + recommended that you use that functionality rather than Eterm's built-in option. + - Built-in functions. Several functions have been added to facilitate the building + of more robust config files. The currently-supported functions are: + - %appname() Returns the current application name. "Eterm-DR-0.7" as of + Eterm 0.7. + - %version() Returns the numeric version. + - %random(...) Randomly chooses one of its parameters and returns that. + - Other new options (consult the MAIN file and the --help screen for more info): + - -E and --home-on-refresh + - --pointer-color + - --scrollbar-right + - --scrollbar-floating + - -M and --menu (Menubar code is beta, so use it at your own risk) + - --term-name + - Config file support for all the above. Also: + - exec (context misc) For use with themes.... + - Some major and minor bug fixes. Nobody noticed, so I won't go into details. :) + - Support for Window Maker's "docking", thanks to CmdrTaco (Rob Malda) + (http://slashdot.org/malda/) + +Changes in DR-0.8: +------------------ + + - Several experimental features are in, like active tags, fake transparency, + and threads support. Use them at your own risk; they are unsupported and + known not to work right. We chose not to fix them since we're going to + rewrite the whole thing anyway (see http://ganja.tky.hut.fi/resurrection/) + - The FORCE_BACKSPACE feature introduce in 0.7 PL5 has been disabled for now; + you can't succesfully start Eterm as a background process with it + - The new fake transparency option, -O/trans, only works OK with a pixmap + the size of your root window / resolution. Test it with an exact image + of your root window for a neat effect :) Note that escape sequences for + changing the background pixmap will be ignored. + - Two new config file options, "trans" and "save_under", have been added. + Read themes/Eterm/MAIN for more information. The corresponding new + command line options are -O and --save-under. + - Fixed the pixmap handling code so that the menubar stuff works right now. + Thanks to Cliff Wright and keebler + for their help with finding and fixing this. + - The Xterm-style scrollbar feature (defined in src/feature.h) will actually + compile and run properly. The restriction on size to 15 pixels has + been removed as well. Thanks to Peter Norby and + Hal Black for supplying patches for + this. + - Made several changes to the configure script so that hopefully it will + work for a larger percentage of the populace. :-) Some of the changes + were suggested by John Reese and Hal Black + . + - Added MIN_ANCHOR_SIZE to src/feature.h which allows you to specify a minimum + size for the scrollbar anchor. Good for large scrollback buffers and/or + small windows. Still a mite flaky at the bottom of the scrollbar, but it + works. Credit for the idea goes to Stephen Farrell , + though the actual code was largely rewritten. + - Added CHANGE_SCROLLCOLOR_ON_FOCUS to src/feature.h which makes the + scrollbar "disappear" (i.e., become the background color) when the window + loses focus. This feature was suggested by Scott Heavner + . + - Added option --menu-text-color and config file attribute menu_text, + which allow you to change the color of the menubar text. This feature + was suggested by Scott Heavner . + - Fixed a bug for FreeBSD that only allowed Eterm to open 16 tty's at + once. Thanks to Christopher Mann for finding this + one. + - PL1 + - Fixed bug which caused scrollbar not to redraw properly + - PL2 + - Rewrote the string functions in src/misc.c to be faster. Also, support + for "\C" and "C-" to represent the Ctrl-key modifier was added. + - Added MENU_TEXT_FLOATING to src/feature.h which puts the menubar text + in the middle of the menubar buttons (which is, IMHO, where it belongs, + but apparently someone disagrees :-) -- mej). + - The pre-release stuff in RELNOTES.Eterm has been removed. + - Added an "emacs" theme for GNU Emacs or XEmacs in a text window. + - Got rid of that damned annoying preedit type error. :-) + - Added call counting for the malloc routines in libmej/mem.* thanks to + Michael Wolf (Elessar) . + - PL3 + - Changed themes/Makefile.in so that existing themes in + ${prefix}/lib/Eterm/themes do not get overwritten by the "make install" + routine. Sorry, stupid oversight on my part. :( -- mej + - New "chooser" theme. Read the comments at the top of + themes/chooser/chooser.menu for more details. :) + - New extended command "echo" in the ESC ] 10 ; set. See the chooser + theme for implementation examples. Basically, it echoes its parameters + and tacks a carriage return on the end. + - Fixed the bug introduced in PL2 which caused a border width < the shadow + width to not properly display the menubar. This was only noticeable in + the mutt theme or to users who specifically set border_width to 0 or 1. + - Eterm now sets the environment variable ETERM_THEME_ROOT to point to the + root directory of the theme it is currently using. + - PL4 + - Made several portability improvements in the configure script and its + associated files. + - Moved the active.tags file into the themes directory, which is the + location from which it is installed. + - The configure script now builds src/feature.h instead of the make process + so that it will be there before the make is done. If src/feature.h.in is + updated, however, src/feature.h will still be generated from it by a make. + - The installed Eterm binary will be Eterm-, and Eterm will + be created as a soft-link to that file in the $bindir directory. + - Eterm will now guess the install prefix (${prefix}) based on where gcc is + located, unless you give a --prefix on the command line. This keeps me + from having to use it. If it makes you have to use it, tough break. =P + - Added the --with-imlib option to configure. If you specify + --with-imlib=/some/path, the compiler will look in /some/path/include + for Imlib's header files and in /some/path/lib for Imlib itself. You can + also specify --without-imlib, which will disable pixmap support entirely. + - PL5 + - Fixed the problem with the Eterm -> Pixmap -> None menu item. + - IMPORTANT NOTE: One of the src/feature.h defines added in version 0.8 was + the MIN_ANCHOR_SIZE #define. There are KNOWN PROBLEMS with using this feature + and trying to scroll up from the bottom using Shift-Prior, the up arrow on the + scrollbar, etc. If this bothers you, COMMENT OUT that line in src/feature.h. + Fixing this problem will require a redesign of how Eterm looks at scrolling + and positioning the terminal window relative to the scrollbar and vice versa. + This may or may not happen in the current development cycle. + - Added the CTRL_CLICK_RAISE #define to src/feature.h which allows a mouse + click in the terminal window while holding the Ctrl key to raise the window + and steal keyboard focus. This is useful if you are stuck without a window + manager for one reason or another or for using Eterm as an X session manager. + - Also added an escape sequence, ESC ] 5 ; BEL, to perform the same task, and + added a menu item called "Steal Focus" to send that escape sequence. + - Fixed the "bug" that made command-line paths relative to the current theme + as well as paths in theme config files. Searching relative to the current + directory takes place after searching the directories in the "path" line + (from the config file). (I have "bug" in quotes because it wasn't really + a bug -- all paths were interpreted relative to the theme used -- but it + applied to command-line variables too, which was very confusing to some.) + +Changes in 0.8.6: +----------------- + + - For starters, we changed the naming convention. No more "DR" and "PL" stuff. + We got asked too many stupid questions. ("What's the P 15 mean?") Starting + with this release, we'll be using numbers only. The third number will still + indicate the patch level, however. + - Added support for imlib-config script supplied with Imlib 1.8 and up. This + speeds and simplifies the calculation of CFLAGS and LDFLAGS for proper + linking with Imlib. + - Fixed problems with compilation on NetBSD thanks to Clifford Wright + . + - Redid the themes to support the new pixmap mechanism I'm working on. Once + the new pixmap archive comes out, you'll want to remove your themes + directory ($prefix/lib/Eterm/themes by default) and install the themes + contained in this distribution. Get the new Eterm Backgrounds Collection + at http://www.tcserv.com/archive/E/ or a mirror near you. + - Reworked the transparency mechanism thanks to Gerald Britton + and Nat Friedman . It now takes a copy + of the root window's pixmap and uses that. It responds to all moves and + resizes by updating the pixmap. No requests for changing pixmap are + honored by a transparent Eterm (the -O or --trans options). Furthermore, + this will probably only work in Enlightenment. And for the full effect, + you'll want to run it without scrollbar/menubar and borderless (the + latter being done either through Enlightenment or with the -x option). + - Added the Esetroot program, which sets the root pixmap atom for those + who don't use Enlightenment as their window manager. There has been + mixed feedback on whether or not this program works. YMMV. + - Added a theme to demo some of the pseudo-transparency features. Use + "Eterm -t trans" to invoke it. + - Some pseudo-transparency toys are in too. The option --shade will darken + the portion of the desktop "showing through" the Eterm window. Results + in a "smoked glass" effect. This option can also be used with the + --tint option to provide a colored glass effect. See the man page for + more information. Also be sure to check out the effect of the + --scrollbar-floating option with transparency. :) + - Fixed compilation without pixmap and/or menubar support. The options + --disable-menus and --without-imlib can, when passed to the configure + script, be used to automatically disable menubar and pixmap support, + respectively. + - NEW MAN PAGE!! At long last, the man page has been updated with the new + options. Many thanks to Shaleh for doing this. + - The values "yes" and "no" can now be used as boolean values in options + and config file entries, along with 0/1, true/false, and on/off. + - Eterm now changes the color of the scrollbar when losing focus. If no + unfocused scrollbar color is specified in the config file or on the + command line, you will not notice it. See the man page and the default + config files for more info. + +Changes in 0.8.7: +----------------- + + - The old libmej is now built as a shared library as well as a static one. + Also, everything but the main() function has been moved into a library, + libEterm. Since most people use lots of Eterms at once, creating a shared + library will reduce the text segment of each Eterm significantly, saving + quite a bit of memory per Eterm. + - Removed MIN_ANCHOR_SIZE and added -a (--min-anchor-size) option. It is 0 by + default so ppl won't complain about the scroll-up "bug". + - Lots of fixes to Esetroot + - CygWin32 support. May take a little bit of effort, but it works. + - Escape sequences to toggle transparency and shading, as well as set tint, + are in. Toggling transparency works. The others don't yet. + - Newer Linux versions required a hack to open the display. + - Cleaned up privileges toggling. + - Changed the --watch-bg option to --watch-pixmap, which will hopefully make it + less tempting for people to think it has something to do with transparency. + - Added the --watch-desktop option which causes a pseudo-transparent Eterm to + monitor the desktop pixmap for changes and update accordingly. + - Several various parser cleanups. + - Transparency can now be done via Imlib rather than Xlib. It is markedly slower + but offers more configureability, like shading by percentage (--shade-pct) and + tinting masks (--tint <24-bit mask>). + - Shading now works for 8bpp pseudo-color displays. This formerly generated an + error message about the X server not setting the visual info properly. It is + not fast by any means, but that's what you get for having an 8bpp video card. + - Fixed the menubar code so that the menus aren't clipped by the window or screen + edge. + - Changed the shell_expand() function in options.c so that \' within single quotes + would insert a single quote. This differs from the shell behavior, but I prefer + it. :) + - More *BSD utmp fixes. + - Added debugging features configureable at configure-time. Also added stack + tracing on crash. + - Fixed the bug with dragging a transparent Eterm across E's desktop dragbar. It + reparents to the root window for a bit, but once you drop the window, it changes + backdrops right on cue. Also works when moving Eterm windows between desktops. + Note that this requires the use of the -W (--watch-desktop) option. + - \e[9n prints the pixmap filename in the title bar. In transparency mode, prints + transparency info to the title bar. + - New --home-on-input option which split off part of --home-on-echo + +Changes in 0.8.8: +----------------- + + - Better, more detailed man page. Now if only people would read it.... + - Shading is now done by percentage, and tinting by hex mask. See the man page for + more info. + - Lots of new options: --menubar-move, --anim, --pause, --viewport-mode, + --xterm-select, and --select-line. See man page for details. + - FORCE_BACKSPACE and FORCE_DELETE have been fixed. + - KS_DELETE (the strings associated with pressing the Delete key) is now set to ^? + by default. If you don't like that, you can set it back, or use the keysym + attribute in the config file, or whatever. + - --with-cc=prog argument to ./configure to specify an alternative compiler. The + default looks for egcs, then pgcc, then gcc, etc. + - Eterm-specific escape sequences: + Syntax: ESC ] 6 ; ; BEL + + where is: 0 toggle transparency + 1 set shade percentage + 2 set tint mask + 3 forced update of pseudo-transparent background + 30 Do not use + 40 Do not use + and is an optional argument, depending + on the particular sequence being used. It + (along with its preceeding semicolon) may or + may not be needed. + - X errors are handled more gracefully and with more helpful information. + - The --disable-stack-trace option to ./configure, whose use is obvious. + - Added an icon and associated option/attribute. + - As always, lots of bug fixes. See the ChangeLog for details. + - The -center option for Esetroot. Centers the pixmap. + - Eterm is now FHS compliant, meaning that the theme and image directories are + now under ${prefix}/share/Eterm instead of ${prefix}/lib/Eterm. See the + move-themes script included in the distribution. + +Changes in 0.8.9: +----------------- + + - Support for scrolling with mouse wheels. + - New --version switch to display compile-time configuration. + - Tinting and shading have been sped up by about 30% thanks to Michael Pearson + . + - Scrollbar type and width is now customizeable at compile-time *and* run-time. + Support for NeXT-style scrollbars has also been added. + - Three *major* bugs have been fixed. Tiled desktop images no longer cause + crashes when tinting or shading. The resize crash bug has also been squished. + The secure system() call replacement which was accidentally removed has been + added back. + - Ctrl-Button1 now grabs input focus. Ctrl-Button2 toggles the scrollbar on and + off. Ctrl-Button3 toggles the menubar on and off. NOTE: If you used to + disable the menubar by commenting out the loading of the menubar file, or + loading a fake one (e.g., '-Mx' or '-M /dev/null'), don't. Simply add "off" to + the end of the menu line (e.g., 'menu Eterm.menu off'), or use the new boolean + command-line option --menubar (e.g., '--menubar off'). Then you can toggle the + menubar using Ctrl-Button3 like you would expect. + - Popup scrollbar support has been added. + - New -D (--desktop) option for choosing a desktop to start on. Your window + manager must be GNOME-compliant for this to work. See the documentation at + http://www.gnome.org/devel/gnomewm/ for info on the _WIN_WORKSPACE property. + - The Eterm Technical Reference has been completely rewritten. It is now an HTML + document located in the doc/ directory. + - Lots and lots and lots of new escape sequences. See the Technical Reference for + details on them. + - Oodles of small bug fixes, as always. :-) + - Debugging output is now runtime configurable. Use the --debug option and supply + a number. 0 (the default) gives no debugging output. 1-5 give increasingly + more output, up to 5 (which I don't recommend using) which synchronizes X events + (and slows things down bigtime). + - You can now save your current Eterm settings from the menu. + - New --app-keypad and --app-cursor options to set the startup mode for + application/normal mode for the keypad and cursor keys. + - Three new utilities in addition to Esetroot, all of which are located in the + utils/ directory. Etbg is a tool for manipulating Eterm's background image on + the fly. Etcolors.sh demonstrates all the different combinations of your + current color settings. Etmenu.sh lets you send menu commands to Eterm's + menubar subsystem without having to type the escape codes yourself. + - Borderless Eterms now attempt to use the Window Manager to become borderless + instead of bypassing it altogether. + diff --git a/acconfig.h b/acconfig.h new file mode 100644 index 0000000..c74de7b --- /dev/null +++ b/acconfig.h @@ -0,0 +1,293 @@ +/* acconfig.h + This file is in the public domain. + + Descriptive text for the C preprocessor macros that + the distributed Autoconf macros can define. + No software package will use all of them; autoheader copies the ones + your configure.in uses into your configuration header file templates. + + The entries are in sort -df order: alphabetical, case insensitive, + ignoring punctuation (such as underscores). Although this order + can split up related entries, it makes it easier to check whether + a given entry is in the file. + + Leave the following blank line there!! Autoheader needs it. */ + + +/* Define if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +#undef _ALL_SOURCE +#endif + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define if type char is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +#undef __CHAR_UNSIGNED__ +#endif + +/* Define if the closedir function returns void instead of int. */ +#undef CLOSEDIR_VOID + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +#undef CRAY_STACKSEG_END + +/* Define for DGUX with . */ +#undef DGUX + +/* Define if you have . */ +#undef DIRENT + +/* Define to the type of elements in the array set by `getgroups'. + Usually this is either `int' or `gid_t'. */ +#undef GETGROUPS_T + +/* Define if the `getloadavg' function needs to be run setuid or setgid. */ +#undef GETLOADAVG_PRIVILEGED + +/* Define if the `getpgrp' function takes no argument. */ +#undef GETPGRP_VOID + +/* Define to `int' if doesn't define. */ +#undef gid_t + +/* Define if you have alloca, as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define if you have and it should be used (not on Ultrix). */ +#undef HAVE_ALLOCA_H + +/* Define if you don't have vprintf but do have _doprnt. */ +#undef HAVE_DOPRNT + +/* Define if your system has a working fnmatch function. */ +#undef HAVE_FNMATCH + +/* Define if your system has its own `getloadavg' function. */ +#undef HAVE_GETLOADAVG + +/* Define if you have the getmntent function. */ +#undef HAVE_GETMNTENT + +/* Define if the `long double' type works. */ +#undef HAVE_LONG_DOUBLE + +/* Define if you support file names longer than 14 characters. */ +#undef HAVE_LONG_FILE_NAMES + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if system calls automatically restart after interruption + by a signal. */ +#undef HAVE_RESTARTABLE_SYSCALLS + +/* Define if your struct stat has st_blksize. */ +#undef HAVE_ST_BLKSIZE + +/* Define if your struct stat has st_blocks. */ +#undef HAVE_ST_BLOCKS + +/* Define if you have the strcoll function and it is properly defined. */ +#undef HAVE_STRCOLL + +/* Define if your struct stat has st_rdev. */ +#undef HAVE_ST_RDEV + +/* Define if you have the strftime function. */ +#undef HAVE_STRFTIME + +/* Define if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define if your struct tm has tm_zone. */ +#undef HAVE_TM_ZONE + +/* Define if you don't have tm_zone but do have the external array + tzname. */ +#undef HAVE_TZNAME + +/* Define if you have . */ +#undef HAVE_UNISTD_H + +/* Define if utime(file, NULL) sets file's timestamp to the present. */ +#undef HAVE_UTIME_NULL + +/* Define if you have . */ +#undef HAVE_VFORK_H + +/* Define if you have the vprintf function. */ +#undef HAVE_VPRINTF + +/* Define if you have the wait3 system call. */ +#undef HAVE_WAIT3 + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + +/* Define if int is 16 bits instead of 32. */ +#undef INT_16_BITS + +/* Define if long int is 64 bits. */ +#undef LONG_64_BITS + +/* Define if major, minor, and makedev are declared in . */ +#undef MAJOR_IN_MKDEV + +/* Define if major, minor, and makedev are declared in . */ +#undef MAJOR_IN_SYSMACROS + +/* Define if on MINIX. */ +#undef _MINIX + +/* Define to `int' if doesn't define. */ +#undef mode_t + +/* Define if you don't have , but have . */ +#undef NDIR + +/* Define if you have , and doesn't declare the + mem* functions. */ +#undef NEED_MEMORY_H + +/* Define if your struct nlist has an n_un member. */ +#undef NLIST_NAME_UNION + +/* Define if you have . */ +#undef NLIST_STRUCT + +/* Define if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Define to `long' if doesn't define. */ +#undef off_t + +/* Define to `int' if doesn't define. */ +#undef pid_t + +/* Define if the system does not provide POSIX.1 features except + with this defined. */ +#undef _POSIX_1_SOURCE + +/* Define if you need to in order for stat and other things to work. */ +#undef _POSIX_SOURCE + +/* Define as the return type of signal handlers (int or void). */ +#undef RETSIGTYPE + +/* Define if the `setpgrp' function takes no argument. */ +#undef SETPGRP_VOID + +/* Define if the setvbuf function takes the buffering type as its second + argument and the buffer pointer as the third, as on System V + before release 3. */ +#undef SETVBUF_REVERSED + +/* Define to `unsigned' if doesn't define. */ +#undef size_t + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +#undef STACK_DIRECTION + +/* Define if the `S_IS*' macros in do not work properly. */ +#undef STAT_MACROS_BROKEN + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define on System V Release 4. */ +#undef SVR4 + +/* Define if you don't have , but have . */ +#undef SYSDIR + +/* Define if you don't have , but have . */ +#undef SYSNDIR + +/* Define if `sys_siglist' is declared by . */ +#undef SYS_SIGLIST_DECLARED + +/* Define if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define if your declares struct tm. */ +#undef TM_IN_SYS_TIME + +/* Define to `int' if doesn't define. */ +#undef uid_t + +/* Define for Encore UMAX. */ +#undef UMAX + +/* Define for Encore UMAX 4.3 that has + instead of . */ +#undef UMAX4_3 + +/* Define if you do not have , index, bzero, etc.. */ +#undef USG + +/* Define vfork as fork if vfork does not work. */ +#undef vfork + +/* Define if the closedir function returns void instead of int. */ +#undef VOID_CLOSEDIR + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN + +/* Define if the X Window System is missing or not being used. */ +#undef X_DISPLAY_MISSING + +/* Define if lex declares yytext as a char * by default, not a char[]. */ +#undef YYTEXT_POINTER + +/* Package name */ +#undef PACKAGE + +/* Version number */ +#undef VERSION + +/* Do we want malloc debugging? */ +#undef WITH_DMALLOC + +/* Linux xdm hack for higher kernel revs */ +#undef NEED_LINUX_HACK + +/* Do we need our own nanosleep()? */ +#undef HAVE_NANOSLEEP + +/* Debugging level */ +#undef DEBUG + +/* Stack tracing tools */ +#undef NO_STACK_TRACE +#undef DBX +#undef GDB +#undef PSTACK + +/* *BSD utmp stuff */ +#undef HAVE_LOGIN +#undef HAVE_LOGOUT + +/* Do we have the X shape extension? */ +#undef HAVE_X_SHAPE_EXT + + +/* Leave that blank line there!! Autoheader needs it. + If you're adding to this file, keep in mind: + The entries are in sort -df order: alphabetical, case insensitive, + ignoring punctuation (such as underscores). */ diff --git a/acl.m4 b/acl.m4 new file mode 100644 index 0000000..f1436c9 --- /dev/null +++ b/acl.m4 @@ -0,0 +1,249 @@ +dnl acl.m4 -- Written by Duncan Simpson +dnl Posted to BUGTRAQ on 17 June 1999 +dnl Used by encouragement. :-) + +dnl Check snprintf for overrun potential +AC_DEFUN(dps_snprintf_oflow, +[AC_MSG_CHECKING(whether snprintf ignores n) +AC_CACHE_VAL(dps_cv_snprintf_bug, +[AC_TRY_RUN( +changequote(<<, >>)dnl +<<#include + +#ifndef HAVE_SNPRINTF +#ifdef HAVE_VSNPRINTF +#include "vsnprintf.h" +#else /* not HAVE_VSNPRINTF */ +#include "vsnprintf.c" +#endif /* HAVE_VSNPRINTF */ +#endif /* HAVE_SNPRINTF */ + +int main(void) +{ +char ovbuf[7]; +int i; +for (i=0; i<7; i++) ovbuf[i]='x'; +snprintf(ovbuf, 4,"foo%s", "bar"); +if (ovbuf[5]!='x') exit(1); +snprintf(ovbuf, 4,"foo%d", 666); +if (ovbuf[5]!='x') exit(1); +exit(0); +} >> +changequote([, ]), dps_cv_snprintf_bug=0, dps_cv_snprintf_bug=1, +dps_cv_snprintf_bug=2)]) +if test $dps_cv_snprintf_bug -eq 0; then + AC_MSG_RESULT([no, snprintf is ok]) +else if test $dps_cv_snprint_bug -eq 1; then + AC_MSG_RESULT([yes, snprintf is broken]) + AC_DEFINE(HAVE_SNPRINTF_BUG,1) +else + AC_MSG_RESULT([unknown, assuming yes]) + AC_DEFINE(HAVE_SNPRINTF_BUG,1) +fi; fi]) + +dnl Check vsnprintf for overrun potential +AC_DEFUN(dps_vsnprintf_oflow, +[AC_MSG_CHECKING(whether vsnprintf ignores n) +AC_CACHE_VAL(dps_cv_vsnprintf_bug, +[AC_TRY_RUN( +changequote(<<, >>)dnl +<<#include +#include + +#ifndef HAVE_VSNPRINTF +#include "vsnprintf.c" +#endif /* HAVE_VSNPRINTF */ + +int prnt(char *s, const char *fmt, ...) +{ + va_list argp; + va_start(argp, fmt); + vsnprintf(s, 4, fmt, argp); + va_end(argp); +} + +int main(void) +{ + char ovbuf[7]; + int i; + for (i=0; i<7; i++) ovbuf[i]='x'; + prnt(ovbuf, "foo%s", "bar"); + if (ovbuf[5]!='x') exit(1); + prnt(ovbuf, "foo%d", 666); + if (ovbuf[5]!='x') exit(1); + exit(0); +} >> +changequote([, ]), dps_cv_vsnprintf_bug=0, dps_cv_vsnprintf_bug=1, +dps_cv_vsnprintf_bug=2)]) + +if test $dps_cv_vsnprintf_bug -eq 0; then + AC_MSG_RESULT([no, vsnprintf is ok]) +else if test $dps_cv_vsnprint_bug -eq 1; then + AC_MSG_RESULT([yes, vsnprintf is broken]) + AC_DEFINE(HAVE_VSNPRINTF_BUG,1) +else + AC_MSG_RESULT([unknown, assuming yes]) + AC_DEFINE(HAVE_VSNPRINTF_BUG,1) +fi; fi]) + +dnl open and symlink interaction bug test +AC_DEFUN(dps_symlink_open_bug, +[AC_MSG_CHECKING(security of interaction between symlink and open) +AC_CACHE_VAL(dps_cv_symlink_open_bug, +[mkdir conftest.d +AC_TRY_RUN( +changequote(<<, >>)dnl +<<#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#else +extern int errno; +#endif + +int main(void) +{ + int fd; + if (chdir("conftest.d")!=0) + exit(1); + if (symlink("foo","bar")!=0) + exit(1); + if ((fd=open("bar", O_CREAT | O_EXCL | O_WRONLY, 0700))==0) + { + write(fd, "If the symlink was to .rhosts you would be unhappy", 50); + close(fd); + exit(1); + } + if (errno!=EEXIST) + exit(1); + exit(0); +} >> +changequote([, ]), cps_cv_symlink_open_bug=0, +[if test -r conftest.d/foo; then + cps_cv_symlink_open_bug=2 +else + cps_cv_symlink_open_bug=1 +fi], cps_cv_symlink_open_buf=3) +rm -rf conftest.d]) +case "$cps_cv_symlink_open_bug" in +0) AC_MSG_RESULT(secure) ;; +1) AC_MSG_RESULT(errno wrong but ok) + AC_DEFINE(HAVE_SYMLINK_OPEN_ERRNO_BUG) ;; +2) AC_MSG_RESULT(insecure) + AC_DEFINE(HAVE_SYMLINK_OPEN_SECURITY_HOLE) + AC_DEFINE(HAVE_SYMLINK_OPEN_ERRNO_BUG) ;; +3) AC_MSG_RESULT(assuming insecure) + AC_DEFINE(HAVE_SYMLINK_OPEN_SECURITY_HOLE) + AC_DEFINE(HAVE_SYMLINK_OPEN_ERRNO_BUG) ;; +*) AC_MSG_RESULT($cps_cv_symlink_open_bug) + AC_MSG_ERROR(Impossible value of cps_cv_symlink_open_bug) ;; +esac]) + +dnl Check to RLIMIT_NPROC resource limit +AC_DEFUN(dps_rlimit_nproc, +[AC_MSG_CHECKING(for working RLIMIT_NPROC resource limit) +AC_CACHE_VAL(dps_cv_rlimit_nproc, +[AC_TRY_RUN( +changequote(<<, >>)dnl +<< +#ifndef HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ +#ifndef HAVE_SIGNAL_H +#include +#endif /* HAVE_SIGNAL_H */ +#ifdef HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif /* HAVE_SYS_RESOURCE_H */ + +int main(void) +{ +#ifdef RLIMIT_NPROC + static const struct rlimit pid_lim={RLIMIT_NPROC, 1}; + pid_t f; + + signal(SIGCHLD, SIG_IGN); + setrlimit(RLIMIT_NPROC, (struct rlimit *) &pid_lim); + if ((f=fork())==0) + exit(0); + if (f==-1) + exit(0); /* The fork() failed (the right thing) */ +#endif + exit(1); +} >> +changequote([, ]), cps_cv_rlimit_nproc=0, cps_cv_rlimit_nproc=1, +cps_cv_rlimit_nproc=2)]) +if test $cps_cv_rlimit_nproc -eq 0; then + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_RLIMIT_NPROC,1) +else if test $cps_cv_rlimit_nproc -eq 1; then + AC_MSG_RESULT([no]) +else + AC_MSG_RESULT([unknown, assuming none]) +fi; fi]) + +dnl Check to RLIMIT_MEMLOCK resource limit +AC_DEFUN(cps_rlimit_memlock, +[AC_MSG_CHECKING(for RLIMIT_MEMLOCK resource limit) +AC_CACHE_VAL(cps_cv_rlimit_memlock, +[AC_TRY_RUN( +changequote(<<, >>)dnl +<< +#ifndef HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ +#ifndef HAVE_SIGNAL_H +#include +#endif /* HAVE_SIGNAL_H */ +#ifdef HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif /* HAVE_SYS_RESOURCE_H */ +#ifdef HAVE_SYS_MMAN +#include +#endif /* HAVE_SYS_MMAN */ +#ifdef HAVE_ERRNO_H +#include +#endif /* HAVE_ERRNO_H */ + +int main(void) +{ +#ifdef RLIMIT_MEMLOCK + static const struct rlimit mlock_lim={RLIMIT_MEMLOCK, 0}; + void *memory; + + if (setrlimit(RLIMIT_MEMLOCK, (struct rlimit *) &mlock_lim)!=-1) + exit(0); +#endif +exit(1); +} >> +changequote([, ]), cps_cv_rlimit_memlock=0, cps_cv_rlimit_memlock=1, +cps_cv_rlimit_memlock=2)]) +if test $cps_cv_rlimit_memlock -eq 0; then + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_RLIMIT_MEMLOCK,1) +else if test $cps_cv_rlimit_memlock -eq 1; then + AC_MSG_RESULT([no]) +else + AC_MSG_RESULT([unknown, assuming none]) +fi; fi]) + diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..c2583dc --- /dev/null +++ b/autogen.sh @@ -0,0 +1,52 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. +# $Id$ + +DIE=0 + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have autoconf installed to compile Eterm." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(libtool --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have libtool installed to compile Eterm." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(automake --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have automake installed to compile Eterm." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +libtoolize --copy --force +aclocal $ACLOCAL_FLAGS +automake --add-missing +autoconf +autoheader + +if [ -x config.status -a -z "$*" ]; then + ./config.status --recheck +else + if test -z "$*"; then + echo "I am going to run ./configure with no arguments - if you wish " + echo "to pass any to it, please specify them on the $0 command line." + echo "If you do not wish to run ./configure, press Ctrl-C now." + trap 'echo "configure aborted" ; exit 0' 1 2 15 + sleep 1 + fi + ./configure "$@" +fi diff --git a/bg/Makefile.am b/bg/Makefile.am new file mode 100644 index 0000000..70a50dd --- /dev/null +++ b/bg/Makefile.am @@ -0,0 +1,42 @@ +# $Id$ + +DIRS = tile scale +EXTRA_DIST = tile/014.png tile/circuit.png tile/backwave.jpg tile/button1.jpg tile/button5.jpg \ + tile/nebula.jpg scale/fourthday.jpg scale/gaia.jpg scale/galleon.jpg scale/night_of_the_dragon.jpg \ + README.backgrounds +pixmapdir = $(pkgdatadir)/pix +themedir = $(pkgdatadir)/themes + +all: Makefile + @echo "*** Generating pixmaps.list file from images in tile/ and scale/..." + @true > pixmaps.list + @cd tile ; \ + for i in `ls -1 | grep -v CVS | grep -v \.cvsignore` ; do \ + echo '" 0 0 '$$i'"' >> ../pixmaps.list ; \ + done ; \ + cd .. ; \ + cd scale ; \ + for i in `ls -1 | grep -v CVS | grep -v \.cvsignore` ; do \ + echo '"-1 -1 '$$i'"' >> ../pixmaps.list ; \ + done + +install-data-hook: + @if test ! -f pixmaps.list ; then $(MAKE) all ; fi + $(mkinstalldirs) $(DESTDIR)$(pixmapdir) + @for j in $(DIRS) ; do echo "Installing pixmaps in $$j" ; cd $$j ; \ + for i in `ls -1 | grep -v CVS | grep -v \.cvsignore` ; do \ + echo $(INSTALL_DATA) $$i $(DESTDIR)${pixmapdir} ; \ + $(INSTALL_DATA) $$i $(DESTDIR)${pixmapdir} ; \ + done ; cd .. ; \ + done + @if test -f $(DESTDIR)${pixmapdir}/pixmaps.list ; then \ + $(CP) -p $(DESTDIR)${pixmapdir}/pixmaps.list $(DESTDIR)${pixmapdir}/pixmaps.list.old ; \ + echo "WARNING: Backup of existing pixmaps.list created." ; \ + fi + $(INSTALL_DATA) pixmaps.list $(DESTDIR)${pixmapdir} + @for i in `ls -1d $(DESTDIR)${themedir}/*` ; do \ + if test $$i != "." -a $$i != ".." -a ! -f $$i/pixmaps.list ; then \ + echo "$(LN_S) ../../pix/pixmaps.list $$i/pixmaps.list" ; \ + $(LN_S) ../../pix/pixmaps.list $$i/pixmaps.list ; \ + fi ; \ + done diff --git a/bg/Makefile.in b/bg/Makefile.in new file mode 100644 index 0000000..84a9803 --- /dev/null +++ b/bg/Makefile.in @@ -0,0 +1,252 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# $Id$ + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +AR = @AR@ +AS = @AS@ +AUTHORS = @AUTHORS@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CHMOD = @CHMOD@ +CP = @CP@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CTAGS = @CTAGS@ +DATE = @DATE@ +DBX = @DBX@ +DIST_ROOT = @DIST_ROOT@ +DLLTOOL = @DLLTOOL@ +EGCS = @EGCS@ +FEATURE_CMD = @FEATURE_CMD@ +GDB = @GDB@ +GRLIBS = @GRLIBS@ +IMLIB_CONFIG = @IMLIB_CONFIG@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR = @MKDIR@ +MV = @MV@ +NM = @NM@ +OBJDUMP = @OBJDUMP@ +PACKAGE = @PACKAGE@ +PGCC = @PGCC@ +PSTACK = @PSTACK@ +RANLIB = @RANLIB@ +RM = @RM@ +SED = @SED@ +TAR = @TAR@ +THREADLIBS = @THREADLIBS@ +VERSION = @VERSION@ + +DIRS = tile scale +EXTRA_DIST = tile/014.png tile/circuit.png tile/backwave.jpg tile/button1.jpg tile/button5.jpg tile/nebula.jpg scale/fourthday.jpg scale/gaia.jpg scale/galleon.jpg scale/night_of_the_dragon.jpg README.backgrounds + +pixmapdir = $(pkgdatadir)/pix +themedir = $(pkgdatadir)/themes +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu bg/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = bg + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu bg/Makefile + $(mkinstalldirs) $(distdir)/scale $(distdir)/tile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-generic clean-am + -rm -f libtool + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: tags distdir info-am info dvi-am dvi check check-am \ +installcheck-am installcheck install-exec-am install-exec \ +install-data-am install-data install-am install uninstall-am uninstall \ +all-redirect all-am all installdirs mostlyclean-generic \ +distclean-generic clean-generic maintainer-clean-generic clean \ +mostlyclean distclean maintainer-clean + + +all: Makefile + @echo "*** Generating pixmaps.list file from images in tile/ and scale/..." + @true > pixmaps.list + @cd tile ; \ + for i in `ls -1 | grep -v CVS | grep -v \.cvsignore` ; do \ + echo '" 0 0 '$$i'"' >> ../pixmaps.list ; \ + done ; \ + cd .. ; \ + cd scale ; \ + for i in `ls -1 | grep -v CVS | grep -v \.cvsignore` ; do \ + echo '"-1 -1 '$$i'"' >> ../pixmaps.list ; \ + done + +install-data-hook: + @if test ! -f pixmaps.list ; then $(MAKE) all ; fi + $(mkinstalldirs) $(DESTDIR)$(pixmapdir) + @for j in $(DIRS) ; do echo "Installing pixmaps in $$j" ; cd $$j ; \ + for i in `ls -1 | grep -v CVS | grep -v \.cvsignore` ; do \ + echo $(INSTALL_DATA) $$i $(DESTDIR)${pixmapdir} ; \ + $(INSTALL_DATA) $$i $(DESTDIR)${pixmapdir} ; \ + done ; cd .. ; \ + done + @if test -f $(DESTDIR)${pixmapdir}/pixmaps.list ; then \ + $(CP) -p $(DESTDIR)${pixmapdir}/pixmaps.list $(DESTDIR)${pixmapdir}/pixmaps.list.old ; \ + echo "WARNING: Backup of existing pixmaps.list created." ; \ + fi + $(INSTALL_DATA) pixmaps.list $(DESTDIR)${pixmapdir} + @for i in `ls -1d $(DESTDIR)${themedir}/*` ; do \ + if test $$i != "." -a $$i != ".." -a ! -f $$i/pixmaps.list ; then \ + echo "$(LN_S) ../../pix/pixmaps.list $$i/pixmaps.list" ; \ + $(LN_S) ../../pix/pixmaps.list $$i/pixmaps.list ; \ + fi ; \ + done + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bg/README.backgrounds b/bg/README.backgrounds new file mode 100644 index 0000000..b688181 --- /dev/null +++ b/bg/README.backgrounds @@ -0,0 +1,34 @@ +Eterm Background Archive +======================== + +This is the official () collection of Eterm background images. The only +things that make it official are (1) I put it together, and (2) the default +themes that come with Eterm are designed to work with these images. NONE of +these images are original work by either of the Eterm authors; they have all +been collected from various sites on the web. As far as I know, they are all +freely available for use. + +However, should any person who can provide proof of ownership of any of these +pictures object to their inclusion, they will be IMMEDIATELY withdrawn. No +copyright infringement is intended. Inclusion here should be taken as a +compliment. :-) + +Installation +------------ + +Now that this is included with the Eterm distribution, these images will be +cataloged and installed as part of the normal Eterm build process. + +Changes +------- + +Adding pictures to the archive is equally simple. If the picture is intended +to be tiled, copy it into the "tile" directory. If it is intended to be scaled +(i.e., non-tileable pictures), copy it into the "scale" directory. Then re-run +"make" and "make install". That's it! The images will automatically be +included in Eterm's random rotation. + +Removing pictures is done the same way. Simply remove them from whichever +directory they reside in, then re-run "make" and "make install". You will need +to manually remove the file from the pixmap directory if you so desire; these +instructions only pertain to changing the standard rotation. diff --git a/bg/scale/.cvsignore b/bg/scale/.cvsignore new file mode 100644 index 0000000..38dfb3b --- /dev/null +++ b/bg/scale/.cvsignore @@ -0,0 +1,4 @@ +*.jpg +*.png +*.gif +*.list diff --git a/bg/tile/.cvsignore b/bg/tile/.cvsignore new file mode 100644 index 0000000..38dfb3b --- /dev/null +++ b/bg/tile/.cvsignore @@ -0,0 +1,4 @@ +*.jpg +*.png +*.gif +*.list diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..dd9a6a8 --- /dev/null +++ b/configure.in @@ -0,0 +1,387 @@ +dnl# $Id$ + +AC_INIT(src/feature.h.in) +AM_INIT_AUTOMAKE(Eterm, 0.8.9) + +dnl# Set some basic variables +DATE="21 January 1999" +AC_SUBST(DATE) +AUTHORS="Tuomo Venalainen (vendu@cc.hut.fi) and Michael Jennings (mej@tcserv.com)" +AC_SUBST(AUTHORS) + +dnl# Supply default CFLAGS, if not specified by `CFLAGS=flags ./configure' +if test ! -z "${CFLAGS}" -o ! -z "${CCOPTS}"; then + CFLAGS_GIVEN=1 +else + CFLAGS_GIVEN=0 +fi + +if test -z "${CFLAGS}"; then + if test -z "${CCOPTS}"; then + CCOPTS="-O" + fi + CFLAGS="$CCOPTS" +fi + +AC_ARG_WITH(cc, [ --with-cc=compiler force Eterm to build with a particular compiler (like pgcc, egcs, etc.)], + CC=$withval, + if test -z "$CC"; then + CC=check + fi +) + +if test "$CC" = "check"; then + dnl# Check for Pentium compilers + AC_CHECK_PROG(EGCS, egcs, egcs) + AC_CHECK_PROG(PGCC, pgcc, pgcc) + + if test ! -z "$EGCS"; then + CC=$EGCS + elif test ! -z "$PGCC"; then + CC=$PGCC + else + unset CC + fi +fi + +AC_PROG_CC +AC_PROG_CPP + +dnl# These must be run after AC_PROG_CC but before any other macros that use +dnl# the C compiler +AC_AIX +AC_ISC_POSIX +AC_MINIX + +dnl# At least make the attempt to support CygWin32 +AC_CYGWIN +AC_ARG_PROGRAM + +AM_PROG_LIBTOOL + +dnl# Where are we? +AC_MSG_CHECKING(for distribution root) +DIST_ROOT=`pwd` +AC_SUBST(DIST_ROOT) +AC_MSG_RESULT($DIST_ROOT) + +AC_GCC_TRADITIONAL + +dnl # If using gcc, use -O2. If -g works with it, use that too +if test "${CFLAGS_GIVEN}" -ne 1; then + if test "$GCC" = "yes"; then + if test "$ac_cv_prog_cc_g" = "yes"; then + CCOPTS='-g -O2' + else + CCOPTS='-O2' + fi + CFLAGS="$CCOPTS" + fi +fi + +AC_PROG_INSTALL + +dnl# Check for host system type +AC_CANONICAL_HOST + +dnl# Check the sanity of what we've done so far +AM_SANITY_CHECK + +dnl# Most people don't want the developer-only clutter +AM_MAINTAINER_MODE + +dnl# If it's there, what the hell? +AM_WITH_DMALLOC + +dnl# Look for needed programs +AC_CHECK_PROG(SED, sed, sed, false) +AC_CHECK_PROG(RM, rm, rm, true) +AC_CHECK_PROG(CP, cp, cp, false) +AC_CHECK_PROG(CHMOD, chmod, chmod, true) +AC_CHECK_PROG(TAR, tar, tar, tar) +AC_CHECK_PROG(MKDIR, mkdir, mkdir, false) +AC_CHECK_PROG(CTAGS, ctags, ctags, true) +AC_CHECK_PROG(AR, ar, ar, false) +AC_CHECK_PROG(MV, mv, mv, true) +AC_LN_S + +AC_CHECK_SIZEOF(int, 4) +AC_CHECK_SIZEOF(long, 4) +AC_CHECK_SIZEOF(long long, 8) +dnl AC_C_BIGENDIAN + +AC_C_CONST +AC_C_INLINE +AC_PATH_XTRA + +if test "$ac_cv_lib_socket_connect" = "yes" ; then + SUBLIBS="-lsocket" +fi +if test "$ac_cv_lib_nsl_gethostbyname" = "yes" ; then + SUBLIBS="$SUBLIBS -lnsl" +fi + +dnl# Checks for header files. +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS(fcntl.h termios.h \ +sys/ioctl.h sys/select.h sys/time.h \ +sys/sockio.h sys/byteorder.h \ +utmpx.h unistd.h bsd/signal.h regex.h \ +regexp.h stdarg.h) +AC_HEADER_TIME + +dnl# Missing typedefs and replacements +AC_TYPE_MODE_T +AC_CHECK_TYPE(off_t, long) +AC_TYPE_PID_T +AC_TYPE_UID_T + +dnl# Checks for library functions. +AC_TYPE_SIGNAL +AC_CHECK_FUNCS(atexit _exit unsetenv setutent seteuid memmove putenv strsep setresuid setresgid memmem usleep snprintf) + +dnl# Check for the need for -lutil on BSD systems +AC_CHECK_FUNC(login, + AC_DEFINE(HAVE_LOGIN) +, AC_CHECK_LIB(util, login, LIBS="$LIBS -lutil" ; + AC_DEFINE(HAVE_LOGIN) +)) +AC_CHECK_FUNC(logout, + AC_DEFINE(HAVE_LOGOUT) +, AC_CHECK_LIB(util, logout, LIBS="$LIBS -lutil" ; + AC_DEFINE(HAVE_LOGOUT) +)) +AC_CHECK_FUNC(getpwuid, , AC_CHECK_LIB(sun, getpwuid, LIBS="$LIBS -lsun")) + +dnl# Check for POSIX threads library +dnl# Don't comment this back in before multithreading actually works, +dnl# so people don't need thread-safe X libs to be able to run unthreaded +dnl# Eterm :) -vendu +#AC_CHECK_LIB(pthread, pthread_create, CFLAGS="$CFLAGS -D_REENTRANT"; +# THREADLIBS="-lpthread", , +# -D_REENTRANT -L/usr/lib -L/lib -L/usr/local/lib) + +dnl# Did they want debugging? +AC_MSG_CHECKING(for debugging level) +AC_ARG_WITH(debugging, [ --with-debugging[=num] enable debugging output, num is an optional level], + if test "$withval" = "yes"; then + withval=4 + else + : + fi + if test "$withval" != "no"; then + echo "$withval" + AC_DEFINE_UNQUOTED(DEBUG, $withval) + else + echo "no debugging" + fi, echo "4" + AC_DEFINE_UNQUOTED(DEBUG, 4) +) + +dnl# Check for support for menus +AC_MSG_CHECKING(whether or not to enable menubar support) +AC_ARG_ENABLE(menus, [ --disable-menus disable support for menubars (support enabled by default)], + if test "$enableval" != "no"; then + echo "yes" ; MENUSED=""; + else echo "no" ; MENUSED='s/define MENUBAR_MAX .*/define MENUBAR_MAX 0/g'; + fi, echo "yes" ; MENUSED="") + +dnl# Check for graphics libraries. +dnl# Force Imlib flags - see below. -vendu +AC_MSG_CHECKING(whether or not to enable pixmap support) +AC_ARG_WITH(imlib, +[ --with-imlib[=DIR] compile with Imlib support (Imlib residing in DIR/lib) [default] + --without-imlib compile with pixmap support disabled], + if test "$withval" != "no"; then + echo "yes" ; CFLAGS="$CFLAGS -I${withval}/include -L${withval}/lib"; + GRLIBS="-lImlib" ; PIXMAPSED=""; + else echo "no" ; PIXMAPSED='s/define PIXMAP_SUPPORT/undef PIXMAP_SUPPORT/g'; + GRLIBS=""; + fi, echo "yes" ; GRLIBS="-lImlib" ; PIXMAPSED="") + +AC_CHECK_LIB(X11, XOpenDisplay, X_LIBS="$X_LIBS -lX11", [ +echo "ERROR: You need libX11 to build Eterm. Verify that you have libX11.a or"; +echo " libX11.so installed and that it is located in the X libraries"; +echo " directory shown above. If it is in a different directory, try using"; +echo " the --x-libraries parameter to configure."; + AC_MSG_ERROR([Fatal: libX11 not found.])], $X_LIBS $SUBLIBS) + +AC_CHECK_LIB(Xext, XextAddDisplay, X_LIBS="-lXext $X_LIBS", [ +echo "ERROR: You need libXext to build Eterm. Verify that you have libXext.a or"; +echo " libXext.so installed and that it is located in the X libraries"; +echo " directory shown above. If it is in a different directory, try using"; +echo " the --x-libraries parameter to configure."; + AC_MSG_ERROR([Fatal: libXext not found.])], $X_LIBS $SUBLIBS) + +AC_CHECK_LIB(Xext, XShapeQueryExtension, AC_DEFINE(HAVE_X_SHAPE_EXT), , $X_LIBS $SUBLIBS) + +if test -z "$PIXMAPSED"; then + + AC_CHECK_PROG(IMLIB_CONFIG, imlib-config, imlib-config, no) + + if test "$IMLIB_CONFIG" != "no"; then + + if test "$prefix" = "NONE"; then + AC_MSG_CHECKING(imlib-config for prefix) + prefix="`$IMLIB_CONFIG --prefix`" + AC_MSG_RESULT($prefix) + fi + + AC_MSG_CHECKING(imlib-config for the value of CFLAGS) + CFLAGS="$CFLAGS `$IMLIB_CONFIG --cflags`" + AC_MSG_RESULT($CFLAGS) + + AC_MSG_CHECKING(imlib-config for the value of GRLIBS) + GRLIBS="$GRLIBS `$IMLIB_CONFIG --libs`" + AC_MSG_RESULT($GRLIBS) + + SAVE_LIBS="$LIBS" + LIBS="$GRLIBS" + + AC_MSG_CHECKING(the sanity of new compile/link flags) + AC_TRY_LINK(, , echo "yes", echo "no" ; IMLIB_CONFIG="no" ; + AC_WARN(Compile/link failed. Reverting to manual method.) + ) + + LIBS="$SAVE_LIBS" + + fi + + if test "$IMLIB_CONFIG" = "no"; then + + AC_CHECK_LIB(png, png_get_valid, GRLIBS="$GRLIBS -lpng -lz -lm", , + $SUBLIBS $X_LIBS -lz -lm) + AC_CHECK_LIB(jpeg, jpeg_read_scanlines, GRLIBS="$GRLIBS -ljpeg", , + $SUBLIBS $X_LIBS) + AC_CHECK_LIB(tiff, TIFFOpen, GRLIBS="$GRLIBS -ltiff", , + $SUBLIBS $X_LIBS -lm) + AC_CHECK_LIB(gif, DGifOpenFileName, GRLIBS="$GRLIBS -lgif", , + $SUBLIBS $X_LIBS) + AC_CHECK_LIB(ungif, DGifOpenFileName, GRLIBS="$GRLIBS -lungif", , + $SUBLIBS $X_LIBS) + AC_CHECK_LIB(Imlib, Imlib_init, , [ + echo "WARNING: Imlib was not found or did not correctly link."; + echo " Please check config.log to see what the error was."; + echo " I will attempt to continue, but things may go wrong."; + AC_MSG_WARN([WARNING: libImlib not found. Attempting to continue anyway.])], + $GRLIBS $SUBLIBS $X_LIBS) + + fi + +fi + +AC_PREFIX(Eterm) +AC_PREFIX(gcc) + +dnl Stack Tracing toys +AC_ARG_ENABLE(stack-trace, [ --disable-stack-trace disable stack trace on abnormal termination], + if test "$enableval" = "no"; then + AC_DEFINE(NO_STACK_TRACE) + NO_STACK_TRACE=1 + fi +) + +if test "$NO_STACK_TRACE" != "1"; then + AC_PATH_PROG(DBX, dbx, no) + if test "$DBX" != "no"; then + AC_DEFINE_UNQUOTED(DBX, "$DBX") + fi + AC_PATH_PROG(GDB, gdb, no) + if test "$GDB" != "no"; then + AC_DEFINE_UNQUOTED(GDB, "$GDB") + fi + AC_PATH_PROG(PSTACK, pstack, no, $PATH:/usr/proc/bin:/usr/sbin) + if test "$PSTACK" != "no"; then + AC_DEFINE_UNQUOTED(PSTACK, "$PSTACK") + fi + AC_CHECK_LIB(cl, U_STACK_TRACE, LIBS="$LIBS -lcl") +fi + +AC_MSG_CHECKING(for Linux 2.1 or higher) +OS_NAME=`uname -s` +if test "$OS_NAME" = "Linux"; then + OS_REV=`uname -r` + OS_MAJOR=`echo $OS_REV | cut -d. -f1` + OS_MINOR=`echo $OS_REV | cut -d. -f2` + if test "$OS_MAJOR" -ge "2" -a "$OS_MINOR" -ge "1"; then + AC_MSG_RESULT(yes) + AC_DEFINE(NEED_LINUX_HACK) + else + AC_MSG_RESULT(no) + fi +else + AC_MSG_RESULT(no) +fi + +dnl# Enable/disable humor +AC_ARG_WITH(sense-of-humor, [ --without-sense-of-humor Specify this if you have no sense of humor], + if test "$withval" = "no"; then + HUMOR=none + fi) + +if test -z "$HUMOR"; then +AC_CHECK_LIB(Kenny, life_signs, , [ + echo " Oh my god, they killed Kenny! You bastards!" +]) +fi + +CFLAGS=${CFLAGS--O} +LDFLAGS=${LDFLAGS--O} + +CPPFLAGS="$CPPFLAGS" +AC_SUBST(CC) +AC_SUBST(CFLAGS) +AC_SUBST(CPPFLAGS) +AC_SUBST(LDFLAGS) +AC_SUBST(LIBS) +AC_SUBST(THREADLIBS) +AC_SUBST(GRLIBS) + +basedir=. +FEATURE_CMD="$SED -e \"s%@PREFIX@%${prefix}%g\" -e \"s%@DATADIR@%${datadir}%g\" -e \"$PIXMAPSED\" -e \"$MENUSED\" "'${DIST_ROOT}'"/src/feature.h.in > "'${DIST_ROOT}'"/src/feature.h" +AC_SUBST(FEATURE_CMD) + +dnl# common parts of the Makefile +dnl# MCOMMON=./Make.common +dnl# AC_SUBST_FILE(MCOMMON) + +AM_CONFIG_HEADER(config.h) + +AC_OUTPUT(Makefile \ +bg/Makefile \ +doc/Makefile \ +utils/Makefile \ +libmej/Makefile \ +src/Makefile \ +src/graphics/Makefile \ +themes/Makefile \ +Eterm.spec \ +) + +dnl If we're not building with Imlib support, don't build Esetroot +if test -n "$PIXMAPSED"; then + sed -e 's/^bin_PROGRAMS.*$//g' doc/Makefile > doc/Makefile.new + mv doc/Makefile.new doc/Makefile +fi + +echo "creating src/feature.h" +eval ${FEATURE_CMD}.new +if cmp -s ${DIST_ROOT}/src/feature.h.new ${DIST_ROOT}/src/feature.h 2>/dev/null ; then + echo "feature.h is unchanged" + rm -f ${DIST_ROOT}/src/feature.h.new +else + mv ${DIST_ROOT}/src/feature.h.new ${DIST_ROOT}/src/feature.h +fi + +echo " +Configuration: + + Source code location: ${srcdir} + Compiler: ${CC} ${CFLAGS} + Host System Type: ${host} + Graphics libraries: ${GRLIBS} + X Windows libs/paths: ${X_LIBS} + Install path: ${prefix} + + See src/feature.h for further configuration information." +echo diff --git a/debian/README.debian b/debian/README.debian new file mode 100644 index 0000000..36f463b --- /dev/null +++ b/debian/README.debian @@ -0,0 +1,12 @@ +eterm for DEBIAN +---------------------- + +Sources can be found at www.eterm.org. Would like again to thank all of +#E on EFNet and #Debian on openprojects.net. + +This is a CVS PRERELEASE DEB _ONLY_! DO NOT FILE BUGS AGAINST IT! +If you run into problems, please contact Brian Almeida + +No changes made from the original. + +Brian M. Almeida , Sun, 27 Sep 1998 20:18:11 -0400 diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..979f32d --- /dev/null +++ b/debian/changelog @@ -0,0 +1,137 @@ +eterm (0.8.9-0.1) unstable; urgency=low + + * Made CVS debian/ stuff just like regular package stuff + (Ok, the -cvs stuff was a bad idea) Contains lots of improvements :) + + -- Brian M. Almeida Tue, 2 Mar 1999 20:42:10 -0500 + +eterm (0.8.8-7) unstable; urgency=low + + * Incorporated upstream patch for --console/-C (#33847) + + -- Brian M. Almeida Tue, 2 Mar 1999 20:39:06 -0500 + +eterm (0.8.8-7) unstable; urgency=low + + * Fixed bash bug in postinst + + -- Brian M. Almeida Sat, 27 Feb 1999 09:49:59 -0500 + +eterm (0.8.8-6) unstable; urgency=low + + * --console/-C option now writes to /dev/xconsole (#33847) + + -- Brian M. Almeida Fri, 26 Feb 1999 11:05:35 -0500 + +eterm (0.8.8-5) unstable; urgency=low + + * UPSTREAM SECURITY FIX for bug #33558 + + -- Brian M. Almeida Thu, 18 Feb 1999 15:29:43 -0500 + +eterm (0.8.8-4) unstable; urgency=low + + * Changed suidmanager line to use 4755 instead of 04755 (#33470) + * Added doc-base support (#31168) + * Cleaned up some lintian errors + - Calls ldconfig in postinst + - Removed -rpath stuff + + -- Brian M. Almeida Tue, 16 Feb 1999 15:55:04 -0500 + +eterm (0.8.8-3) unstable; urgency=low + + * REALLY fixed the pixmap problem! Yay! Thanks to Thunder- for his help + in tracking it down. + + -- Brian M. Almeida Tue, 9 Feb 1999 19:33:47 -0500 + +eterm (0.8.8-2) unstable; urgency=low + + * Correct eterm-backgrounds dependency (#28215) + * Relies on correct version of imlib (#29463) + * Added glibc2.1 fix for sparc port from Christian Meder (#32816) + * Corrected pixmap.lists files (#32835) + * Added note about non-bash shells and vim in README.Debian (re: #32768) + + -- Brian M. Almeida Sat, 6 Feb 1999 19:23:21 -0500 + +eterm (0.8.8-1) unstable; urgency=low + + * New upstream release + * New maintainer + * Updated download location in /usr/doc/copyright + * Added Eterm termcap files in /usr/doc/eterm + * imlib-nonfree1 is dead, background problem fixed (#20528) + * Uses correct location of Imlib.h (#24381) + * Backspace problem under bash fixed (#27617) + * Changed default TERM to xterm-debian (#27678) + * Has sample configuration file (#28018) + * Correct depends on eterm-backgrounds (#28284) + * Eterm now registers with suidmanager (#29777) + * Linked against libjpeg62 (#30464) + * Linked against libpng2-1.0.2b (#30975) + * Symlinks no longer dangle (#31511) + * Esetroot memory leak fixed (#32225) + + -- Brian M. Almeida Mon, 1 Feb 1999 15:24:00 -0500 + +eterm (0.8.7-0.4) frozen unstable; urgency=low + + * Non-maintainer upload + * Fixed -rpath bug + + -- Brian M. Almeida Mon, 7 Dec 1998 18:32:00 -0500 + +eterm (0.8.7-0.3) unstable; urgency=low + + * Non-maintainer upload + * Fixed the still-broken themes in 0.8.7-0.2 + + -- Brian M. Almeida Sun, 25 Oct 1998 11:00:00 -0400 + +eterm (0.8.7-0.2) unstable; urgency=low + + * Non-maintainer upload + * Fixed the extremely broken 0.8.7-0.1 (Oops!) + * Added more cleanup stuff to debian/rules (.deps .libs etc) + + -- Brian M. Almeida Sat, 24 Oct 1998 00:53:45 -0400 + +eterm (0.8.7-0.1) unstable; urgency=low + + * Non-maintainer upload + * New upstream release + + -- Brian M. Almeida Thu, 22 Oct 1998 00:53:45 -0400 + +eterm (0.8.6-3) unstable; urgency=low + + * Changed the depends: backgrounds to a Recommends at the request of Zed Phobre + + -- Sean E. Perry Tue, 20 Oct 1998 00:53:45 -0400 + +eterm (0.8.6-2) unstable; urgency=low + + * Fixed the menu file -- typos gotta love 'em + + -- Sean E. Perry Mon, 19 Oct 1998 21:43:20 -0400 + +eterm (0.8.6-1) frozen unstable; urgency=low + + * Fixed the fact that the theme files were missing + * Can find the pixmaps properly now + + -- Sean E. Perry Sun, 18 Oct 1998 02:19:22 -0400 + +eterm (0.8.6-0) unstable; urgency=low + + * New maintainer + * new upstream release + + -- Sean E. Perry Sun, 27 Sep 1998 20:18:11 -0400 + +Local variables: +mode: debian-changelog +add-log-mailing-address: "bma@debian.org" +End: diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..4e574bb --- /dev/null +++ b/debian/control @@ -0,0 +1,17 @@ +Source: eterm +Section: x11 +Priority: optional +Maintainer: Brian M. Almeida +Standards-Version: 2.5.0.0 + +Package: eterm +Architecture: any +Depends: ${shlibs:Depends} +Recommends: eterm-backgrounds +Description: Enlightened Terminal Emulator (ala xterm) with Imlib support + A terminal emulator in the spirit of xterm or rxvt. However this one differs + in that it uses an Enlightenment style config file, as well as themes. The + Imlib graphics engine is used to render images. This version supports + background images, pixmap shading/tinting, and pseudo-transparency. + Eterm also now uses libpthreads. + diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..26ba98b --- /dev/null +++ b/debian/copyright @@ -0,0 +1,8 @@ +This package was debianized by Sean E. Perry shaleh@debian.org on +Sun, 27 Sep 1998 20:18:11 -0400. + +It was downloaded from www.eterm.org + +Copyright: + +Eterm is released under the GPL. diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..d8c30c1 --- /dev/null +++ b/debian/dirs @@ -0,0 +1,5 @@ +usr/X11R6/bin +usr/X11R6/man +usr/lib/menu +usr/share/Eterm + diff --git a/debian/doc-base b/debian/doc-base new file mode 100644 index 0000000..8cd9b42 --- /dev/null +++ b/debian/doc-base @@ -0,0 +1,10 @@ +Document: eterm +Title: Eterm Frequently Asked Questions +Author: Michael Jennings +Abstract: Frequently Asked Questions about the Enlightened Terminal. + . +Section: Apps/Terminals + +Format: HTML +Index: /usr/doc/eterm/FAQ.html +Files: /usr/doc/eterm/FAQ.html diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..5b67382 --- /dev/null +++ b/debian/docs @@ -0,0 +1 @@ +README ReleaseNotes doc/FAQ.html doc/Eterm.tcap doc/Eterm.ti diff --git a/debian/menu b/debian/menu new file mode 100644 index 0000000..85ab8df --- /dev/null +++ b/debian/menu @@ -0,0 +1,2 @@ +?package(eterm):needs=X11 section=XShells\ + title="Eterm" command="/usr/bin/X11/Eterm" diff --git a/debian/postinst b/debian/postinst new file mode 100644 index 0000000..843845a --- /dev/null +++ b/debian/postinst @@ -0,0 +1,29 @@ +#!/bin/sh -e + +ldconfig + +if [ -x /usr/bin/update-menus ] ; then update-menus ; fi + +cd /usr/share/Eterm/themes +for theme_dir in `ls -1` +do + if [ -d $theme_dir ] + then + cd $theme_dir + echo "Linking pixmaps.list in $theme_dir" + ln -sf /usr/share/Eterm/pix/pixmaps.list pixmaps.list + cd .. + fi +done + +# Register with suidmanager +if command -v suidregister >/dev/null 2>&1 && [ -e /etc/suid.conf ]; then + suidregister -s eterm /usr/X11R6/bin/Eterm root root 4755 +else + chown root.root /usr/X11R6/bin/Eterm + chmod 4755 /usr/X11R6/bin/Eterm +fi + +if command -v install-docs >/dev/null 2>&1; then + install-docs -i /usr/share/doc-base/eterm +fi diff --git a/debian/postrm b/debian/postrm new file mode 100644 index 0000000..e03afae --- /dev/null +++ b/debian/postrm @@ -0,0 +1,9 @@ +#!/bin/sh -e +# Automatically added by dh_installmenu +if test -x /usr/bin/update-menus ; then update-menus ; fi +# End automatically added section +# Automatically added by dh_suidregister +if command -v suidunregister >/dev/null 2>&1 && [ -e /etc/suid.conf ]; then + suidunregister -s eterm /usr/X11R6/bin/Eterm +fi +# End automatically added section diff --git a/debian/rules b/debian/rules new file mode 100644 index 0000000..8986ae8 --- /dev/null +++ b/debian/rules @@ -0,0 +1,94 @@ +#!/usr/bin/make -f + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +INSTALL_BASE=`pwd`/debian/tmp + +configure: configure.in + libtoolize --copy --force + aclocal $ACLOCAL_FLAGS + automake --add-missing + autoconf + autoheader + +build: build-stamp +build-stamp: + dh_testdir + + # Add here commands to compile the package. + ./configure --prefix=/usr --bindir=/usr/X11R6/bin \ + --datadir=/usr/share --mandir=/usr/X11R6/man + + + # because glibc 2.1's utmpx.h is incompatible on sparc + sed -e 's/#define HAVE_UTMPX_H 1/\/* #undef HAVE_UTMPX_H *\//' config.h > config.h.tmp + mv config.h.tmp config.h + + # fix rpath issues + sed < libtool > libtool-2 \ + -e 's/^hardcode_libdir_flag_spec.*$$/hardcode_libdir_flag_spec="-D__LIBTOOL_IS_A_FOOL__ "/' \ + -e '/^archive_cmds="/s/"$$/ \\$$deplibs"/' + mv libtool-2 libtool + chmod 755 libtool + + make + + touch build-stamp + +clean: + dh_testdir + dh_testroot + rm -f build-stamp + + # Add here commands to clean up after the build process. + -$(MAKE) -k distclean + -rm -f `find . -name "*~"` + -rm -rf `find . -name "\.deps"` + -rm -rf `find . -name "\.libs"` + -rm -rf debian/tmp `find debian/* -type d ! -name CVS` debian/files* core + -rm -f debian/*substvars + + dh_clean + +# Build architecture-independent files here. +binary-indep: build +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build + dh_testdir -a + dh_testroot -a + dh_clean -k -a + dh_installdirs -a + + # Add here commands to install the files into debian/tmp + $(MAKE) install DESTDIR=$(INSTALL_BASE) \ + PREFIX=$(INSTALL_BASE)/usr \ + datadir=$(INSTALL_BASE)/usr/share \ + pkglibdir=$(INSTALL_BASE)/usr/share/Eterm \ + DATADIR=$(INSTALL_BASE)/usr/share \ + themedir=$(INSTALL_BASE)/usr/share/Eterm/themes + + dh_installdocs -a + dh_installmenu -a + #dh_installmanpages --verbose -a + dh_undocumented -a Esetroot.1x + dh_installchangelogs -a + dh_strip -a + dh_compress -a + dh_fixperms -a + chown root.root debian/tmp/usr/X11R6/bin/Eterm + chmod 4755 debian/tmp/usr/X11R6/bin/Eterm + dh_suidregister + dh_installdeb -a + dh_shlibdeps -a + dh_gencontrol -a + dh_md5sums -a + dh_builddeb -a + +source diff: + @echo >&2 'source and diff are obsolete - use dpkg-source -b'; false + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary diff --git a/debian/shlibs.local b/debian/shlibs.local new file mode 100644 index 0000000..688087d --- /dev/null +++ b/debian/shlibs.local @@ -0,0 +1 @@ +libpng 2 libpng2(>= 1.0.2b-0.1) diff --git a/doc/.cvsignore b/doc/.cvsignore new file mode 100644 index 0000000..a62695a --- /dev/null +++ b/doc/.cvsignore @@ -0,0 +1,4 @@ +Eterm.1 +Eterm.1.html +Makefile +Makefile.in diff --git a/doc/Eterm.1.in b/doc/Eterm.1.in new file mode 100644 index 0000000..e23f892 --- /dev/null +++ b/doc/Eterm.1.in @@ -0,0 +1,1263 @@ +.TH ETERM 1 @DATE@ "X Version 11" "X Tools" +.SH NAME +Eterm \(em +an Enlightened terminal emulator for the X Window System +.SH SYNOPSIS +.B Eterm +.RI [ options ] + +.SH DESCRIPTION +.PP +.B Eterm +\(em version +.B @VERSION@ +\(em is a color vt102 terminal emulator intended as an +.IR xterm (1) +replacement for users who want a term program integrated with +Enlightenment, or +simply want a little more "eye candy". +.B Eterm +uses Imlib for advanced graphic abilities. See below for details. +.SH OPTIONS +The +.B Eterm +options are listed below. +In keeping with the freedom-of-choice philosophy, options may be eliminated +or default values chosen at compile-time, so options and defaults listed +may not accurately reflect the version installed on your system. + +Options that do not take a parameter (besides -h and --help) are boolean. If +you use the POSIX (short) option, you are forcing the parameter to "true". If +you use the long option, you can use any of the accepted boolean values, which +are "yes", "on", "1", and "true" to turn the option on, or "no", "off", "0", or +"false" to turn the option off. The same is true for boolean values in the +configuration file. +.LP +.TP +.BI \-t " theme" ", \-\-theme " theme +Load specified +.I theme\. +Consult the FAQ for more details on what constitutes an Eterm +.I theme\. +.TP +.BI \-X " conffile" ", \-\-config-file " conffile +Use an alternative config file name. Otherwise Eterm uses the default, +which is +.I MAIN\. +.TP +.BR "\-h" , " \-\-help" +Print out a message describing available options. +.TP +.BR \-\-version +Print +.B Eterm +version and compile-time configuration. +.TP +.BI \-\-debug " level" +Show debugging output. +.I level +is an integer between 0 and 5 which determines how verbose the debugging +output is. +.TP +.BR "\-r" , " \-\-reverse-video" +Reverse video, swaps the foreground and background colors. +.TP +.BI \-b " color" ", \-\-background-color " color +Set +.I color +as the background color. +.B NOTE: +this will actually be the foreground color if reverse video is also +selected. +.TP +.BI \-f " color" ", \-\-foreground-color " color +Set +.I color +as the foreground (text) color. +.B NOTE: +this will actually be the background color if reverse video is also +selected. +.TP +.BI \-\-color0 " color" +.TP +.BI ... +.TP +.BI \-\-color15 " color" +Use +.I color +as color X. +.TP +.BI \-\-colorBD " color" +Use +.I color +as the bold color. +.TP +.BI \-\-colorUL " color" +Use +.I color +as the underline color. +.TP +.BI \-\-menu-text-color " color" +Use +.I color +as the menu text color (only makes sense if menu is enabled). +.TP +.BI \-S " color" ", \-\-scrollbar-color " color +Use +.I color +as the scrollbar color (only makes sense if scrollbar is enabled). +.TP +.BI \-\-unfocused-scrollbar-color " color +Use +.I color +as the scrollbar color when window does not have focus +(only makes sense if scrollbar is enabled). +.TP +.BI \-\-pointer-color " color" +Use +.I color +as the pointer color. +.TP +.BI \-c " color" ", \-\-cursor-color " color +Use +.I color +as the cursor color. +.TP +.BI \-\-cursor-text-color " color" +Use +.I color +as the cursor text color. +.TP +.BI \-d " displayname" ", \-\-display " displayname +Attempt to open a window on the named X display +.I displayname. +In the absence of this option, the display specified by the +.B DISPLAY +environment variable is used. +.TP +.BI \-g " geom" ", \-\-geometry " geom +Window geometry as Width x Height+X coord+Y coord, i.e 100x200+0+100 +.TP +.BR "\-i" , "\-\-iconic" +Start in iconified state (only if the window manager supports +iconification). +.TP +.BI \-n " name" ", \-\-name " name +Sets name of current instance to +.I name. +This will affect the icon title and the window title string unless +they are otherwise explicitly set. +.TP +.BI \-T " title" ", \-\-title " title +Sets window's title text to +.I title. +.TP +.BI \-\-icon-name " text" +Sets the icon title text to +.I text. +.TP +.BI \-B " type" ", \-\-scrollbar-type " type +Specifies the +.I type +scrollbar style should be used. +.I type +can be any of +.BR "motif" ", " "xterm" ", or " "next" "." +.TP +.BI \-\-scrollbar-width " width" +Set the width of the scrollbar, in pixels, to +.IR width "." +Eterm does not impose any restrictions on this value, but it should be reasonable. +.TP +.BI \-D " desktop" ", \-\-desktop " desktop +Starts the Eterm on the specified desktop. +.I desktop +should be an integer between 0 and your highest-numbered desktop. +.BR "NOTE" ": " +You must have a GNOME-compliant window manager for this feature to work. Please see +http://www.gnome.org/devel/gnomewm/ for more information on the +.B _WIN_WORKSPACE +property and how to support it. +.TP +.BI \-\-bold-font " font" +Sets the bold text font to +.I font. +.TP +.BI \-F " font" ", \-\-font " font +Sets the normal text font to +.I font. +.TP +.BI \-\-font1 " font" +.TP +.BI ... +.TP +.BI \-\-font4 " font" +Sets font X to +.I font. +.TP +.BI \-P " pic" ", \-\-background-pixmap " pic +Use +.I pic +as the background image. +.I pic +can be in any format that Imlib understands. Currently this means just +about anything, including JPG, PNG, GIF, TIFF, PPM, etc. The image is +tiled by default. To scale the image, use the +.B --scale +option below. +.TP +.BI \-I " pic" ", \-\-icon " pic +Sets the icon pixmap file to +.IR "pic" "." +Works similarly to the +.B -P +option above. +.TP +.BI \-\-up-arrow-pixmap " pic" +As above, except the scrollbar's up-arrow is set. +.B NOTE: +This is not currently implemented. +.TP +.BI \-\-down-arrow-pixmap " pic" +As above, except the scrollbar's down-arrow is set. +.B NOTE: +This is not currently implemented. +.TP +.BI \-\-trough-pixmap " pic" +As above, except the scrollbar's background (trough) is set. +.B NOTE: +This is not currently implemented. +.TP +.BI \-\-anchor-pixmap " pic" +As above, except the scrollbar's anchor image is set. +.B NOTE: +This is not currently implemented. +.TP +.BR "\-@" , " \-\-scale" +Scale the image rather than tile. Only makes sense if the background pixmap +option is used (see above). +.TP +.BR "\-W" , " \-\-watch-desktop" +In a pseudo-transparent Eterm, this will watch the desktop for changes to the +image, Eterm moving to a different desktop, etc. Use with the transparency +options below. +.TP +.BR "\-O" , " \-\-trans" +This gives a pseudo-transparent Eterm. The image is taken directly from the +root window, so any requests for changing the pixmap are ignored. If you do +not use Enlightenment (http://www.enlightenment.org/) as your window manager, +you will need to use the +.I Esetroot +program in the +.B doc/ +directory to set your root background image. +.TP +.BI \-\-shade " percentage" +Darkens the background pixmap (either an image file or the transparent +portion can be shaded). The amount of shading is controlled by the +specified +.IR percentage , +which may or may not be followed by a percent sign. +.TP +.BI \-\-tint " mask" +Tints the background pixmap (either an image file or the transparent +portion can be shaded). The +.I mask +is an integer, usually specified in hexadecimal in the form +.BR " " "0x" "RRGGBB" "," +where +.BR "RR" ", " "GG" ", and " "BB" +are hexadecimal numbers between +.BR "00" " and " "ff" " (" "0" " and" +.BR "255" " decimal)" +which represent the brightness of the image's red, green, and blue +values, respectively. A value of +.B 00 +will mask that color out entirely, while a value of +.B ff +will not change that color at all. Some common tints are: +.RS 10 +none 0xffffff +.br +red 0xff8080 +.br +green 0x80ff80 +.br +blue 0x8080ff +.br +cyan 0x80ffff +.br +magenta 0xff80ff +.br +yellow 0xffff80 +.RE +.TP +.BI \-p " newpath" ", \-\-path " newpath +Sets the pic search path. When the +.B --background-pixmap +or other pixmap options are used, this path will be used to find the image. +.TP +.BI \-N " list" ", \-\-anim " list +Specifies an animation list to be use in cycling the background pixmap. The +.I list +consists of two or more words. The first word defines the delay, in seconds, +between updates of the background. This should be set to a reasonable value +to insure that Eterm doesn't spend all its time rendering backgrounds. All +remaining words have the same syntax as the +.B background +attribute in a configuration file (two integers followed by the image filename), +except that the two integers are optional. If they are specified, remember to +group them with the filename using quotes. The following are both valid: +.RS 10 +Eterm -N '10 image1.jpg image2.jpg' +.br +Eterm -N '10 "0 0 image1.jpg" "-1 -1 image2.jpg"' +.RE +.TP +.BR "\-l", " \-\-login-shell" +Makes the new shell a login shell. +.TP +.BR "\-s", " \-\-scrollbar" +Enables the scrollbar. (Default) +.TP +.BR \-\-menubar +Enables the menubar. (Default) +.TP +.BR "\-u", " \-\-utmp-logging" +Tries to enable proper utmp logging. For this to work, Eterm probably needs +to run setuid or setgid, usually setuid root. +.TP +.BR "\-v", " \-\-visual-bell" +Enables the "visual bell". Means the window will flash or blink rather +than beep. +.TP +.BR "\-H", " \-\-home-on-echo" +Jump to bottom on output. +.TP +.BR "\-\-home-on-input" +Jump to bottom on input. +.TP +.BR "\-E", " \-\-home-on-refresh" +Jump to bottom on refresh (^L) +.TP +.BR "\-\-scrollbar-right" +Display scrollbar on the right hand side. +.TP +.BR "\-\-scrollbar-floating" +Display the scrollbar without a trough. +.TP +.BR "\-\-scrollbar-popup" +Display the scrollbar only when the Eterm window is focused. +.TP +.BR "\-x", " \-\-borderless" +This option forces Eterm to have no borders. This also means that the +window can not be moved (unless the +.BR \-V " or " \-\-menubar-move +option is specified) or resized. Recommend using +.B --geometry +as well with this option. +.TP +.BR "\-m", " \-\-map-alert" +Un-iconify on beep. +.TP +.BR "\-8", " \-\-meta8" +Causes the Meta key to set the 8th bit in the char. +.TP +.BR "\-\-save-under" +If supported by the X server, tries to use backing store for faster +refreshes. +.TP +.BR "\-\-no-cursor" +Disables the text cursor. +.TP +.BR \-V ", " \-\-menubar-move +This options causes Eterm to enable the moving of the Eterm window by +dragging the right-hand side of the menubar. This is useful for +borderless Eterms (and is, in fact, on by default if the +.BR \-x " or " \-\-borderless +option is specified). +.TP +.BR \-\-pause +After the child process terminates, Eterm will wait for a keypress +before exiting. +.TP +.BR \-\-xterm-select +Duplicate's xterm's treatment of cutchars. The only real difference is +what happens when you double click on a single cutchar between two +words. If this option is on, only that single character gets selected. +If it is off, that character is selected along with the two words. The +latter behavior is useful for double-clicking on the space between someone's +first and last names, or the @ sign in an e-mail address, etc. +.TP +.BR \-\-select-line +If activated, this option causes a triple click to select the entire line +from beginning to end. If off, a triple-click selects just from the current +word to the end of the line. +.TP +.BR \-\-viewport-mode +This activates a special Eterm mode which is hard to describe in words. +Basically, imagine the effect you get with pseudo-transparency, where +the desktop background moves through the Eterm window as you move the +window, so that it always aligns with the desktop image. Now, imagine +the same effect, but the image used isn't the desktop image but any +pixmap you choose. The image is scaled or tiled up to the size of the +desktop, and dragging the Eterm around the screen reveals different +portions of the image as you move, much like a small viewport window +in a ship or submarine does. The effect is especially keen if you +open several Eterms in this mode with the same image. +.TP +.BI \-\-big-font-key " keysym" +Specify a keysym to increase the font size. Default is Shift and the + +key on the keypad. Ctrl-> or Meta-> may also work (if you #define one +of the hotkeys in src/feature.h). +.TP +.BI \-\-small-font-key " keysym" +Specify a keysym to decrease the font size. Default is Shift and the - +key on the keypad. Ctrl-< or Meta-< may also work (if you #define one +of the hotkeys in src/feature.h). +.TP +.BR \-\-app-keypad +Start Eterm in application keypad mode (as opposed to normal keypad mode). +.TP +.BR \-\-app-cursor +Start Eterm in application cursor key mode (as opposed to normal cursor +key mode). +.TP +.BI \-L " num" ", \-\-save-lines " num +Set the number of lines in the scrollback buffer to +.I num. +.TP +.BI \-a " size" ", \-\-min-anchor-size " size +Specifies the minimum size, in pixels high, of the scrollbar anchor. +.B NOTE: +This causes abnormal scrolling behavior when combined with large +scrollback buffers! +.TP +.BI \-w " width" ", \-\-border-width " width +Set the window's border width to +.I width. +The border this controls is the gap between the edge of the X window and +the edge of the terminal window; this has nothing to do with the window +border's your window manager supplies. +.TP +.BI \-\-print-pipe " pipe" +The pipe for the PrintScreen function. +.TP +.BI \-\-cut-chars " separators" +The seperators for double-click selection. +.TP +.BI \-M " file" ", \-\-menu " file +Replace default menubar file with +.IR file . +To disable the menubar altogether, do not specify a bogus value for +.IR file . +Instead, use the boolean option +.B \-\-menubar off +.TP +.BI \-\-term-name " TERM" +Use +.I TERM +for the value $TERM. +.TP +.BR "\-C", " \-\-console" +Grab console messages. Depending on your system, Eterm may need to be +setuid root to do this. +.TP +.BI \-e " command" ", \-\-exec " command +Execute +.I command +rather than a shell. + +.SH SPECIAL LANGUAGE FEATURES +The following are +.B *NOT* +compiled in by default. +.PP +.TP +.B Kanji (Japanese character) options +.TP +.BI \-K " font" ", \-\-kanji-font " font +Use +.I font +as the default kanji font. +.TP +.BI \-\-kanji-font1 " font" +.TP +.BI ... +.TP +.BI \-\-kanji-font4 " font" +Use +.I font +as kanji font X. +.TP +.BR "\-\-kanji-encoding" +Use Kanji encoding mode (eucj or sjis). +.TP +.B Greek options +.TP +.BR "\-\-greek-keyboard" +Use Greek keyboard mapping (iso or ibm). + +.SH THEMES + +Eterm is built on the philosophy of Freedom of Choice. Each user should be +able to choose the environment in which he wishes to exist, and the tools he +uses should support that. In accordance with that philosophy, Eterm is +extremely configurable. Eterm supports a concept called "themes," which should +be familiar to users of Enlightenment, icewm, or Microsoft Windows 95/98/NT. +The general concept of a theme is a collection of resources that change as many +aspects of a programs look and feel as possible. For example, an Enlightenment +theme allows you to customize menus, window borders, desktops, icons, iconbars, +and everything else about how E looks and feels. + +An Eterm theme consists of a primary configuration file, always called "MAIN", +residing in a directory bearing the same name as the theme. This directory must +be a child of one of the directories specified by CONFIG_SEARCH_PATH in +src/feature.h, in the environment variable defined by PATHENV in src/feature.h, +or in the default PATH. The theme may also contain additional configuration +files referenced by the primary MAIN file, pixmaps, menu files, documentation, +etc., which are allowable as extensions to the minimum requirement of an Eterm +theme. + +By convention and default, Eterm themes should be stored under +~/.Eterm/themes// or @THEMEDIR@/. + +All command line options can be enabled/disabled in the theme's configuration +file (the default is @THEMEDIR@/Eterm/MAIN). The next section contains details +on the format and usage of the configuration file. + +.SH CONFIGURATION + +Since Eterm @VERSION@ is based on the concept of themes, it is vital that you +have a thorough understanding of the previous section before taking on this +one. The previous section and this one were written by the same person who +wrote the Eterm code which handles options, config files, and themes, so it's +probably the most authoritative documentation on the subject you're going to +find. + +From here on out, I will assume you've read the above text and know how to +change the default value for the theme and the config file name. Just realize +that when I subsequently refer to MAIN, if you are using a different name, +substitute the name you supplied in place of MAIN. I may also refer to the +Eterm theme. If you are using a different theme, substitute your theme's name +in place of Eterm. It is highly recommended that you have a copy of the Eterm +theme MAIN file that comes with Eterm handy while you read this documentation. + +Okay, first the general idea. The MAIN file is composed of comments and +non-comments. Comments begin with a pound sign and continue to the end of the +line. Lines of whitespace are also ignored. The rest of the file is the config +stuff, which is divided into sections (called "contexts") and variables (called +"attributes"). There are eight valid contexts: color, attributes, pixmaps, +toggles, keyboard, misc, kanji, and main. Each attribute must be inside a +certain context to be valid. For instance, while the "foreground" attribute is +perfectly acceptable in the color context, it would be rejected if found in, +say, the toggles context. This allows for better organization of the config +file. + +Each context must be enclosed in a begin...end pair that specifies the type of +section. The statement "begin toggles" starts the toggles context, and the +next "end" statement would terminate it. + +The rest of this section will contain a step-by-step analysis of the config +file, including what can go in each section. Note that some attributes (and +even entire contexts) may not be available depending on what support was +compiled into Eterm by the person who built it. +.LP +.TP +MAGIC NUMBER + +The first line of the config file must contain a "magic number" type line +that lets Eterm verify that it's reading an Eterm config file and not +something else (like an Enlightenment 0.13 and earlier config file). The +line should look like this: + + + +where VERSION is the Eterm version for which the config file is intended. +For example, config files written for Eterm 0.8 should have "" +as their first line, followed immediately by a newline. +.TP +MAIN CONTEXT + +There are very few things that are valid within the "main" context. In +fact, the only non-comment lines allowed in the main context are begin's +and end's for other contexts. According to the internal mechanism of +Eterm, each context can have any number of subcontexts, but as it is +currently implemented, only main has any. Valid subcontexts for main are +color, attributes, pixmaps, toggles, keyboard, misc, and kanji. They can +appear in any order. The order I list them here is simply the order in +which they appear in the default themes, which was arbitrarily chosen for +continuity. +.TP +COLOR CONTEXT + +This context contains color specifications. With the exception of +.B tint +and the terminal colors 0-15, all +.IR color s +should be either a valid color name or an RGB string as outlined in the +.IR X11 (7) +man page. + +.RS 5 +.BI foreground " color" +.RS 5 +Use +.I color +for the foreground (text) color. +.RE + +.BI background " color" +.RS 5 +Use +.I color +for the background color. +.RE + +.BI tint " mask" +.RS 5 +Tints the background pixmap (either an image file or the transparent +portion can be shaded). The +.I mask +is an integer, usually specified in hexadecimal in the form +.BR " " "0x" "RRGGBB" "," +where +.BR "RR" ", " "GG" ", and " "BB" +are hexadecimal numbers between +.BR "00" " and " "ff" " (" "0" " and" +.BR "255" " decimal)" +which represent the brightness of the image's red, green, and blue +values, respectively. A value of +.B 00 +will mask that color out entirely, while a value of +.B ff +will not change that color at all. Some common tints are: +.RS 5 +none 0xffffff +.br +red 0xff8080 +.br +green 0x80ff80 +.br +blue 0x8080ff +.br +cyan 0x80ffff +.br +magenta 0xff80ff +.br +yellow 0xffff80 +.RE +.RE + +.BI shade " percentage" +.RS 5 +Darkens the background pixmap (either an image file or the transparent +portion can be shaded). The amount of shading is controlled by the +specified +.IR percentage , +which may or may not be followed by a percent sign. +.RE + +.BI cursor " color" +.RS 5 +Use +.I color +for the cursor color. +.RE + +.BI cursor_text " color" +.RS 5 +Use +.I color +for the cursor text color. +.RE + +.BI menu_text " color" +.RS 5 +Use +.I color +for the menu text color. +.RE + +.BI scrollbar " color" +.RS 5 +Use +.I color +for the scrollbar color. +.RE + +.BI unfocusedscrollbar " color" +.RS 5 +Use +.I color +for the scrollbar color if Eterm is unfocused. +.RE + +.BI pointer " color" +.RS 5 +Use +.I color +for the mouse pointer color. +.RE + +.BR video " { " normal " | " reverse " }" +.RS 5 +.B normal +will not reverse the foreground and background colors. +.B reverse +(meaning reverse video) will. +.RE + +.BI color " num" " " "color" +.RS 5 +Set terminal color +.I num +(0-15) to the color name, string, or set of 3 decimal/hex/octal RGB values +specified by +.IR color . +.RE + +.BR color " { " "bd" " | " "ul" " }" +.I color +.RS 5 +Set terminal bold +.BR " " "(" bd ") or underline (" ul ") color" +to the color name, string, or set of 3 decimal/hex/octal RGB values +specified by +.IR color . +.RE +.RE + +.TP +ATTRIBUTES CONTEXT + +This context contains X11 attributes. Most of these are dependent upon the +cooperation of the window manager. + +.RS 5 +.BI geometry " geom" +.RS 5 +Use the geometry string +.I geom +to specify the startup geometry. +.I geom +should be in the format +.BI " " W x H+X+Y +where +.I W +is the width, +.I H +is the height, and +.I +X +and +.I +Y +are the X and Y offsets. If the signs on +.I X +and +.I Y +are positive, the coordinates are offsets (in pixels) from the left and top, +respectively, of the screen. If the signs are negative, the offsets are +relative to the right and bottom of the screen, respectively. +.RE + +.BI title " title" +.RS 5 +Use +.I title +as the text in the title bar of the Eterm window. +.RE + +.BI name " name" +.RS 5 +Use +.I name +as the resource name of the Eterm window. +.RE + +.BI iconname " name" +.RS 5 +Use +.I name +as the icon name of the Eterm window icon. +.RE + +.BI desktop " num" +.RS 5 +Start Eterm on desktop +.IR num . +.BR NOTE ": " +This requires a GNOME-compliant Window Manager. Please see +http://www.gnome.org/devel/gnomewm/ for more information on the +.B _WIN_WORKSPACE +property and how to support it. +.RE + +.BI scrollbar_type " type" +.RS 5 +Use a scrollbar with the +.IR type " style. " type " can" +be any of +.BR motif ", " xterm ", or " next "." +.RE + +.BI scrollbar_width " num" +.RS 5 +Use a scrollbar that is +.I num +pixels wide. +.RE + +.BI font " num" " " "font" +.br +.BI "font bold " font +.RS 5 +Set the +.IR num th +font (0-4), or the +.B bold +font, to +.IR font . +.RE +.RE + +.TP +PIXMAPS CONTEXT + +This context contains attributes related to pixmaps. + +.RS 5 +.BI background " x_scale y_scale filename" +.RS 5 +Use +.I filename +as the background image for the Eterm window. +.I filename +can be an absolute path, relative to the current theme, or relative to one of +the directories in the +.B path +attribute listed below. The +.IR x_scale " and " y_scale +values should be either both 0 (tile) or both -1 (scale). +.RE + +.BI path " directory_list" +.RS 5 +Specifies a colon-delimited list of directories relative to which Eterm should +search for image and menu files. The syntax for +.I directory_list +is precisely the same as that of the +.B $PATH +environment variable in UNIX shells. +.RE + +.BI icon " filename" +.RS 5 +Use +.I filename +as the icon image for the Eterm window. +.I filename +can be an absolute path, relative to the current theme, or relative to one of +the directories in the +.B path +attribute listed above. +.RE + +.BI anim " interval" "" " images ..." +.RS 5 +Specifies an animation list to be use in cycling the background pixmap. +.I interval +defines the delay, in seconds, between updates of the background. This +should be set to a reasonable value to insure that Eterm doesn't spend all +its time rendering backgrounds. All remaining words have the same syntax as the +.B background +attribute in a configuration file (two integers followed by the image filename), +except that the two integers are optional. If they are specified, remember to +group them with the filename using quotes. The following are both valid: +.RS 5 +anim 10 image1.jpg image2.jpg +.br +anim 10 "0 0 image1.jpg" "-1 -1 image2.jpg" +.RE +.RE +.RE + +.TP +TOGGLES CONTEXT + +This context contains boolean variables which can be toggled on or off. Valid +values for the attributes in this section are "yes", "on", "1", and "true" to +turn the option on, or "no", "off", "0", or "false" to turn the option off. +These values are denoted by +.IR boolean . +They all default to false unless otherwise noted. + +.RS 5 +.BI map_alert " boolean" +.RS 5 +If true, Eterm will un-iconify itself when it receives a beep (ASCII 0x07). +.RE + +.BI visual_bell " boolean" +.RS 5 +If true, Eterm will flash rather than sending a beep. +.RE + +.BI login_shell " boolean" +.RS 5 +If true, Eterm will prepend '-' to the shell name when calling it. Depending +on your shell, this may modify its startup behavior. +.RE + +.BI scrollbar " boolean" +.RS 5 +This turns on and off the display of the scrollbar. Default is on. +.RE + +.BI menubar " boolean" +.RS 5 +This turns on and off the display of the menubar. Default is on. +.RE + +.BI utmp_logging " boolean" +.RS 5 +If true, Eterm will attempt to make an entry in the utmp file to record the +login information. Eterm may need to run privileged to do this. +.RE + +.BI meta8 " boolean" +.RS 5 +Toggles the interpretation of the Meta key setting the 8th bit in a +character. +.RE + +.BI iconic " boolean" +.RS 5 +If true, Eterm will launch as an icon. +.RE + +.BI home_on_echo " boolean" +.RS 5 +Zoom to the bottom of the scrollback buffer on output. +.RE + +.BI home_on_input " boolean" +.RS 5 +Zoom to the bottom of the scrollback buffer on input. +.RE + +.BI home_on_refresh " boolean" +.RS 5 +Zoom to the bottom of the scrollback buffer on refresh (Ctrl-L). +.RE + +.BI scrollbar_floating " boolean" +.RS 5 +If true, the scrollbar will have no trough. +.RE + +.BI scrollbar_right " boolean" +.RS 5 +If true, Eterm will put the scrollbar on the right of the window (default is left). +.RE + +.BI scrollbar_popup " boolean" +.RS 5 +If true, Eterm will hide the scrollbar when the Eterm window loses focus and restore +it when focus is regained. Default is to not change the scrollbar state based on +focus. +.RE + +.BI borderless " boolean" +.RS 5 +If true, Eterm will run with no window borders. This also means that the +window can not be moved or resized. You will want to specify a +.B geometry +with this attribute. +.RE + +.BI save_under " boolean" +.RS 5 +If true, Eterm will use a backing store. +.RE + +.BI trans " boolean" +.RS 5 +Toggles Eterm's pseudo-transparency feature. Yes, it's fake. Yes, it will +always be fake. Don't ask. +.RE + +.BI watch_desktop " boolean" +.RS 5 +This option is required if you want Eterm to watch for updates to the desktop +background image, including moving across desktops. There is a speed sacrifice +that must be made for this feature, although I've tried to make it as small as +possible. +.RE + +.BI no_cursor " boolean" +.RS 5 +If true, Eterm will not display a text cursor. +.RE + +.BI menubar_move " boolean" +.RS 5 +This options causes Eterm to enable the moving of the Eterm window by +dragging the right-hand side of the menubar. This is useful for +borderless Eterms (and is, in fact, on by default if the +.BR borderless +attribute is true). +.RE + +.BI pause " boolean" +.RS 5 +After the child process terminates, Eterm will wait for a keypress +before exiting. +.RE + +.BI xterm_select " boolean" +.RS 5 +Duplicate's xterm's treatment of cutchars. The only real difference is +what happens when you double click on a single cutchar between two +words. If this option is on, only that single character gets selected. +If it is off, that character is selected along with the two words. The +latter behavior is useful for double-clicking on the space between someone's +first and last names, or the @ sign in an e-mail address, etc. +.RE + +.BI select_line " boolean" +.RS 5 +If true, this attribute causes a triple-click to select from the current +word to the end of the line. If off, a triple click selects the entire +line from beginning to end. +.RE + +.BI select_trailing_spaces " boolean" +.RS 5 +If true, this attribute causes spaces at the end of a line to be included +as part of the selection text when selecting. The default is to strip +these trailing spaces. +.RE + +.BI viewport_mode " boolean" +.RS 5 +This activates a special Eterm mode which is hard to describe in words. +Basically, imagine the effect you get with pseudo-transparency, where +the desktop background moves through the Eterm window as you move the +window, so that it always aligns with the desktop image. Now, imagine +the same effect, but the image used isn't the desktop image but any +pixmap you choose. The image is scaled or tiled up to the size of the +desktop, and dragging the Eterm around the screen reveals different +portions of the image as you move, much like a small viewport window +in a ship or submarine does. The effect is especially keen if you +open several Eterms in this mode with the same image. +.RE +.RE + +.TP +KEYBOARD CONTEXT + +This context contains keyboard-related configuration options. + +.RS 5 +.BI smallfont_key " keysym" +.RS 5 +Specify a keysym to decrease the font size. Default is Shift and the - key on +the keypad. Ctrl-< or Meta-< may also work (if you #define one of the hotkeys +in src/feature.h). +.RE + +.BI bigfont_key " keysym" +.RS 5 +Specify a keysym to increase the font size. Default is Shift and the + key on +the keypad. Ctrl-> or Meta-> may also work (if you #define one of the hotkeys +in src/feature.h). +.RE + +.BI keysym " keysym" " " "string" +.RS 5 +Define keysym +.I keysym +to send +.I string +instead of its default. +.I keysym +must be between 0xff00 and 0xffff or Eterm will complain. +.RE + +.BI greek " boolean" +.BR " " "{ " "iso" " | " "ibm" " }" +.RS 5 +Turn on/off greek keyboard support, and set which greek mode to use. +.RE + +.BI app_keypad " boolean" +.RS 5 +Turn on/off application keypad mode on startup. +.RE + +.BI app_cursor " boolean" +.RS 5 +Turn on/off application cursor key mode on startup. +.RE +.RE + +.TP +MISC CONTEXT + +This context contains miscellaneous attributes that really didn't belong +anywhere else. + +.RS 5 +.BI print_pipe " command" +.RS 5 +Set the command to which to pipe print requests (printscreen) to +.IR command . +.RE + +.BI save_lines " num" +.RS 5 +Set the number of lines in the scrollback buffer to +.IR num . +.RE + +.BI cut_chars " string" +.RS 5 +Define the characters used as word delimiters to the characters contained in +.IR string . +.RE + +.BI min_anchor_size " num" +.RS 5 +Sets the minimum size, in pixels, of the scrollbar anchor (the part your mouse +grabs onto and moves around) to +.IR num . +.RE + +.BI border_width " num" +.RS 5 +Sets the width of the border between the text window and the X window to +.IR num . +.RE + +.BI menu " file" +.RS 5 +Loads menubar code from +.IR file . +The way to turn the menubar off is to not have this line in the config file, +but passing some bogus filename (or +.BR /dev/null ) +as +.I file +will work too, though it may produce an error message. +.RE + +.BI term_name " name" +.RS 5 +Use +.I name +as the +.B $TERM +environment variable, which controls which termcap/terminfo entry gets used. +The default is +.BR xterm . +.RE + +.BI exec " command" +.RS 5 +Rather than executing a shell, this will cause Eterm to spawn +.I command +as its child process. You can only have one of these! +.RE +.RE + +.TP +KANJI CONTEXT + +This context contains attributes which are only used when Eterm is compiled +with Kanji support. This context is not valid in a normal Eterm. + +.RS 5 +.BI font " num" " " "font" +.RS 5 +Set the +.IR num th +kanji font (0-4) to +.IR font . +.RE + +.BR encoding " { " "eucj" " | " "sjis" " }" +.RS 5 +Set the kanji encoding method. +.RE +.RE + +.TP +BUILT-IN FUNCTIONS + +Eterm has a set of built-in functions which are available in config files. +They can be used anywhere their output would be valid. Built-in functions +are prefixed with the +.B % +character. + +.RS 5 +.BI %random( params ) +.RS 5 +This function randomly chooses one of the words which compose +.I params +and returns that. "Words" are defined in shell terms, meaning that single or +double quotes can be used to separate individual words of +.I params +which contain spaces. And you can even get creative and use a +backquote-executed command to generate the list of words to pass to +.BR %random() . +The default themes that come with Eterm demonstrate this technique, in fact. +But keep in mind that random pixmaps aren't the only thing you can do with this +function. You can randomize anything...colors, toggles, fonts, tinting...you +name it! +.RE + +.BI %exec( command ) +.RS 5 +Executes +.I command +and returns the result. Basically it's exactly like using backquotes, except +that it hasn't been implemented yet, so use backquotes instead. :-} +.RE + +.BI %appname() +.RS 5 +Returns the application name, a hyphen, and the version number. Currently this +is the string +.BR Eterm-@VERSION@ . +.RE + +.BI %version() +.RS 5 +Returns the version number. Currently this +is the string +.BR @VERSION@ . +.RE +.RE + +.TP +INCLUDES + +Eterm supports the +.BI %include " file" +directive to allow for separation of the configuration information into +separate files. + +.SH AUTHORS +Tuomo Venalainen (vendu@cc.hut.fi) and Michael Jennings (mej@tcserv.com). +Man page re-written for version 0.8 by Shaleh (shaleh@debian.org). + +.SH URL(s) +Eterm Home Page -- http://www.eterm.org/ +.br +Eterm FAQ -- http://www.eterm.org/FAQ.html +.br +Eterm iFAQ -- http://www.eterm.org/cgi-bin/ifaq.cgi +.br +Resurrection -- http://ganja.tky.hut.fi/Resurrection/ +.br diff --git a/doc/Eterm.tcap b/doc/Eterm.tcap new file mode 100644 index 0000000..df5fb60 --- /dev/null +++ b/doc/Eterm.tcap @@ -0,0 +1,44 @@ +# termcap for rxvt (and xterm) -- (modified from the Midnight Commander) +# +# From: Jakub Jelinek 1 Sep 1995 +# This is a checked termcap entry for the xterm terminal emulator. +# It is compatible with the enclosed terminfo entry. +# Install this by cutting off the old xterm entry from /etc/termcap +# and replacing that place it with this file. +# Heavily based on xterm from: +# Eric S. Raymond 30 Mar 1995 +# Note: If you use the line-drawing character set, the disable afterwards +# will leave you in US-ASCII. If you live somewhere that wants a pound sign +# at 2/3, change rmacs to "\E(A". Further note: cuf and cub don't seem +# to be reliable under my xterm, so they're commented out. +#------------------------------------------------------------------------- + +xterm|vs100|xterm terminal emulator (X11R6 Window System):\ + :am:bs:km:mi:ms:pt:xn:xo:co#80:li#24:it#8:\ + :AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:\ + :IC=\E[%d@:LE=\E[%dD:UP=\E[%dA:\ + :ac=++\054\054..00II--``aaffgghhjjkkllmmnnooqqssttuuvvwwxx~~:\ + :ae=\E(B:al=\E[L:as=\E(0:bl=^G:cd=\E[J:ce=\E[K:\ + :cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\ + :ct=\E[3k:dc=\E[P:dl=\E[M:ei=\E[4l:ho=\E[H:\ + :ic=\E[@:im=\E[4h:\ + :is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l\E[4l:\ + :k0=\E[21~:\ + :k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~:k5=\E[15~:\ + :k6=\E[17~:k7=\E[18~:k8=\E[19~:k9=\E[20~:k;=\E[21~:\ + :F1=\E[23~:F2=\E[24~:F3=\E[25~:F4=\E[26~:\ + :F5=\E[28~:F6=\E[29~:F7=\E[31~:F8=\E[32~:F9=\E[33~:FA=\E[34~:\ + :*0=\E[1~:kI=\E[2~:kD=\E[3~:*6=\E[4~:kP=\E[5~:kN=\E[6~:\ + :kh=\E[7~:@7=\E[8~:kB=\E[Z:\ + :ke=\E>:ks=\E=:\ + :ku=\E[A:kd=\E[B:kr=\E[C:kl=\E[D:\ + :K1=\EOw:K3=\EOy:K2=\EOu:K4=\EOq:K5=\EOs:\ + :kb=^H:up=\E[A:do=^J:nd=\E[C:le=^H:\ + :md=\E[1m:me=\E[m:mr=\E[7m:\ + :r2=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l\E[4l\E<:\ + :rc=\E8:sc=\E7:se=\E[m:sf=^J:so=\E[7m:sr=\EM:ta=^I:\ + :te=\E[2J\E[?47l\E8:ti=\E7\E[?47h:u6=\E[%d;%dR:\ + :u7=\E[6n:u8=\E[?1;2c:u9=\E[c:ue=\E[m:\ + :us=\E[4m: +xterm-color|color-xterm|xterm with color support:\ + :tc=xterm:tc=ansi-pc-color: diff --git a/doc/Eterm.ti b/doc/Eterm.ti new file mode 100644 index 0000000..336aa7f --- /dev/null +++ b/doc/Eterm.ti @@ -0,0 +1,147 @@ +#------------------------------------------------------------------------- +# terminfo for Eterm (and xterm) -- [modified from the Midnight Commander] +# +# Install using `tic Eterm.ti', to be used with the enclosed termcap +#------------------------------------------------------------------------- + +xterm-basic|xterm terminal base (X Window System), + am, km, mir, msgr, xenl, xon, cols#80, lines#24, it#8, +# Not sure about eo (Erase overstrike with a blank) + eo, + cr=\r, bel=^G, + +# Scroll text up, down + ind=\n, ri=\EM, + +# Clear Screen, EOS, EOL, BOL + clear=\E[H\E[2J, ed=\E[J, el=\E[K, el1=\E[1K, + +# Change Scroll Region + csr=\E[%i%p1%d;%p2%dr, + +# Cursor Position + cup=\E[%i%p1%d;%p2%dH, + +# Horizontal & Vertical Position Absolute + hpa=\E[%i%p1%dG, vpa=\E[%i%p1%dd, + +# Cursor Up/Down/Forward/Backward: any, 1 char + cuu=\E[%p1%dA, cud=\E[%p1%dB, cuf=\E[%p1%dC, cub=\E[%p1%dD, + cuu1=\E[A, cud1=\E[B, cuf1=\E[C, cub1=\b, + +# Misc cursor motion + home=\E[1;1H, + +# Enter insert mode, leave insert mode + smir=\E[4h, rmir=\E[4l, + +# Set tab stops, clear tab stops, tab character + hts=\EH, tbc=\E[3g, ht=\t, + +# Make cursor invisible, normal, bold + civis=\E[?25l, cnorm=\E[?25h, cvvis=\E[?25h, + +# Save/Restore Cursor position + sc=\E7, rc=\E8, + +# Alternate Char Set (line drawing), enable/enter/exit ACS + acsc=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, + enacs=\E(B\E)0, smacs=\E(B\E)U^N, rmacs=\E(B\E)0^O, + +#-- begin AIX 3.2.5 hack +# acsc (box2 is the standard AIX form, box1 has been changed to work!) +# box1=llqqkkxxjjmmwwuuvvttnn, +# box2=lqkxjmwuvtn, +# font0=\E(B, font1=\E(0, +# position occupied by kend +# colf7=\E[8~, +#-- end AIX 3.2.5 hack + +# Delete/Insert: Chars, Lines, 1-char, 1-line + dch=\E[%p1%dP, dl=\E[%p1%dM, + ich=\E[%p1%d@, il=\E[%p1%dL, + dch1=\E[P, dl1=\E[M, + ich1=\E[@, il1=\E[L, + +# Erase Chars + ech=\E[%p1%dX, + +# Enter/Leave Fonts: Bold, Reverse, Blink, Underline +# standout (enter/leave), Define attribs 1-9 + bold=\E[1m, rev=\E[7m, blink=\E[5m, + smul=\E[4m, rmul=\E[24m, smso=\E[7m, rmso=\E[m, + +# visual bell + flash=\E[?5h\E[?5l, + +# Enter/leave keypad transmit, Cursor keys (sent by terminal). Don't touch +# cursor keys! use ANSI cursor keys rather than application cursor keys to +# avoid starting in application cursor mode when `$xterm&' is used and to +# enable the Eterm Shift/Ctrl cursor extensions. + smkx=\E=, rmkx=\E>, + kcuu1=\E[A, kcud1=\E[B, kcuf1=\E[C, kcub1=\E[D, + +# Other nice keys + ka1=\EOw, ka3=\EOy, kb2=\EOu, kc1=\EOq, kc3=\EOs + +# Function keys + kf0=\E[21~, + kf1=\E[11~, kf2=\E[12~, kf3=\E[13~, kf4=\E[14~, kf5=\E[15~, + kf6=\E[17~, kf7=\E[18~, kf8=\E[19~, kf9=\E[20~, kf10=\E[21~, + kf11=\E[23~, kf12=\E[24~, kf13=\E[25~, kf14=\E[26~, + kf15=\E[28~, kf16=\E[29~, kf17=\E[31~, + kf18=\E[32~, kf19=\E[33~, kf20=\E[34~, + +# Find, Insert, Delete, Select, Prior, Next + kfnd=\E[1~, kich1=\E[2~, kdch1=\E[3~, kslt=\E[4~, kpp=\E[5~, knp=\E[6~, +# Home (vt100 may use khome=\E[H), End, Backspace, Enter, Backtab + khome=\E[7~, kend=\E[8~, kbs=\177, kent=\EOM, kcbt=\E[Z, + +# Shifted Right, Left, Delete, Prior, Next, Home, End, Ctrl-End + kRIT=\E[c, kLFT=\E[d, + kDC=\E[3$, kPRV=\E[5$, kNXT=\E[6$, + kHOM=\E[7$, kEND=\E[8$, kel=\E[8^, + +# Reset terminal, turn off all attributes + rs1=\E>\E[1;3;4;5;6l\E[?7h\E[m\E[r\E[2J\E[H, + rs2=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l\E[4l\E>, +# dec.ti +# rs2=@, + +# Init terminal + is1=\E[?47l\E=\E[?1l, + is2=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;3;4;6l\E[4l, + +# Leave/Enter CA-Mode. + smcup=\E7\E[?47h, rmcup=\E[?47l\E8, +# dec.ti +# smcup=\E[?7h\E[?1l\E(B\E=, rmcup=\E[?7h, + +# turn on/off the printer +# mc5=\E[5i, mc4=\E[4i, + mc4=\E[4i, + +# +# XTerm with color support. +# +xterm|vs100|xterm terminal emulator (X Window System), + use=xterm-basic, +# sgr=\E[0%?%p1%p6%|%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t^N%e^O%;, + sgr=\E[%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;m, + sgr0=\E[m^O, +# from dec.ti +# sgr0=\E[m\E(B, +# sgr0=\E[m, +# sgr=\E[%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;m%?%p9%t\E(0%e\E(B%;, + +xterm-color|color-xterm|Eterm|eterm|color xterm terminal emulator (X Window System), + use=xterm, colors#8, pairs#64, + +# Set all color pairs to the original ones +# op=\E[0m, + op=\E[39;49m, + +# Set foreground color, background color + setf=\E[%p1%{30}%+%dm, setb=\E[%p1%{40}%+%dm, + +#--------------------------------------------------------------------- eof diff --git a/doc/Eterm_reference.html b/doc/Eterm_reference.html new file mode 100644 index 0000000..a1ec10c --- /dev/null +++ b/doc/Eterm_reference.html @@ -0,0 +1,1469 @@ + + + + + +

+ +

+This document covers the technical aspects of Eterm, including escape sequences +it supports, "under-the-hood" descriptions of certain Eterm features, etc. +Portions of this document were taken from the XTerm documentation.

+ +

Table of Contents

+
    +
  1. Document Conventions +
  2. Symbols +
  3. Escape Sequences + +
  4. Key Sequences +
  5. Eterm Extensions, Standards, and Implementations + +
+ +

Document Conventions

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ConventionMeaning
cA literal. It should be typed as shown.
SYMA symbol. Replace with the proper character. See the symbol table below + for a listing of the symbols used and their meanings.
textA parameter. Replace the italicized text with a parameter. The text + itself generally describes the type of parameter needed.
[ ... ]Items enclosed in brackets are optional.
{ ... | ... }Items inclosed in braces and separated by pipes indicate that exactly one + of the items should be chosen.
+
+ +

Symbols

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SymbolMeaning
BELBell (Ctrl-G)
BSBackspace (Ctrl-H)
CRCarriage Return (Ctrl-M)
ENQEnquiry (Ctrl-E), Send Device Attributes (DA). Eterm replies with the + string defined by ESCZ_ANSWER in src/feature.h, which is + ESC[?1;2c by default. This response indicates a VT100 + emulator with Advanced Video Option.
ESCEscape (Ctrl-[)
FF or NPForm Feed or New Page(Ctrl-L)
LF or NLLine Feed or New Line (Ctrl-J)
SIShift In (Ctrl-O), invokes the G0 (default) character set
SOShift Out (Ctrl-O), invokes the G1 (alternate) character set
SPCSpace
TAB or HTHorizontal Tab (Ctrl-I)
VTVertical Tab (Ctrl-K)
+ +

Escape Sequences

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SequenceFunction
ESC { ( | ) | * | + | $ } { 0 | A | B }Select ISO 2022 character sets.
+
    +
  • ( sets the G0 character set +
  • ) sets the G1 character set +
  • * sets the G2 character set +
  • + sets the G3 character set +
  • $ sets the Kanji character set +
+
    +
  • 0 uses the DEC Special Character and Line Drawing set +
  • A uses the United Kingdom (UK) character set +
  • B uses the United States (USASCII) character set +
+
ESC 7Save cursor (SC)
ESC 8Restore cursor (RC)
ESC =Application Keypad (SMKX)
ESC >Numeric Keypad (RMKX)
ESC DIndex (IND)
ESC ENext Line (NEL)
ESC HTab Set (HTS)
ESC MReverse Index (RI)
ESC ZObselete form of Send Device Attributes (DA), which is ESC [ c
ESC [ [ n ] @Insert n blank Characters (ICH). Default for n is 1.
ESC [ [ n ] ACursor Up n times (CUU), default 1
ESC [ [ n ] BCursor Down n times (CUD), default 1
ESC [ [ n ] CCursor Forward n times (CUF), default 1
ESC [ [ n ] DCursor Backward n times (CUB), default 1
ESC [ [ n ] ECursor Down n times and to first column, default 1
ESC [ [ n ] FCursor Up n times and to first column, default 1
ESC [ [ n ] GCursor to Column n (HPA)
ESC [ [ r ; c ] HCursor Position [row;column] (CUP), default 1;1
ESC [ [ n ] IMove forward n tab stops, default 1
ESC [ [ n ] JErase in Display (ED) +
    +
  • n == 0: Clear Below (default) +
  • n == 1: Clear Above +
  • n == 2: Clear All +
+
ESC [ [ n ] KErase in Line (EL) +
    +
  • n == 0: Clear to Right (default) +
  • n == 1: Clear to Left (EL1) +
  • n == 2: Clear All +
+
ESC [ [ n ] LInsert n lines (IL), default 1
ESC [ [ n ] MDelete n lines (DL), default 1
ESC [ [ n ] PDelete n characters (DCH), default 1
ESC [ [ n ] WTabulator functions +
    +
  • n == 0: Tab Set (HTS) +
  • n == 2: Tab Clear (TBC), clear current column (default) +
  • n == 5: Tab Clear (TBC), clear all +
+
ESC [ [ n ] XErase n characters (ECH), default 1
ESC [ [ n ] ZMove backward n tabstops, default 1
ESC [ [ n ] `Same as ESC [ n G (HPA)
ESC [ [ n ] aSame as ESC [ n C (CUF)
ESC [ [ n ] cSend Device Attributes (DA), default of 0 returns + "ESC[?1;2c" indicating a VT100 with advanced video option +
ESC [ [ n ] dCursor to line n (VPA)
ESC [ [ n ] eSame as ESC [ n A (CUU)
ESC [ [ r ; c ] fHorizontal and Vertical Position (HVP), default 1;1
ESC [ [ n ] gTab Clear +
    +
  • n == 0: Tab Clear (TBC), clear current column (default) +
  • n == 3: Tab Clear (TBC), clear all +
+
ESC [ [ n ] iPrinting +
    +
  • n == 4: Disable transparent print mode (MC4) +
  • n == 5: Enable transparent print mode (MC5) +
+
ESC [ n [ ; n ... ] { h | l }
    +
  • h: Set Mode (SM) +
  • l: Reset Mode (RM) +
+
    +
  • n == 4: Insert Mode (SMIR)/Replace Mode (RMIR) +
  • n == 20: Automatic Newline (LNM)/Normal Linefeed (LNM) +
+
ESC [ n [ ; n ... ] mCharacter Attributes (SGR) +
    +
  • n == 0: Normal (default) +
  • n == 1/22: Turn bold (bright fg) on/off +
  • n == 4/24: Turn underline on/off +
  • n == 5/25: Turn "blink" (bright bg) on/off +
  • n == 7/27: Turn inverse on/off +
  • n == 30/40: foreground/background black +
  • n == 31/41: foreground/background red +
  • n == 32/42: foreground/background green +
  • n == 33/43: foreground/background yellow +
  • n == 34/44: foreground/background blue +
  • n == 35/45: foreground/background magenta +
  • n == 36/46: foreground/background cyan +
  • n == 37/47: foreground/background white +
  • n == 39/49: foreground/background default +
+
ESC [ [ n ] nDevice Status Report (DSR) +
    +
  • n == 5: Status Report, returns "ESC[0n" + ("OK") +
  • n == 6: Report Cursor Position (CPR) as + "ESC[r;cR" +
  • n == 7: Request display name (ignored by default for + security reasons) +
  • n == 8: Request version number in window title +
+
ESC [ [ t ; b ] rSet Scrolling Region (CSR), where t is the top row and b is + the bottom row, defaults to the full screen
ESC [ [ n ] xRequest Terminal Parameters (DECREQTPARM)
ESC [ ? n [ ; n ... ] { h | l | s | r | t }DEC Private Modes (shown as set/reset) +
    +
  • h: Set Private Mode (DECSET) +
  • l: Reset Private Mode (DECRST) +
  • s: Save all DEC Private Mode values +
  • r: Restore previously-saved DEC Private Mode values +
  • t: Toggle Private Mode (rxvt/Eterm extension) +
+
    +
  • n == 1: Application/Normal cursor keys (DECCKM) +
  • n == 3: 132/80 column mode (DECCOLM) +
  • n == 4: Smooth/Jump scrolling (DECSCLM) [not yet implemented] +
  • n == 5: Reverse/Normal video (DECSCNM) +
  • n == 6: Origin/Normal cursor mode (DECOM) +
  • n == 7: Wraparound mode on/off (DECAWM) +
  • n == 9: (X10 Xterm mouse reporting) Do/Don't send mouse + coords on button press (see below) +
  • n == 10: Toggle menubar on/off (rxvt/Eterm extension) +
  • n == 25: Visible/invisible cursor +
  • n == 30: Toggle scrollbar on/off (rxvt/Eterm extension) +
  • n == 35: Allow/Disallow xterm shift+key sequences (rxvt/Eterm extension) +
  • n == 40: Allow/Disallow 80 <--> 132 mode +
  • n == 47: Use Alternate/Normal screen buffer +
  • n == 66: Application/Normal keypad (DECPAM) +
  • n == 67: Backspace key sends BS/DEL (DECBKM) +
  • n == 1000: (X11 Xterm mouse reporting) Do/Don't send mouse + coords on button press and release (see + below) +
+
ESC [ n [ ; n [ ... ] ] tWindow Operations +
    +
  • n == 1: Un-iconify window +
  • n == 2: Iconify window +
  • n == 3: Move window. Must by followed by + ;x;y +
  • n == 4: Resize window. Must by followed by + ;height;width +
  • n == 5: Raise window +
  • n == 6: Lower window +
  • n == 7: Refresh window +
  • n == 8: Resize text area. Must by followed by + ;height;width, + with height and width given in + characters. +
  • n == 11: Report icon state. (not implemented) +
  • n == 13: Report window position as + ESC[3;x;yt +
  • n == 14: Report window size in pixels as + ESC[4;height;widtht +
  • n == 18: Report text area size in characters as + ESC[4;height;widtht +
  • n == 20: Report icon name as + ESC]LnameESC\ +
  • n == 21: Report window title as + ESC]ltitleESC\ +
+
ESC ] n ; string BELSet Text Parameters +
    +
  • n == 0: Change icon name and window title to string +
  • n == 1: Change icon name to string +
  • n == 2: Change window title to string +
  • n == 10: Menubar commands (see below) +
  • n == 20: Pixmap commands (see below) +
  • n == 39: Set the default foreground color to string +
  • n == 49: Set the default background color to string +
  • n == 50: Set font to string. rxvt/Eterm extensions: +
      +
    • string == "#+n": Change font up by n, default 1 +
    • string == "#-n": Change font down by n, default 1 +
    • string empty: Change to font 0 +
    • string == "#n": Change to font n +
    +
+
ESC ] { l | L | I } string ESC \
    +
  • l: Change window title to string +
  • L: Change icon name to string +
  • I: Read new icon image from file whose path is string +
+
ESC cFull Reset (RIS)
ESC nInvoke the G2 character set (LS2)
ESC oInvoke the G3 character set (LS3)
+ +

Menubar Escape Sequences

+ +

+The menubar system in Eterm is probably the most complex, convoluted, +complicated, and poorly-implemented feature of Eterm. The code, though +modified somewhat, is still almost entirely derived from rxvt. It will be +rewritten from scratch as part of +Project Resurrection, but +for now, here are the basics. You'll probably want to look at the menubar +files that come with Eterm; they're pretty good samples.

+ +

+First, let's discuss the paradigm used by the menubar system. Like so many +things these days, the menubar uses a filesystem analogy, with the menubar +itself comprising the top level (root) and each menu and submenu is a +"directory" or "subdirectory" thereof. You manipulate the contents of the +menubar by adding and removing menus, menu items, and submenus via their +respective "paths." You even have a "working directory" and can add/remove +several items at a time by changing to the directory you want.

+ +

+The following table shows the commands which are recognized by the menubar +system. These commands can be supplied as string in the menubar escape +sequence, or they can be lines in a menubar file.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CommandAction
= titleSet the menubar title to title. Note that the menubar title is + entirely separate from Eterm's titlebar text. Any occurance of + %v in title is replaced by the Eterm version. + %n is replaced by the resource name (as specified by the + -n option. %% inserts a literal '%'. +
[ + ] pathChange directories to path. If path doesn't exist, it is + created. / represents the menubar itself. + /some_menu/ represents a primary menu in the + menubar. /some_menu/submenu/ + represents a submenu underneath that menu. And so on.... You can also + use "." and ".." just like you would on a UNIX filesystem. +
-pathRemoves the menu at path. All submenus and menu items are + automatically removed. +
[ + ] [ path ] { menuitem } [ + { rtext } ] [ { action } ] + Add a menu item at path. The label (menuitem) is required + but can be hidden by using a dot ('.') as the first + character of menuitem, or by using the same text for rtext. + The optional string rtext will be right-justified; this is + generally used to note the key sequence bound to a particular menu item. + If action is not specified, the contents of rtext are + used.

+

+ action is the string which is bound to the menuitem. It is parsed + for escape sequences, control characters, etc. See the table below for a + list of valid encodings. If action begins with a NUL character + (^@), the string is sent to Eterm instead of to the + application. (To send a string beginning with a NUL to the application, + simply prefix the string with two NUL's. The first one will be stripped + and the remainder send to the application.) So any escape sequences you + want Eterm to parse should begin with ^@.

+

+ As mentioned in the table below, M- can be used as a + substitute for ESC in an action string, with one difference: + a carriage return (\r) is appending automatically to + any string that begins with M- and does not already have + the trailing CR.

+

+ To add a separator bar, specify - as menuitem.

+
- [ path ] { menuitem }Removes menuitem.
[apptitle: title ]Sets Eterm's titlebar title to title. Not to be confused with the + [title:] command, which sets the menubar title. +
[clear]Clears the menubar of all menus. Equivalent to rm -rf / + on a UNIX filesystem. +
[done [ : tag ] ]Sets the current menubar to read-only. No modification attempts will be + accepted (unless they are enclosed in [::]; see below). +
[dump]Dumps the current menubars out to a file. The path of this file is placed + in the Eterm titlebar. The menubars are dumped so that the resulting file + is a valid Eterm menubar file which can be parsed by Eterm in the future + to restore the current menubar settings. +
[echo: text ]Sends text to the application running in the Eterm window.
[hide]Hides (toggles off) the menubar and sets it to read-only.
[menu [ : name ] ]Begin addition/modification of the name menubar. If name is + not given, "default" is used. This command sets the + menubar to read-write.
[pixmap: string ]A convenience command. string should follow the syntax shown in + the Pixmap Escape Sequences section below. +
[read: file ]Reads the menubar file file and parses the commands it contains. A + menubar file consists of commands shown in this table. Lines beginning + with '#' and blank lines are ignored. +
[rm [ : ] [ spec ] ]Removes part or all of the contents of a menubar. spec can be a + path, a menu item, or '*', or empty. The latter two + remove all menus in the menubar. +
[show]Shows (toggles on) the menubar and sets it to read-only.
[title: title ]Sets the menubar title to title
[:command:]Specifies that the current menu's read-only status should be ignored in + order to parse command. command should be one of the above + commands. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Escaped StringMeaning
Backslash-Escaped Characters (case is ignored)
\aBEL (Alert)
\bBS
\cXInterpreted as Ctrl-X. Analogous to ^X.
\eESC
\fFF
\nLF
\rCR
\tTAB
\vVT
\nnnnnn is interpreted as an octal number, and the corresponding + character is inserted. +
Convenience Shortcuts
^XInterpreted as Ctrl-X. X can be any character between + @ and _. Case is ignored. +
C-XInterpreted as Ctrl-X. Analogous to ^X.
M-XInterpreted as ESC followed by X. Analogous to + \eX. If the string begins with M-, + a CR is automatically appended to the end of the string if not + already present. +
+ +

Pixmap Escape Sequences

+ +

+The string supplied to the pixmap escape sequence (above) consists of a +filename (which can be empty) followed by a semicolon, then one or more +geometry strings. The following table shows the valid geometry strings and +their affects on the background pixmap:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StringFunction
?Query scale and position (generally disabled)
Adjusting scaling and position
WxH+X+YSet scaling to W% by H%, and position to X% by + Y%. W and H are percentages of the original image + size. The position is a percentage, where +50+50 centers the + pixmap in the window.
WxH+XAssumes Y == X
WxHAssumes Y == X == 50 (centers the pixmap)
W+X+YAssumes H == W
W+XAssumes H == W and Y == X
WAssumes H == W and Y == X == 50
Adjusting position only
=+X+YSet position to X% by Y% (absolute).
=+XSet position to X% by X%.
+X+YAdjust position horizontally X% and vertically Y% from + current position (relative).
+X+XAdjust position horizontally X% and vertically X% from + current position.
Adjusting scale only
Wx0Multiply horizontal scaling factor by W%
0xHMultiply vertical scaling factor by H%
+ +

+Examples:

+ +
    +
  • "\e]20;Dragon.jpg\007" -- Set background image to + "Dragon.jpg" +
  • "\e]20;Canyon.jpg;200\007" -- Set background image to + "Canyon.jpg", scaling to 200% by 200%, and center it. +
  • "\e]20;;100\007" -- Set scaling back to 100% +
  • "\e]20;blackstone.png;0x0\007" -- Set background image to + "blackstone.png" and tile it +
  • "\e]20;;0x0\007" -- Tile current image instead of scaling +
+ +

Mouse Reporting

+ +

+When Eterm receives a mouse reporting request (and if mouse reporting is +currently enabled), it replies with the sequence +"ESC[Mbxy". The values for b, x, and +y are as follows (subtract the value of space ' ' first):

+ +
    +
  • Button status: The lower 2 bits of b indicate the button status, + with 00 indicating Button1 down, 01 indicating Button2 down, 10 indicating + Button3 down, and 11 indicating the button was released. (button = + b & 0x3 - ' ') +
  • Modifier status: The upper bits of b are used to flag which + modifiers were active when the button was pressed. The low bit is the + Shift flag, the middle is Meta, and the high bit is Control. (mod = + b & 0x1c - ' ') +
  • Coordinates: x and y are the column and row, respectively. + (c = x - ' '; r = y - ' ') +
+ +

Key Sequences

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Cursor Keys
Key PressedWhat Eterm Sends
NormalShiftControlApplication
UpESC [ AESC [ aESC O aESC O A
DownESC [ BESC [ bESC O bESC O B
RightESC [ CESC [ cESC O cESC O C
LeftESC [ DESC [ dESC O dESC O D
Special Keys
Key PressedNormalShiftControlControl+Shift
Tab^IESC [ Z^I 
Backspace^H^?^? 
Home (Find)ESC [ 1 ~ESC [ 1 $ESC [ 1 ^ESC [ 1 @
End (Select)ESC [ 4 ~ESC [ 4 $ESC [ 4 ^ESC [ 4 @
InsertESC [ 2 ~Paste mouse selectionESC [ 2 ^ESC [ 2 @
Delete (Execute)ESC [ 3 ~ESC [ 3 $ESC [ 3 ^ESC [ 3 @
PageUp (Prior)ESC [ 5 ~Scroll up one pageESC [ 5 ^ESC [ 5 @
PageDown (Next)ESC [ 6 ~Scroll down one pageESC [ 6 ^ESC [ 6 @
Function Keys (Note: Shift-F1 through F10 sends F11-F20)
Key PressedNormalShiftControlControl+Shift
F1ESC [ 11 ~ESC [ 23 ~ESC [ 11 ^ESC [ 23 ^
F2ESC [ 12 ~ESC [ 24 ~ESC [ 12 ^ESC [ 24 ^
F3ESC [ 13 ~ESC [ 25 ~ESC [ 13 ^ESC [ 25 ^
F4ESC [ 14 ~ESC [ 26 ~ESC [ 14 ^ESC [ 26 ^
F5ESC [ 15 ~ESC [ 28 ~ESC [ 15 ^ESC [ 28 ^
F6ESC [ 17 ~ESC [ 29 ~ESC [ 17 ^ESC [ 29 ^
F7ESC [ 18 ~ESC [ 31 ~ESC [ 18 ^ESC [ 31 ^
F8ESC [ 19 ~ESC [ 32 ~ESC [ 19 ^ESC [ 32 ^
F9ESC [ 20 ~ESC [ 33 ~ESC [ 20 ^ESC [ 33 ^
F10ESC [ 21 ~ESC [ 34 ~ESC [ 21 ^ESC [ 34 ^
F11ESC [ 23 ~ESC [ 23 $ESC [ 23 ^ESC [ 23 @
F12ESC [ 24 ~ESC [ 24 $ESC [ 24 ^ESC [ 24 @
F13ESC [ 25 ~ESC [ 25 $ESC [ 25 ^ESC [ 25 @
F14ESC [ 26 ~ESC [ 26 $ESC [ 26 ^ESC [ 26 @
F15 (Help)ESC [ 28 ~ESC [ 28 $ESC [ 28 ^ESC [ 28 @
F16 (Menu)ESC [ 29 ~ESC [ 29 $ESC [ 29 ^ESC [ 29 @
F17ESC [ 31 ~ESC [ 31 $ESC [ 31 ^ESC [ 31 @
F18ESC [ 32 ~ESC [ 32 $ESC [ 32 ^ESC [ 32 @
F19ESC [ 33 ~ESC [ 33 $ESC [ 33 ^ESC [ 33 @
F20ESC [ 34 ~ESC [ 34 $ESC [ 34 ^ESC [ 34 @
Keypad
Key PressedNormalApplication
KP_Enter^MESC O M
KP_F1ESC O PESC O P
KP_F2ESC O QESC O Q
KP_F3ESC O RESC O R
KP_F4ESC O SESC O S
XK_KP_Multiply*ESC O j
XK_KP_Add+ESC O k
XK_KP_Separator,ESC O l
XK_KP_Subtract-ESC O m
XK_KP_Decimal.ESC O n
XK_KP_Divide/ESC O o
XK_KP_00ESC O p
XK_KP_11ESC O q
XK_KP_22ESC O r
XK_KP_33ESC O s
XK_KP_44ESC O t
XK_KP_55ESC O u
XK_KP_66ESC O v
XK_KP_77ESC O w
XK_KP_88ESC O x
XK_KP_99ESC O y
+ +

Eterm Extensions, Standards, and Implementations

+ +

+ +

Eterm Proprietary Escape Sequences

+ +

+The table below contains a listing of all the Eterm-specific escape sequences +that Eterm supports. These sequences were created by the Eterm authors. Please +note the following conventions used in this table:

+ +

+When an escape sequence is said to "set/toggle" an option, this means that the +boolean parameter of the sequence is optional. If given, it will either set or +unset the option. If omitted, the current state of that option will be +reversed (i.e., turned off if on, or on if off). Acceptable values for "true" +are: 1, on, yes, or (of course) +true. Likewise, acceptable values for "false" are: +0, off, no, or +false.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SequenceFunction
ESC [ 9 nTitlebar Status. This places Eterm's current status in the titlebar. The + status information includes the application name and version number, as + well as the shading/tinting state if transparent, the pixmap path if their + is a background pixmap, or "No Pixmap" if neither of these is true. +
ESC ] 5 ; BELSteal Focus. Eterm will raise itself to the top and steal keyboard/mouse + focus. This is useful in case your window manager dies or has trouble + starting up. By default, this is activated by holding the Ctrl key and + clicking on the Eterm window with the left mouse button (Button1). +
ESC ] 6 ; 0 [ ; boolean ] BELSet/toggle transparency state.
ESC ] 6 ; 1 ; pct BELSet shading percentage to pct.
ESC ] 6 ; 2 ; mask BELSet tint mask to mask. As a favor to keebler, I left support for + the old text aliases in the escape sequence parser. Thus, the following + are supported as alternative values for mask: +
    +
  • none: 0xffffff +
  • red: 0xff8080 +
  • green: 0x80ff80 +
  • blue: 0x8080ff +
  • cyan: 0x80ffff +
  • magenta: 0xff80ff +
  • yellow: 0xffff80 +
+
ESC ] 6 ; 3 ; BELForce an update the of transparency background.
ESC ] 6 ; 4 [ ; boolean ] BELSet/toggle desktop watching.
ESC ] 6 ; 10 ; [ type ] [ ; width ] BELSet scrollbar style to type and scrollbar width to width. + If specified, type must be one of motif, + xterm, or next. If you omit the + type parameter and only wish to set the width, take care not to + omit the extra semicolon. width is an integer. Its value is + fairly wide-open, but should be something reasonable. +
ESC ] 6 ; 11 [ ; boolean ] BELSet/toggle right-side scrollbar. +
ESC ] 6 ; 12 [ ; boolean ] BELSet/toggle floating scrollbar (i.e., one with no trough).
ESC ] 6 ; 13 [ ; boolean ] BELSet/toggle popup scrollbar (i.e., one that appears when the window has + focus and disappears when it does not). +
ESC ] 6 ; 15 [ ; boolean ] BELSet/toggle menubar move.
ESC ] 6 ; 20 [ ; boolean ] BELSet/toggle visual bell.
ESC ] 6 ; 21 [ ; boolean ] BELSet/toggle map alert.
ESC ] 6 ; 22 [ ; boolean ] BELSet/toggle xterm's cutchar selection behavior.
ESC ] 6 ; 23 [ ; boolean ] BELSet/toggle selection of the whole line by triple-click.
ESC ] 6 ; 24 [ ; boolean ] BELSet/toggle viewport mode.
ESC ] 6 ; 25 [ ; boolean ] BELSet/toggle selection trailing spaces.
ESC ] 6 ; 50 ; desktop BELMove Eterm to desktop desktop and make it the current desktop. + This requires a GNOME-compliant Window Manager, such as + Enlightenment. +
ESC ] 6 ; 70 BELExit Eterm (most useful from a menubar).
ESC ] 6 ; 71 [ ; path ] BELSaves the current configuration to the current theme directory, or to + path if specified. If a file of the same name already exists, it + is renamed to path.YYYYMMDD.HHMMSS (where + YYYYMMDD.HHMMSS is the current system time). +
+ +

Transparency

+ +

+The standard for implementing transparency was a mutual effort between myself, +Carsten Haitzler , Gerald Britton , and +Nat Friedman , based off of an original idea by Nat. First I'll +define the standard, then I'll discuss its justification.

+ +

+There are two separate procedures for setting the transparency property (the +_XROOTPMAP_ID atom in X). The first is for persistent X clients such as window +managers. These clients should proceed through their normal mechanism for +setting the desktop image. Once the finalized pixmap has been created, the +_XROOTPMAP_ID property should be set on the desktop window (the same window +which will receive the pixmap...note that this is not necessarily the root +window), and its value should be set to the Pixmap ID. The following sample +code (taken from Enlightenment) demonstrates this:

+ +
+/* disp is the Display, win is the desktop Window, pmap is the pixmap */
+static Atom prop = 0;
+
+if (!prop) {
+  prop = XInternAtom(disp, "_XROOTPMAP_ID", False);
+}
+XChangeProperty(disp, win, prop, XA_PIXMAP, 32, PropModeReplace,
+                (unsigned char *)&pmap, 1);
+XSetWindowBackgroundPixmap(disp, win, pmap);
+XClearWindow(disp, win);
+
+ +

+The second procedure is for temporary clients; i.e., clients who set the desktop +pixmap and then exit. An example of this type of client would be Esetroot, the +transparency utility provided with Eterm. These clients should set the +_XROOTPMAP_ID property just like the persistent client does. They should also +set a companion property as well, ESETROOT_PMAP_ID. Both are set to the same +pixmap ID. When a temporary client runs, it checks to see if _XROOTPMAP_ID and +ESETROOT_PMAP_ID have the same value. If so, the client knows that it can +safely do an XKillClient() on the pixmap ID. This will save memory, as the +old pixmap can be removed. If they are not equal, however, calling +XKillClient() would kill the persistent client which did set it, most likely the +user's window manager. This would be a Bad Ideatm. The following +code fragment (taken from Esetroot) illustrates this process:

+ +
+/* disp is the Display, win is the desktop Window, pmap is the pixmap */
+Atom prop_root, prop_esetroot, type;
+int format;
+unsigned long length, after;
+unsigned char *data_root, *data_esetroot;
+
+/* First check to see if the properties already exist, and if they are equal */
+prop_root = XInternAtom(disp, "_XROOTPMAP_ID", True);
+prop_esetroot = XInternAtom(disp, "ESETROOT_PMAP_ID", True);
+
+if (prop_root != None && prop_esetroot != None) {
+  XGetWindowProperty(disp, win, prop_root, 0L, 1L, False, AnyPropertyType,
+                     &type, &format, &length, &after, &data_root);
+  if (type == XA_PIXMAP) {
+    XGetWindowProperty(disp, win, prop_esetroot, 0L, 1L, False, AnyPropertyType,
+                       &type, &format, &length, &after, &data_esetroot);
+    if (data_root && data_esetroot && type == XA_PIXMAP && *((Pixmap *) data_root) == *((Pixmap *) data_esetroot)) {
+      /* It's safe.  Kill the pixmap. */
+      XKillClient(disp, *((Pixmap *) data_root));
+    }
+  }
+}
+
+/* This will locate the property, creating it if it doesn't exist */
+prop_root = XInternAtom(disp, "_XROOTPMAP_ID", False);
+prop_esetroot = XInternAtom(disp, "ESETROOT_PMAP_ID", False);
+
+/* The call above should have created it.  If that failed, we can't continue. */
+if (prop_root == None || prop_esetroot == None) {
+  fprintf(stderr, "Error:  Creation of pixmap property failed.\n");
+  exit(1);
+}
+XChangeProperty(disp, win, prop_root, XA_PIXMAP, 32, PropModeReplace,
+                (unsigned char *) &pmap, 1);
+XChangeProperty(disp, win, prop_esetroot, XA_PIXMAP, 32, PropModeReplace,
+                (unsigned char *) &pmap, 1);
+XSetCloseDownMode(disp, RetainPermanent);
+
+ +

+When the client runs, it looks for the _XROOTPMAP_ID property on the desktop +window. (The client searches through all its parent windows until it either +finds one with this property set, or hits the root window without finding it.) +If the client finds this property, it can then use the pixmap directly, or make +a copy of the pixmap in order to perform additional operations on it (such as +brightening, shading, tinting, etc.).

+ +

+So why use this technique? Why require such support from the window manager and +other external applications? Why not simply set the background to +ParentRelative and be done with it? let X handle everything? This +seems to be a point of great confusion lately. Those who have taken the time to +put the other terminal emulators who have chosen the latter route through their +paces already know the answer: Power. Very simply, you have *much* greater +power and flexibility with this technique than any other. X only permits a +limited amount of flexibility when copying the background directly (basically +just bitwise logical operations). The above technique allows programs to tint, +shade, brighten, or otherwise manipulate the image in *any* way they see fit. +Want a 10% shade? A 30% shade? Maybe a light cyan tint? Or perhaps you prefer +a midnight blue tint.... With this technique, you can have it *your* way, not +their way.

+ diff --git a/doc/FAQ.html b/doc/FAQ.html new file mode 100644 index 0000000..69a635d --- /dev/null +++ b/doc/FAQ.html @@ -0,0 +1,534 @@ + + + + +Eterm FAQ + + + + +

Eterm FAQ

+

+

Contents

+

+

+ +
+

Q&A

+

+

How do I know which version of Eterm I am running?

+

+Eterm always displays its current version at the top of the options list +on the usage screen. You can view the usage screen by envoking Eterm with +the -h or --help option. Also, you can place the current +version number in the Eterm title bar using the escape sequence "ESC[8n". +

+


+

Why did you have to go and change all the options!?

+

+There are several reasons we chose to do this: +
+

    +
  1. To make Eterm's command-line option mechanisms be POSIX- and GNU-compliant. +
  2. To allow for shorter synonyms for the most frequently-used options. +
  3. We were sick of the obfuscated nature of the xterm options. +
  4. We felt like it. +
+For those who don't know, POSIX-standard option syntax uses single-letter options +which can be combined on the command line (e.g., the "-xvf" in a tar command), +among other things. GNU-standard options (also known as "long options") begin +with two hyphens and make it very easy to tell what an individual option +controls (e.g., --background-pixmap, whose POSIX synonym is -P). +

+
+

Why isn't my .Xdefaults being parsed any more?

+

+This is another change made as of DR 0.6. Since it is Eterm (Enlightened term, +intended for use with The +Enlightenment Window Manager), we chose to have it read a config file +very similar to Enlightenment's own MAIN. + +

+Eterm 0.7 has support for themes. (See the later question, +"What constitutes an Eterm theme?", for more info +on themes.) By default, the make install will copy the themes +from the themes/* directories into the $libdir/Eterm/themes/ directory +(/usr/local/lib/Eterm/themes by default). It will no longer read +~/.Eterm/MAIN, but instead will look for the Eterm theme if no +theme is specified on the command line.

+ +

+
+

Well then why isn't the Eterm theme MAIN file being parsed?

+

+The most likely cause of this (besides not having one :-) is not having the +proper "magic number" line at the top of your config file. As of DR 0.6a, +the first line of your config file must look like:
+

+<Eterm-0.6a>
+
+ +

+This "magic number" mechanism prevents Eterm from trying to read an Enlightenment +config file as its own, and it may provide backward compatibility in the future. +The "0.6a" part represents the version of Eterm for which the config file was +written (without the "DR" if there is one). +

+


+

Where do I find out what you've changed for each release?

+

+There is a file called RELNOTES.Eterm in the base directory of each +Eterm distribution. Those release notes give information about what changes +were made in each release, plans for future changes, etc. +

+


+

What information/help files are in the Eterm distribution?

+

+Here is a list: +

    +
  • doc/FAQ -- A preliminary Eterm FAQ. This document will soon replace it. +
  • doc/colortest.sh -- A script to demonstrate Eterm's color capabilities. +
  • doc/Eterm.ref -- Eterm technical reference. Exhaustive list of all supported escape sequences. +
  • doc/menu.sh -- A script to demonstrate Eterm's menubar code. +
  • doc/Eterm.tcap -- Sample Eterm termcap file. +
  • doc/Eterm.ti -- Sample Eterm terminfo file. Compile with tic. +
  • doc/Eterm.help -- Output of Eterm --help (until we get a new man page). +
  • doc/Eterm.1 -- Old Eterm man page. Does not reflect changes in DR 0.6. +
  • RELNOTES.Eterm -- Eterm release notes. Read this!! +
  • INSTALL -- A script that does the configure, compile, link, and install for you. +
+
+

Do I need this file called Eterm-bg.tar.gz?

+

+One of Eterm's most notable features is its ability to put images (called pixmaps by +convention) in the background of your terminal windows. Eterm-bg.tar.gz +(obtainable from any Eterm site) contains about 14 Meg worth of cool pixmaps to +try. It's completely optional. If you do get it, be sure to untar it into your +home directory. It puts the images in .Eterm/pix/ underneath wherever +you install it. I also left the .xvpics directory intact, so you can use +the Visual Schnauzer to preview the pixmaps. +

+


+

The man page is all wrong! What's up with that?

+

+The man page for Eterm DR 0.6 and later is not finished yet. Stay tuned to these +pages. I'll post it here as soon as it's ready. +

+


+

Why did the mouse selection thing suddenly quit working?

+

+Make sure that mouse reporting is actually turned off. Unfortunately, some editors +do not properly turn off mouse reporting when they are abnormally terminated. The +tcsh shell may also use mouse reporting unless explicitly turned off. You can check +this by trying the selection/cut/paste while holding down Alt or Shift. See the +Technical Reference (doc/Eterm.ref) for more detailed information. +

+


+

The docs keep mentioning blinking text, but I can't get it to work. What am I doing wrong?

+

+You aren't doing anything wrong. Eterm does not support, and probably never will +support, blinking text. Instead (assuming NO_BRIGHTCOLOR is *not* defined during +compilation), Eterm uses the bold and blink attributes to provide high-intensity +versions of the foreground and background colors respectively. In general, +colors 0-7 are the low-intensity colors, and colors 8-15 are the corresponding +high-intensity colors. (So color 8 is a "bold" color 0, color 9 is a "bold" +color 1, etc.) It is worth noting that some programs break this convention and +use colors 8-15 to provide 16 total colors, none of which bear any relationship +to any other based on their color number. + +

+Related to this issue is the question of how the default foreground and +background colors are treated (those specified by the -f (--foreground-color) +and -b (--background-color) options) with respect to the bold and blink +attributes. In the simplest (and most common) case, the fg/bg colors each match +one of the low-intensity colors (0-7). If this is true, the bold/blink +attributes (respectively) activate the corresponding high-intensity color +(8-15). + +

+If this is not the case, and either the foreground color or the background +color does not match any of the 8 low-intensity colors, slightly different +action must be taken. In the former case, the bold foreground is simulated +using an overstrike mechanism *. In the +latter case, the blink attribute is simply ignored. + +

+* This feature is dependent upon NO_BOLDOVERSTRIKE +not being defined during compile. Furthermore, its use is discouraged and +unsupported, as it tends to create "pixel droppings." +

+


+

How do I change the screen colors?

+

+You can change the colors 0-15 in your Eterm configuration file. These settings, +taken from themes/Eterm/MAIN, are Rasterman's colors which he says work well +for displaying ANSI art: + +

+    color  0 0    0    0
+    color  1 0xaa 0    0
+    color  2 0    0210 0
+    color  3 0xaa 0x55 0x22
+    color  4 0    0    0xaa
+    color  5 0xaa 0    0xaa
+    color  6 0    0xaa 0xaa
+    color  7 0xaa 0xaa 0xaa
+    color  8 0x44 0x44 0x44
+    color  9 0xff 0x44 0x44
+    color 10 0x44 0xff 0x44
+    color 11 0xff 0xff 0x44
+    color 12 0x44 0x44 0xff
+    color 13 0xff 0x44 0xff
+    color 14 0x44 0xff 0xff
+    color 15 #ffffff
+
+ +

+The syntax for this section is discussed in themes/Eterm/MAIN. + +

+You can also change individual colors on the command line, using the --colorN +options (where N is the number of the color you wish to change). The value can be +either a color name or an RGB triple. For example, --color5=blue or +--color1="#ff0000". +

+


+

What's the deal with Backspace/Delete? Neither seems to work!

+

+The Backspace/Delete problem has plagued UNIX for quite some time now, and there are +no easy answers. This FAQ covers how Eterm handles the two keys; however, detailed +explanations of xmodmap, stty, and so forth are beyond its scope. +The appropriate man pages should be consulted. + +

+First, I'll assume that the Backspace key on your keyboard corresponds to the Backspace +keysym under X. (This is not always the case. See the next question for more details +on this.) There are two standard values that the Backspace key sends: Ctrl-H ("^H") +and Ctrl-? ("^?"). Eterm inherits the "erase" stty setting from the terminal from +which it is started. If it is not started from a terminal (e.g., if it were started +from a window manager button or pull-down menu, or a remote shell), Eterm defaults +to the value of CERASE (defined in <termios.h>). This may not be the same +as the stty settings of your terminal. + +

+When starting a new Eterm, you can set the desired value before calling Eterm: + +

+  $ stty erase ^H
+  $ Eterm
+
+ +or + +
+  $ stty erase ^?
+  $ Eterm
+
+ +

+Remember, you can generate either value using Backspace and Ctrl/Shift-Backspace. You +can also toggle which key is which using the "ESC[36h" and "ESC[36l" escape sequences. + +

+In an existing Eterm, use these commands: + +

+  $ stty erase ^H
+  $ echo -n "^[[36h"
+
+ +or + +
+  $ stty erase ^?
+  $ echo -n "^[[36l"
+
+ +

+Of course, there are other Backspace-related problems. For example, some editors +use termcap/terminfo, but there are some that expect Backspace == ^H regardless. +And then there's GNU Emacs, which binds ^H to help.... My personal solution is +to always use ^H for backspace, and add this line to my .emacs file: + +

+(global-set-key "\C-h" 'delete-backward-char)
+
+ +

+This should cover the Backspace problems. Remember that if you use ^? for Backspace, +you'll need to change the doc/Eterm.ti and doc/Eterm.tcap to +reflect this. + +

+The Delete key (which is supposed to correspond to ^?) has problems of its own. In +an effort to avoid excessive confusion (yeah, right :-) between Backspace and +Delete, Eterm assigns "ESC[3~" to the Delete key, which is the vt100 sequence +for Execute. +

+


+

Why won't my Backspace work under Linux?

+

+Apparently, the XFree86 server elects to map the Backspace key as Delete to match +the Linux console. Besides complaining to the Linux and XF86 people, here's +what you can do about it: + +

    +
  1. Use xmodmap to correct the Backspace mapping. Add this line to your ~/.Xmodmap + file: + +
    +  keycode 22 = BackSpace
    +
    + +Use xev to change the keycode to properly match your machine if needed. This +will also fix the BackSpace problem with Motif applications, like Netscape. +
  2. Remap the Eterm keybindings as described in the next answer. You will lose + the Ctrl/Shift-Backspace and escape sequence toggling functionality discussed + in the previous answer. +
+

+Congratulations! Your Backspace now works as described in the previous answer, so +start from there. +

+


+

How do I change the key bindings in Eterm?

+

+You must compile Eterm with KEYSYM_RESOURCE defined to change key bindings. +Assuming you've done this, you can change the keystrings associated with +keysyms 0xFF00 - 0xFFFF (special keys only) in your Eterm config file. + +

+Here is a sample set of keysym attributes included in the tn3270 theme: + +

+# Delete - ^D
+keysym 0xFFFF "\004"
+
+# Left - ^B
+keysym 0xFF51 "\002"
+# Right - ^F
+keysym 0xFF53 "\006"
+# Up - ^P
+keysym 0xFF52 "\020"
+# Down - ^N
+keysym 0xFF54 "\016"
+# Home - ^A
+keysym 0xFF50 "\001"
+# End - ^E
+keysym 0xFF57 "\005"
+
+# F1 - F12
+keysym 0xFFBE "\e1"
+keysym 0xFFBF "\e2"
+keysym 0xFFC0 "\e3"
+keysym 0xFFC1 "\e4"
+keysym 0xFFC2 "\e5"
+keysym 0xFFC3 "\e6"
+keysym 0xFFC4 "\e7"
+keysym 0xFFC5 "\e8"
+keysym 0xFFC6 "\e9"
+keysym 0xFFC7 "\e0"
+keysym 0xFFC8 "\e-"
+keysym 0xFFC9 "\e="
+
+# map Prior/Next to F7/F8
+keysym 0xFF55 "\e7"
+keysym 0xFF56 "\e8"
+
+
+

My keyboard has some extra keys. How can I use them in Eterm?

+

+The proper way to do this is to use xmodmap to remap the keys needed. +Consult the appropriate man page, as a discussion of xmodmap usage +is beyond the scope of this FAQ. +

+


+

How does a program tell if it's running in an Eterm or an xterm?

+

+It is useful to know whether or not you are in an xterm or an Eterm (or +another terminal emulator that supports color), for purposes of setting +color variables and so forth. To this end, Eterm always sets and exports +the $COLORTERM environment variable, so you can use +test to see if it's set. Many programs (mutt, jed, slrn, etc.) +perform this test for you to determine whether or not to use color. +

+


+

How do I properly set $DISPLAY to the correct, full IP address from a shell?

+

+You must have compiled Eterm with DISPLAY_IS_IP and ENABLE_DISPLAY_ANSWER defined. It +is also wise to define ESCZ_ANSWER properly, or the provided shell code samples +will not work. (You'll need to use $COLORTERM to determine if you +are using an Eterm.) + +

+Here are a couple shell script samples that will properly set your +$DISPLAY, first for Bourne/POSIX-compatible shells, +then for csh-compatible shells. + +

+#!/bin/sh
+# If $TERM is not set, set it to xterm
+[ ${TERM:-empty} = empty ] && TERM=xterm
+
+# If it's an xterm, see if it's an Eterm
+if [ ${TERM:-foo} = xterm ]; then
+  stty -icanon -echo min 0 time 15 
+  echo -n '^[Z'
+  read term_id
+  stty icanon echo
+
+# If it's an Eterm, get $DISPLAY from it.
+  if [ "$term_id" = '^[[?1;2C' -a ${DISPLAY:-empty} = empty ]; then
+    echo -n '^[[7n'
+    read DISPLAY
+  fi
+fi
+----- 8< ----- cut here ----- 8< -----
+#!/bin/csh
+# If $TERM is not set, set it to xterm
+if ( !(${?TERM}) ) then
+  TERM = xterm
+endif
+
+# If it's an xterm, see if it's an Eterm
+if ( ${TERM} =~ xterm ) then
+  stty -icanon -echo min 0 time 15
+  echo -n '^[Z'
+  set term_id=$<
+  stty icanon echo
+  if ( "${term_id}" == "^[[?1;2C" && ${?DISPLAY} == 0 ) then
+    echo -n '^[[7n'
+    setenv DISPLAY "$<"
+  endif
+endif
+
+
+

Why isn't the -n (--name) option working?

+

+This is most often due to the fact that the MAIN file distributed with +some versions of Eterm contains lines that set the title and +iconname attributes. If you comment these lines out, the -n +(--name) option will set the title and icon name if they are not +otherwise explicitly assigned on the command line. +

+


+

Eterm doesn't work on my machine. Help!

+

+One of the primary goals of the Eterm project is portability. We do our +best to write portable code, but we only have a limited number of platforms +on which we have accounts. Therefore, you as the end user are a vital part +of the testing and debugging process. +

+If you run into problems with Eterm, please go through the steps outlined +here. If you make it to the last step +(going in order, of course) with no luck, please do the following:

+
    +
  1. Comment out line 41 of src/feature.h where NDEBUG is defined. +
  2. Recompile Eterm. +
  3. Run the new copy of Eterm and mail the output to me (mej@tcserv.com). +
+This is the only way we can get the information we need about where the +program is when it runs into problems, or what privileges it has, or +whatever. If you do not do this, we cannot help you. +

+
+

Why is 0 sending a Ctrl-C?

+

+This problem was reported by Charles Hagenbuch . I'm not sure +why it happens, but according to Chuck, stty sane fixes it.

+

+
+

What constitutes an Eterm theme?

+

+An Eterm theme consists of a primary configuration file, always called +"MAIN", residing in a directory bearing the same name as the +theme. This directory must be a child of one of the directories +specified by CONFIG_SEARCH_PATH in src/feature.h, in +the environment variable defined by PATHENV in src/feature.h, +or in the default PATH. The theme may also contain additional configuration +files referenced by the primary MAIN file, pixmaps, menu files, documentation, +etc., which are allowable as extensions to the minimum requirement of an +Eterm theme. + +

+By convention, Eterm themes should be stored under +~/.Eterm/themes/<theme_name>/ or +$libdir/themes/<theme_name> + +

+


+

How does Eterm determine which theme to use?

+

+

    +
  1. If the -t or --theme option is specified on the + command line, Eterm will search for, and use if found, the specified + theme. +
  2. Eterm will check to see if it is running under Enlightenment. If + it is, it will query Enlightenment for the current theme name. + It will then search for, and use if found, an Eterm theme by the + same name. (NOTE: This is contingent on Enlightenment having + this capability, so this will not work yet.) +
  3. Eterm will search for, and use if found, a theme called Eterm. +
  4. Eterm will search for, and use if found, a theme called DEFAULT. +
  5. As a last resort, Eterm will search for, and use if found, a + compatible MAIN file. (Recall that this is not a valid Eterm theme.) +
+

+
+

What does this accomplish?

+

+This proposal fulfills both of the primary goals regarding theme +support. On the one hand, it allows for things like "Eterm -t tn3270", +where .../tn3270/MAIN would contain color definitions, +keysym definitions, etc. which would be beneficial to tn3270, but +perhaps detrimental to other applications. + +

+On the other hand, it provides Enlightenment theme authors a relatively- +transparent mechanism for extending the look and feel of their E theme +to their Eterm windows. +

+ +


+ + + + + +
[Powered by Nu-Media Net!] +Copyright © 1997-1995, Michael Jennings. All rights worth squat. These pages are guaranteed to be +100% SPAM(tm)-free or your money back! +
+
+Last modified -- Wednesday, 05 August 1998, 21:19:35 EDT
+ + + + + + diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..3bdcfa8 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,14 @@ +# $Id$ + +man_MANS = Eterm.1 + +all: Makefile Eterm.1.html + +Eterm.1: Eterm.1.in + $(SED) -e 's%@''VERSION''@%$(VERSION)%g' -e 's%@''DATE''@%$(DATE)%g' -e 's%@THEMEDIR@%$(pkgdatadir)/themes%g' $@.in > $@ + +Eterm.1.html: Eterm.1 + -nroff -man $< | man2html > $@ + +EXTRA_DIST = Eterm.1.in Eterm_reference.html Eterm.tcap Eterm.ti FAQ.html Makefile.am Makefile.in + diff --git a/install-sh b/install-sh new file mode 100644 index 0000000..89fc9b0 --- /dev/null +++ b/install-sh @@ -0,0 +1,238 @@ +#! /bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +tranformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/libmej/Makefile.am b/libmej/Makefile.am new file mode 100644 index 0000000..2ae3dd2 --- /dev/null +++ b/libmej/Makefile.am @@ -0,0 +1,12 @@ +# $Id$ + +lib_LTLIBRARIES = libmej.la + +libmej_la_SOURCES = debug.c mem.c strings.c snprintf.c + +INCLUDES = -I. -I.. -I$(includedir) -I$(prefix)/include + +libmej_la_LDFLAGS = -version-info 8:9:8 + +EXTRA_DIST = debug.h global.h mem.h strings.h strptime.h strptime.c + diff --git a/libmej/Makefile.in b/libmej/Makefile.in new file mode 100644 index 0000000..1eca941 --- /dev/null +++ b/libmej/Makefile.in @@ -0,0 +1,372 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# $Id$ + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +AR = @AR@ +AS = @AS@ +AUTHORS = @AUTHORS@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CHMOD = @CHMOD@ +CP = @CP@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CTAGS = @CTAGS@ +DATE = @DATE@ +DBX = @DBX@ +DIST_ROOT = @DIST_ROOT@ +DLLTOOL = @DLLTOOL@ +EGCS = @EGCS@ +FEATURE_CMD = @FEATURE_CMD@ +GDB = @GDB@ +GRLIBS = @GRLIBS@ +IMLIB_CONFIG = @IMLIB_CONFIG@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR = @MKDIR@ +MV = @MV@ +NM = @NM@ +OBJDUMP = @OBJDUMP@ +PACKAGE = @PACKAGE@ +PGCC = @PGCC@ +PSTACK = @PSTACK@ +RANLIB = @RANLIB@ +RM = @RM@ +SED = @SED@ +TAR = @TAR@ +THREADLIBS = @THREADLIBS@ +VERSION = @VERSION@ + +lib_LTLIBRARIES = libmej.la + +libmej_la_SOURCES = debug.c mem.c strings.c snprintf.c + +INCLUDES = -I. -I.. -I$(includedir) -I$(prefix)/include + +libmej_la_LDFLAGS = -version-info 8:9:8 + +EXTRA_DIST = debug.h global.h mem.h strings.h strptime.h strptime.c +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(lib_LTLIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I.. +X_CFLAGS = @X_CFLAGS@ +X_LIBS = @X_LIBS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +libmej_la_LIBADD = +libmej_la_OBJECTS = debug.lo mem.lo strings.lo snprintf.lo +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +GZIP_ENV = --best +DEP_FILES = .deps/debug.P .deps/mem.P .deps/snprintf.P .deps/strings.P +SOURCES = $(libmej_la_SOURCES) +OBJECTS = $(libmej_la_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .lo .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu libmej/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-libLTLIBRARIES: + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + +distclean-libLTLIBRARIES: + +maintainer-clean-libLTLIBRARIES: + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(libdir) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + echo "$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p"; \ + $(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \ + done + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +.s.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.S.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + +maintainer-clean-libtool: + +libmej.la: $(libmej_la_OBJECTS) $(libmej_la_DEPENDENCIES) + $(LINK) -rpath $(libdir) $(libmej_la_LDFLAGS) $(libmej_la_OBJECTS) $(libmej_la_LIBADD) $(LIBS) + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = libmej + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu libmej/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: install-libLTLIBRARIES +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-libLTLIBRARIES +uninstall: uninstall-am +all-am: Makefile $(LTLIBRARIES) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(libdir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-libLTLIBRARIES mostlyclean-compile \ + mostlyclean-libtool mostlyclean-tags mostlyclean-depend \ + mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-libLTLIBRARIES clean-compile clean-libtool clean-tags \ + clean-depend clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-libLTLIBRARIES distclean-compile \ + distclean-libtool distclean-tags distclean-depend \ + distclean-generic clean-am + -rm -f libtool + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-libLTLIBRARIES \ + maintainer-clean-compile maintainer-clean-libtool \ + maintainer-clean-tags maintainer-clean-depend \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-libLTLIBRARIES distclean-libLTLIBRARIES \ +clean-libLTLIBRARIES maintainer-clean-libLTLIBRARIES \ +uninstall-libLTLIBRARIES install-libLTLIBRARIES mostlyclean-compile \ +distclean-compile clean-compile maintainer-clean-compile \ +mostlyclean-libtool distclean-libtool clean-libtool \ +maintainer-clean-libtool tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libmej/debug.c b/libmej/debug.c new file mode 100644 index 0000000..845d34c --- /dev/null +++ b/libmej/debug.c @@ -0,0 +1,55 @@ +/********************************************************* + * DEBUG.C -- Standardized debugging output * + * -- Michael Jennings * + * -- 20 December 1996 * + *********************************************************/ +/* + * This file is original work by Michael Jennings . + * + * Copyright (C) 1997, Michael Jennings + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +static const char cvs_ident[] = "$Id$"; + +#include "global.h" +#include +#include +#ifndef WITH_DMALLOC +# include +#endif +#include +#include +#include +#include +#define DEBUG_C +#include "debug.h" + +int +real_dprintf(const char *format,...) +{ + + va_list args; + int n; + + va_start(args, format); + n = fprintf(stderr, "[debug] "); + n += vfprintf(stderr, format, args); + va_end(args); + fflush(stderr); + return (n); +} diff --git a/libmej/debug.h b/libmej/debug.h new file mode 100644 index 0000000..d96afdb --- /dev/null +++ b/libmej/debug.h @@ -0,0 +1,36 @@ +/********************************************************** + * DEBUG.H -- Header file for DEBUG.C * + * -- Michael Jennings * + * -- 20 December 1996 * + **********************************************************/ +/* + * This file is original work by Michael Jennings . + * + * Copyright (C) 1997, Michael Jennings + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#if !defined(DEBUG_C) && !defined(DEBUG_CC) + extern int real_dprintf(const char *, ...); +#endif + +#ifndef _LIBMEJ_DEBUG_H +# define _LIBMEJ_DEBUG_H + +#include "../src/debug.h" + +#endif /* _LIBMEJ_DEBUG_H */ diff --git a/libmej/global.h b/libmej/global.h new file mode 100644 index 0000000..2a6077b --- /dev/null +++ b/libmej/global.h @@ -0,0 +1,47 @@ +/*************************************************************** + * GLOBAL.H -- Compile-time options header file * + * -- Michael Jennings * + * -- 16 January 1997 * + ***************************************************************/ +/* + * This file is original work by Michael Jennings . + * + * Copyright (C) 1997, Michael Jennings + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _GLOBAL_H_ + +#define _GLOBAL_H_ + +#include "config.h" +#include "src/feature.h" + +/* Other compile-time defines */ +#ifdef LINUX +# define _GNU_SOURCE +# define __USE_GNU +# define _BSD_SOURCE +#elif defined(IRIX) +# define _MODERN_C_ +# define _BSD_TYPES +# define _SGI_SOURCE +#elif defined(HP_UX) + +#endif + +#endif /* _GLOBAL_H_ */ diff --git a/libmej/mem.c b/libmej/mem.c new file mode 100644 index 0000000..97550fc --- /dev/null +++ b/libmej/mem.c @@ -0,0 +1,407 @@ + +/*************************************************************** + * MEM.C -- Memory allocation handlers * + * -- Michael Jennings * + * -- 07 January 1997 * + ***************************************************************/ +/* + * This file is original work by Michael Jennings . + * + * Copyright (C) 1997, Michael Jennings + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +static const char cvs_ident[] = "$Id$"; + +#include "global.h" +#include +#include +#include +#include +#include +#include +#include +#define MEM_C +#include "debug.h" +#include "mem.h" + +/* + * These're added for a pretty obvious reason -- they're implemented towards + * The beginning of each one's respective function. (The ones with capitalized + * letters. I'm not sure that they'll be useful outside of gdb. Maybe. + */ +#if DEBUG >= DEBUG_MALLOC +static int malloc_count = 0; +static int calloc_count = 0; +static int realloc_count = 0; +static int free_count = 0; + +#endif + +MemRec memrec = +{0, 0, 0, (void **) NULL, (size_t *) NULL}; + +char * +SafeStr(register char *str, unsigned short len) +{ + + register unsigned short i; + + for (i = 0; i < len; i++) { + if (iscntrl(str[i])) { + str[i] = '.'; + } + } + + return (str); +} + +void +memrec_init(void) +{ + + memrec.Count = 0; + D_MALLOC(("Constructing memrec\n")); + memrec.Ptrs = (void **) malloc(sizeof(void *)); + + memrec.Size = (size_t *) malloc(sizeof(size_t)); + memrec.init = 1; + +} + +void +memrec_add_var(void *ptr, size_t size) +{ + + memrec.Count++; + if ((memrec.Ptrs = (void **) realloc(memrec.Ptrs, sizeof(void *) * memrec.Count)) == NULL) { + D_MALLOC(("Unable to reallocate pointer list -- %s\n", strerror(errno))); + } + if ((memrec.Size = (size_t *) realloc(memrec.Size, sizeof(size_t) * memrec.Count)) == NULL) { + D_MALLOC(("Unable to reallocate pointer size list -- %s\n", strerror(errno))); + } + D_MALLOC(("Adding variable of size %lu at 0x%08x\n", size, ptr)); + memrec.Ptrs[memrec.Count - 1] = ptr; + memrec.Size[memrec.Count - 1] = size; +#if 0 + memrec_dump(); +#endif +} + +void +memrec_rem_var(void *ptr) +{ + + unsigned long i; + + for (i = 0; i < memrec.Count; i++) + if (memrec.Ptrs[i] == ptr) + break; + if (i == memrec.Count && memrec.Ptrs[i] != ptr) { +#if 0 + memrec_dump(); +#endif + D_MALLOC(("Attempt to remove a pointer not allocated with Malloc/Realloc:" + " 0x%08x\n", ptr)); + return; + } + memrec.Count--; + D_MALLOC(("Removing variable of size %lu at 0x%08x\n", memrec.Size[i], memrec.Ptrs[i])); + memmove(memrec.Ptrs + i, memrec.Ptrs + i + 1, sizeof(void *) * (memrec.Count - i)); + + memmove(memrec.Size + i, memrec.Size + i + 1, sizeof(size_t) * (memrec.Count - i)); + memrec.Ptrs = (void **) realloc(memrec.Ptrs, sizeof(void *) * memrec.Count); + + memrec.Size = (size_t *) realloc(memrec.Size, sizeof(size_t) * memrec.Count); +#if 0 + memrec_dump(); +#endif +} + +void +memrec_chg_var(void *oldp, void *newp, size_t size) +{ + + unsigned long i; + + for (i = 0; i < memrec.Count; i++) + if (memrec.Ptrs[i] == oldp) + break; + if (i == memrec.Count && memrec.Ptrs[i] != oldp) { +#if 0 + memrec_dump(); +#endif + D_MALLOC(("Attempt to move a pointer not allocated with Malloc/Realloc:" + " 0x%08x\n", oldp)); + return; + } + D_MALLOC(("Changing variable of %lu bytes at 0x%08x to one " + "of %lu bytes at 0x%08x\n", memrec.Size[i], memrec.Ptrs[i], size, newp)); + memrec.Ptrs[i] = newp; + memrec.Size[i] = size; +#if 0 + memrec_dump(); +#endif +} + +void +memrec_dump(void) +{ + + unsigned long i, j, k, l, total = 0; + unsigned long len1, len2; + unsigned char *ptr; + unsigned char buff[9]; + + fprintf(stderr, "DUMP :: %lu pointers stored.\n", memrec.Count); + fprintf(stderr, "DUMP :: Pointer | Address | Size | Offset | 00 01 02 03 04 05 06 07 | ASCII \n"); + fflush(stderr); + fprintf(stderr, "DUMP :: ---------+----------+--------+---------+-------------------------+---------\n"); + fflush(stderr); + len1 = sizeof(void *) * memrec.Count; + + len2 = sizeof(size_t) * memrec.Count; + for (ptr = (unsigned char *) memrec.Ptrs, j = 0; j < len1; j += 8) { + fprintf(stderr, "DUMP :: %07lu | %08X | %06lu | %07X | ", (unsigned long) 0, (unsigned int) memrec.Ptrs, (unsigned long) (sizeof(void *) * memrec.Count), (unsigned int) j); + + l = ((len1 - j < 8) ? (len1 - j) : (8)); + memset(buff, 0, 9); + memcpy(buff, ptr + j, l); + for (k = 0; k < l; k++) { + fprintf(stderr, "%02.2X ", buff[k]); + } + for (; k < 8; k++) { + fprintf(stderr, " "); + } + fprintf(stderr, "| %-8s\n", SafeStr((char *) buff, l)); + fflush(stderr); + } + for (ptr = (unsigned char *) memrec.Size, j = 0; j < len2; j += 8) { + fprintf(stderr, "DUMP :: %07lu | %08x | %06lu | %07X | ", (unsigned long) 0, (unsigned int) memrec.Size, sizeof(size_t) * memrec.Count, (unsigned int) j); + l = ((len2 - j < 8) ? (len2 - j) : (8)); + memset(buff, 0, 9); + memcpy(buff, ptr + j, l); + for (k = 0; k < l; k++) { + fprintf(stderr, "%02.2X ", buff[k]); + } + for (; k < 8; k++) { + fprintf(stderr, " "); + } + fprintf(stderr, "| %-8s\n", SafeStr((char *) buff, l)); + fflush(stderr); + } + for (i = 0; i < memrec.Count; i++) { + total += memrec.Size[i]; + for (ptr = (unsigned char *) memrec.Ptrs[i], j = 0; j < memrec.Size[i]; j += 8) { + fprintf(stderr, "DUMP :: %07lu | %08x | %06lu | %07X | ", i + 1, (unsigned int) memrec.Ptrs[i], (unsigned long) memrec.Size[i], (unsigned int) j); + l = ((memrec.Size[i] - j < 8) ? (memrec.Size[i] - j) : (8)); + memset(buff, 0, 9); + memcpy(buff, ptr + j, l); + for (k = 0; k < l; k++) { + fprintf(stderr, "%02.2X ", buff[k]); + } + for (; k < 8; k++) { + fprintf(stderr, " "); + } + fprintf(stderr, "| %-8s\n", SafeStr((char *) buff, l)); + fflush(stderr); + } + } + fprintf(stderr, "DUMP :: Total allocated memory: %10lu bytes\n\n", total); + fflush(stderr); +} + +/************* Function prototypes ****************/ + +/* Replacements for malloc(), realloc(), calloc(), and free() */ +void *Malloc(size_t); +void *Realloc(void *, size_t); +void *Calloc(size_t, size_t); +void Free(void *); + +/* A handler for SIGSEGV */ +void HandleSigSegv(int); + +void * +Malloc(size_t size) +{ + +#if 0 + char *temp = NULL; + +#endif + void *temp = NULL; + +#if DEBUG >= DEBUG_MALLOC + ++malloc_count; +#ifdef MALLOC_CALL_DEBUG + if (!(malloc_count % MALLOC_MOD)) { + fprintf(stderr, "Calls to malloc(): %d\n", malloc_count); + } +#endif +#endif + +#if DEBUG >= DEBUG_MALLOC + + if (!memrec.init) { + D_MALLOC(("WARNING: You must call memrec_init() before using the libmej memory management calls.\n")); + memrec_init(); + } +#endif + +#if 0 + temp = (char *) malloc(size); +#endif + temp = malloc(size); + if (!temp) + return NULL; +#if DEBUG >= DEBUG_MALLOC + memrec_add_var(temp, size); +#endif + return (temp); +} + +void * +Realloc(void *ptr, size_t size) +{ + + char *temp = NULL; + +#if DEBUG >= DEBUG_MALLOC + ++realloc_count; +# ifdef MALLOC_CALL_DEBUG + if (!(realloc_count % REALLOC_MOD)) { + fprintf(stderr, "Calls to realloc(): %d\n", realloc_count); + } +# endif +#endif +/* + * Redundant. You know the drill :) + * #if DEBUG >= DEBUG_MALLOC + */ + if (!memrec.init) { + D_MALLOC(("WARNING: You must call memrec_init() before using the libmej memory management calls.\n")); + memrec_init(); + } +/* #endif */ + + if (ptr == NULL) { + temp = (char *) Malloc(size); + } else { + temp = (char *) realloc(ptr, size); +#if DEBUG >= DEBUG_MALLOC + memrec_chg_var(ptr, temp, size); +#endif + } + if (!temp) + return NULL; + return (temp); +} + +void * +Calloc(size_t count, size_t size) +{ + + char *temp = NULL; + +#if DEBUG >= DEBUG_MALLOC + ++calloc_count; +#ifdef MALLOC_CALL_DEBUG + if (!(calloc_count % CALLOC_MOD)) { + fprintf(stderr, "Calls to calloc(): %d\n", calloc_count); + } +#endif +#endif + +#if DEBUG >= DEBUG_MALLOC + + if (!memrec.init) { + D_MALLOC(("WARNING: You must call memrec_init() before using the libmej memory management calls.\n")); + memrec_init(); + } +#endif + + temp = (char *) calloc(count, size); +#if DEBUG >= DEBUG_MALLOC + memrec_add_var(temp, size * count); +#endif + if (!temp) + return NULL; + return (temp); +} + +void +Free(void *ptr) +{ + +#if DEBUG >= DEBUG_MALLOC + ++free_count; +#ifdef MALLOC_CALL_DEBUG + if (!(free_count % FREE_MOD)) { + fprintf(stderr, "Calls to free(): %d\n", free_count); + } +#endif +#endif +#if DEBUG >= DEBUG_MALLOC + if (!memrec.init) { + D_MALLOC(("WARNING: You must call memrec_init() before using the libmej memory management calls.\n")); + memrec_init(); + } +#endif + + if (ptr) { +#if DEBUG >= DEBUG_MALLOC + memrec_rem_var(ptr); +#endif + free(ptr); + } else { + D_MALLOC(("Caught attempt to free NULL pointer\n")); + } +} + +void +HandleSigSegv(int sig) +{ + + static unsigned char segv_again = 0; + + /* Reinstate ourselves as the SIGSEGV handler if we're replaced */ + (void) signal(SIGSEGV, HandleSigSegv); + + /* Recursive seg faults are not cool.... */ + if (segv_again) { + printf("RECURSIVE SEGMENTATION FAULT DETECTED!\n"); + _exit(EXIT_FAILURE); + } + segv_again = 1; +#if DEBUG >= DEBUG_MALLOC + fprintf(stderr, "SEGMENTATION FAULT! DUMPING MEMORY TABLE\n"); + memrec_dump(); +#endif + exit(EXIT_FAILURE); +} + +inline void * +fixed_realloc(void *ptr, size_t size) +{ + + if (ptr) + return (realloc(ptr, size)); + else + return (malloc(size)); + +} diff --git a/libmej/mem.h b/libmej/mem.h new file mode 100644 index 0000000..3ab5226 --- /dev/null +++ b/libmej/mem.h @@ -0,0 +1,82 @@ + /*************************************************************** + * MEM.H -- Header file for mem.c * + * -- Michael Jennings * + * -- 07 January 1997 * + ***************************************************************/ +/* + * This file is original work by Michael Jennings . + * + * Copyright (C) 1997, Michael Jennings + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _MEM_H_ + +#define _MEM_H_ + +typedef struct memrec_struct { + unsigned char init; + unsigned long Count, TotalSize; + void **Ptrs; + size_t *Size; +} MemRec; + +#ifdef WITH_DMALLOC +# include +# define MALLOC(sz) malloc(sz) +# define CALLOC(type,n) calloc((n),(sizeof(type))) +# define REALLOC(mem,sz) fixed_realloc((mem),(sz)) +# define FREE(ptr) free(ptr) +#elif defined(DEBUG) || !defined(NDEBUG) +# define MALLOC(sz) Malloc(sz) +# define CALLOC(type,n) Calloc((n),(sizeof(type))) +# define REALLOC(mem,sz) Realloc((mem),(sz)) +/* # define FREE(ptr) Free(ptr) */ +# define FREE(ptr) { Free(ptr); ptr = NULL; } +# define MALLOC_MOD 25 +# define REALLOC_MOD 25 +# define CALLOC_MOD 25 +# define FREE_MOD 25 +#else +# define MALLOC(sz) malloc(sz) +# define CALLOC(type,n) calloc((n),(sizeof(type))) +# define REALLOC(mem,sz) fixed_realloc((mem),(sz)) +# define FREE(ptr) free(ptr) +#endif + +#ifndef MEM_C + +extern char *SafeStr(char *, unsigned short); +extern MemRec memrec; +extern void memrec_init(void); +void memrec_add_var(void *, size_t); +void memrec_rem_var(void *); +void memrec_chg_var(void *, void *, size_t); +void memrec_dump(void); +extern void *Malloc(size_t); +extern void *Realloc(void *, size_t); +extern void *Calloc(size_t, size_t); +extern void Free(void *); +extern void myalarm(long); +extern void HandleSigSegv(int); +extern char *GarbageCollect(char *, size_t); +extern char *FileGarbageCollect(char *, size_t); +extern void *fixed_realloc(void *, size_t); +#endif /* MEM_C */ + +#endif /* _MEM_H_ */ + diff --git a/libmej/snprintf.c b/libmej/snprintf.c new file mode 100644 index 0000000..6d351e9 --- /dev/null +++ b/libmej/snprintf.c @@ -0,0 +1,519 @@ +#include "global.h" +#include + +static const char cvs_ident[] = "$Id$"; + +/* + * Shamelessly snarfed from Enlightenment... + * which shamelessly snarfed from sane... + * which shamelessly snarfed from LPR + * which probably shamelessly snarfed from.... + * + * Moved comments to end so I can actually read the code.. cleaned out useless + * junk.... + */ + +#ifndef HAVE_SNPRINTF + +#ifdef HAVE_STDARG_H +#include +#endif + +#define VA_LOCAL_DECL va_list ap +#define VA_START(f) va_start(ap, f) +#define VA_SHIFT(v,t) ; /* no-op for ANSI */ +#define VA_END va_end(ap) + +/* + * dopr(): poor man's version of doprintf + */ + +static void dopr(char *buffer, const char *format, va_list args); +static void fmtstr(char *value, int ljust, int len, int zpad, int precision); +static void fmtnum(long value, int base, int dosign, + int ljust, int len, int zpad, int precision); +static void fmtdouble(int fmt, double value, + int ljust, int len, int zpad, int precision); +static void dostr(char *); +static char *output; +static void dopr_outch(int c); +static char *end; +int visible_control = 1; + +int +vsnprintf(char *str, size_t count, const char *fmt, va_list args) +{ + str[0] = 0; + end = str + count - 1; + dopr(str, fmt, args); + if (count > 0) { + end[0] = 0; + } + return (strlen(str)); +} + +#ifdef HAVE_STDARG_H +int +snprintf(char *str, size_t count, const char *fmt,...) +#else +int +snprintf(va_alist) + va_dcl + +#endif +{ +#ifndef HAVE_STDARG_H + char *str; + size_t count; + char *fmt; + +#endif + VA_LOCAL_DECL; + + VA_START(fmt); + VA_SHIFT(str, char *); + + VA_SHIFT(count, size_t); + VA_SHIFT(fmt, char *); + + (void) vsnprintf(str, count, fmt, ap); + VA_END; + return (strlen(str)); +} + +static void +dopr(char *buffer, const char *format, va_list args) +{ + int ch; + long value; + int longflag = 0; + char *strvalue; + int ljust; + int len; + int zpad; + int precision; + int set_precision; + double dval; + + output = buffer; + while ((ch = *format++)) { + switch (ch) { + case '%': + ljust = len = zpad = 0; + precision = -1; + set_precision = 0; + nextch: + ch = *format++; + switch (ch) { + case 0: + dostr("**end of format**"); + return; + case '-': + ljust = 1; + goto nextch; + case '.': + set_precision = 1; + precision = 0; + goto nextch; + case '*': + len = va_arg(args, int); + + goto nextch; + case '0': /* set zero padding if len not set */ + if (len == 0 && set_precision == 0) + zpad = '0'; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (set_precision) { + precision = precision * 10 + ch - '0'; + } else { + len = len * 10 + ch - '0'; + } + goto nextch; + case 'l': + longflag = 1; + goto nextch; + case 'u': + case 'U': + /*fmtnum(value,base,dosign,ljust,len, zpad, precision) */ + if (longflag) { + value = va_arg(args, long); + } else { + value = va_arg(args, int); + } + fmtnum(value, 10, 0, ljust, len, zpad, precision); + break; + case 'o': + case 'O': + /*fmtnum(value,base,dosign,ljust,len, zpad, precision) */ + if (longflag) { + value = va_arg(args, long); + } else { + value = va_arg(args, int); + } + fmtnum(value, 8, 0, ljust, len, zpad, precision); + break; + case 'd': + case 'i': + case 'D': + if (longflag) { + value = va_arg(args, long); + } else { + value = va_arg(args, int); + } + fmtnum(value, 10, 1, ljust, len, zpad, precision); + break; + case 'x': + if (longflag) { + value = va_arg(args, long); + } else { + value = va_arg(args, int); + } + fmtnum(value, 16, 0, ljust, len, zpad, precision); + break; + case 'X': + if (longflag) { + value = va_arg(args, long); + } else { + value = va_arg(args, int); + } + fmtnum(value, -16, 0, ljust, len, zpad, precision); + break; + case 's': + strvalue = va_arg(args, char *); + + fmtstr(strvalue, ljust, len, zpad, precision); + break; + case 'c': + ch = va_arg(args, int); + + { + char b[2]; + int vsb = visible_control; + + b[0] = ch; + b[1] = 0; + visible_control = 0; + fmtstr(b, ljust, len, zpad, precision); + visible_control = vsb; + } + break; + case 'f': + case 'g': + dval = va_arg(args, double); + + fmtdouble(ch, dval, ljust, len, zpad, precision); + break; + case '%': + dopr_outch(ch); + continue; + default: + dostr("???????"); + } + longflag = 0; + break; + default: + dopr_outch(ch); + break; + } + } + *output = 0; +} + +/* + * Format '%[-]len[.precision]s' + * - = left justify (ljust) + * len = minimum length + * precision = numbers of chars in string to use + */ +static void +fmtstr(char *value, int ljust, int len, int zpad, int precision) +{ + int padlen, strlen, i, c; /* amount to pad */ + + zpad = 0; + if (value == 0) { + value = ""; + } + if (precision > 0) { + strlen = precision; + } else { + /* cheap strlen so you do not have library call */ + for (strlen = 0; (c = value[strlen]); ++strlen) { + if (visible_control && iscntrl(c) && !isspace(c)) { + ++strlen; + } + } + } + padlen = len - strlen; + if (padlen < 0) + padlen = 0; + if (ljust) + padlen = -padlen; + while (padlen > 0) { + dopr_outch(' '); + --padlen; + } + /* output characters */ + for (i = 0; (c = value[i]); ++i) { + if (visible_control && iscntrl(c) && !isspace(c)) { + dopr_outch('^'); + c = ('@' | (c & 0x1F)); + } + dopr_outch(c); + } + while (padlen < 0) { + dopr_outch(' '); + ++padlen; + } +} + +static void +fmtnum(long value, int base, int dosign, int ljust, + int len, int zpad, int precision) +{ + int signvalue = 0; + unsigned long uvalue; + char convert[20]; + int place = 0; + int padlen = 0; /* amount to pad */ + int caps = 0; + + precision = 0; + /* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n", + * value, base, dosign, ljust, len, zpad )); */ + uvalue = value; + if (dosign) { + if (value < 0) { + signvalue = '-'; + uvalue = -value; + } + } + if (base < 0) { + caps = 1; + base = -base; + } + do { + convert[place++] = + (caps ? "0123456789ABCDEF" : "0123456789abcdef") + [uvalue % (unsigned) base]; + uvalue = (uvalue / (unsigned) base); + } + while (uvalue); + convert[place] = 0; + padlen = len - place; + if (padlen < 0) + padlen = 0; + if (ljust) + padlen = -padlen; + /* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n", + * convert,place,signvalue,padlen)); */ + if (zpad && padlen > 0) { + if (signvalue) { + dopr_outch(signvalue); + --padlen; + signvalue = 0; + } + while (padlen > 0) { + dopr_outch(zpad); + --padlen; + } + } + while (padlen > 0) { + dopr_outch(' '); + --padlen; + } + if (signvalue) + dopr_outch(signvalue); + while (place > 0) + dopr_outch(convert[--place]); + while (padlen < 0) { + dopr_outch(' '); + ++padlen; + } +} + +static void +fmtdouble(int fmt, double value, int ljust, int len, int zpad, int precision) +{ + char convert[128]; + char fmtstr[128]; + int l; + + zpad = 0; + if (len == 0) + len = 10; + if (len > (int) sizeof(convert) - 10) { + len = (int) sizeof(convert) - 10; + } + if (precision > (int) sizeof(convert) - 10) { + precision = (int) sizeof(convert) - 10; + } + if (precision > len) + precision = len; + strcpy(fmtstr, "%"); + if (ljust) + strcat(fmtstr, "-"); + if (len) { + sprintf(fmtstr + strlen(fmtstr), "%d", len); + } + if (precision > 0) { + sprintf(fmtstr + strlen(fmtstr), ".%d", precision); + } + l = strlen(fmtstr); + fmtstr[l] = fmt; + fmtstr[l + 1] = 0; + sprintf(convert, fmtstr, value); + dostr(convert); +} + +static void +dostr(char *str) +{ + while (*str) + dopr_outch(*str++); +} + +static void +dopr_outch(int c) +{ + if (end == 0 || output < end) { + *output++ = c; + } +} + +/************************************************************** + * Original: + * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 + * A bombproof version of doprnt (dopr) included. + * Sigh. This sort of thing is always nasty do deal with. Note that + * the version here does not include floating point... + * + * plp_snprintf() is used instead of sprintf() as it does limit checks + * for string length. This covers a nasty loophole. + * + * The other functions are there to prevent NULL pointers from + * causing nast effects. + **************************************************************/ + +/*************************************************************************** + * LPRng - An Extended Print Spooler System + * + * Copyright 1988-1997, Patrick Powell, San Diego, CA + * papowell@sdsu.edu + * See below for conditions of use. + * + *************************************************************************** + * MODULE: snprintf.c + * PURPOSE: LPRng version of printf - absolutely bombproof (hopefully!) + **************************************************************************/ + +/* + * The "Artistic License" + * + * Preamble + * + * The intent of this document is to state the conditions under which a + * Package may be copied, such that the Copyright Holder maintains some + * semblance of artistic control over the development of the package, + * while giving the users of the package the right to use and distribute + * the Package in a more-or-less customary fashion, plus the right to make + * reasonable modifications. + * + * Definitions: + * + * "Package" refers to the collection of files distributed by the + * Copyright Holder, and derivatives of that collection of files + * created through textual modification. + * + * "Standard Version" refers to such a Package if it has not been + * modified, or has been modified in accordance with the wishes + * of the Copyright Holder as specified below. + * + * "Copyright Holder" is whoever is named in the copyright or + * copyrights for the package. + * + * "You" is you, if you are thinking about copying or distributing + * this Package. + * + * "Reasonable copying fee" is whatever you can justify on the + * basis of media cost, duplication charges, time of people involved, + * and so on. (You will not be required to justify it to the + * Copyright Holder, but only to the computing community at large + * as a market that must bear the fee.) + * + * "Freely Available" means that no fee is charged for the item + * itself, though there may be fees involved in handling the item. + * It also means that recipients of the item may redistribute it + * under the same conditions they received it. + * + * 1. You may make and give away verbatim copies of the source form of the + * Standard Version of this Package without restriction, provided that you + * duplicate all of the original copyright notices and associated disclaimers. + * + * 2. You may apply bug fixes, portability fixes and other modifications + * derived from the Public Domain or from the Copyright Holder. A Package + * modified in such a way shall still be considered the Standard Version. + * + * 3. You may otherwise modify your copy of this Package in any way, provided + * that you insert a prominent notice in each changed file stating how and + * when you changed that file, and provided that you do at least ONE of the + * following: + * + * a) place your modifications in the Public Domain or otherwise make them + * Freely Available, such as by posting said modifications to Usenet or + * an equivalent medium, or placing the modifications on a major archive + * site such as uunet.uu.net, or by allowing the Copyright Holder to include + * your modifications in the Standard Version of the Package. + * + * b) use the modified Package only within your corporation or organization. + * + * c) rename any non-standard executables so the names do not conflict + * with standard executables, which must also be provided, and provide + * a separate manual page for each non-standard executable that clearly + * documents how it differs from the Standard Version. + * + * d) make other distribution arrangements with the Copyright Holder. + * + * 4. You may distribute the programs of this Package in object code or + * executable form, provided that you do at least ONE of the following: + * + * a) distribute a Standard Version of the executables and library files, + * together with instructions (in the manual page or equivalent) on where + * to get the Standard Version. + * + * b) accompany the distribution with the machine-readable source of + * the Package with your modifications. + * + * c) give non-standard executables non-standard names, and clearly + * document the differences in manual pages (or equivalent), together + * with instructions on where to get the Standard Version. + * + * d) make other distribution arrangements with the Copyright Holder. + * + * 5. You may charge a reasonable copying fee for any distribution of this + * Package. You may charge any fee you choose for support of this + * Package. You may not charge a fee for this Package itself. However, + * you may distribute this Package in aggregate with other (possibly + * commercial) programs as part of a larger (possibly commercial) software + * distribution provided that you do not advertise this Package as a + * product of your own. + * + * 6. The name of the Copyright Holder may not be used to endorse or promote + * products derived from this software without specific prior written permission. + * + * 7. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * The End + */ + +#endif /* HAVE_SNPRINTF */ diff --git a/libmej/strings.c b/libmej/strings.c new file mode 100644 index 0000000..d2b88f8 --- /dev/null +++ b/libmej/strings.c @@ -0,0 +1,568 @@ +/*************************************************************** + * STRINGS.C -- String manipulation routines * + * -- Michael Jennings * + * -- 08 January 1997 * + ***************************************************************/ +/* + * This file is original work by Michael Jennings . + * + * Copyright (C) 1997, Michael Jennings + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +static const char cvs_ident[] = "$Id$"; + +#include "global.h" +#include +#include +#include +#include +#include +#ifndef WITH_DMALLOC +# include +#endif +#include +#include "debug.h" +#include "mem.h" +#define STRINGS_C +#include "strings.h" + +#ifndef HAVE_MEMMEM +/* Find first occurance of bytestring needle of size needlelen in memory region + haystack of size haystacklen */ +void * +memmem(void *haystack, register size_t haystacklen, void *needle, register size_t needlelen) +{ + + register char *hs = (char *) haystack; + register char *n = (char *) needle; + register unsigned long i; + register len = haystacklen - needlelen; + + for (i = 0; i < len; i++) { + if (!memcmp(hs + i, n, needlelen)) { + return (hs + i); + } + } + return (NULL); +} +#endif + +#ifndef HAVE_USLEEP +void +usleep(unsigned long usec) +{ + + struct timeval delay; + + delay.tv_sec = 0; + delay.tv_usec = usec; + select(0, NULL, NULL, NULL, &delay); + +} + +#endif + +/***** Not needed ****** +#ifndef HAVE_NANOSLEEP +inline void +nanosleep(unsigned long nsec) { + usleep(nsec / 1000); +} +#endif +************************/ + +/* Return the leftmost cnt characters of str */ +char * +LeftStr(const char *str, unsigned long cnt) +{ + + char *tmpstr; + + tmpstr = (char *) MALLOC(cnt + 1); + strncpy(tmpstr, str, cnt); + tmpstr[cnt] = 0; + return (tmpstr); +} + +/* Return cnt characters from str, starting at position index (from 0) */ +char * +MidStr(const char *str, unsigned long index, unsigned long cnt) +{ + + char *tmpstr; + const char *pstr = str; + + tmpstr = (char *) MALLOC(cnt + 1); + pstr += index; + strncpy(tmpstr, pstr, cnt); + tmpstr[cnt] = 0; + return (tmpstr); +} + +/* Return the rightmost characters of str */ +char * +RightStr(const char *str, unsigned long cnt) +{ + + char *tmpstr; + const char *pstr = str; + + tmpstr = (char *) MALLOC(cnt + 1); + pstr += strlen(str); + pstr -= cnt; + strcpy(tmpstr, pstr); + return (tmpstr); +} + +/* Returns TRUE if str matches regular expression pattern, FALSE otherwise */ +#if defined(HAVE_REGEX_H) || defined(IRIX) +unsigned char +Match(register const char *str, register const char *pattern) +{ + + register regex_t *rexp; + register int result; + +#ifndef IRIX + char errbuf[256]; + + rexp = (regex_t *) MALLOC(sizeof(regex_t)); +#endif + +#ifdef IRIX + if ((rexp = compile((const char *) pattern, (char *) NULL, (char *) NULL)) == NULL) { + fprintf(stderr, "Unable to compile regexp %s\n", pattern); + return (FALSE); + } +#else + if ((result = regcomp(rexp, pattern, REG_EXTENDED)) != 0) { + regerror(result, rexp, errbuf, 256); + fprintf(stderr, "Unable to compile regexp %s -- %s.\n", pattern, errbuf); + FREE(rexp); + return (FALSE); + } +#endif + +#ifdef IRIX + result = step((const char *) str, rexp); + FREE(rexp); + return (result); +#else + if (((result = regexec(rexp, str, (size_t) 0, (regmatch_t *) NULL, 0)) + != 0) && (result != REG_NOMATCH)) { + regerror(result, rexp, errbuf, 256); + fprintf(stderr, "Error testing input string %s -- %s.\n", str, errbuf); + FREE(rexp); + return (FALSE); + } + FREE(rexp); + return (!result); +#endif +} +#endif + +/* Return malloc'd pointer to index-th word in str. "..." counts as 1 word. */ +char * +Word(unsigned long index, const char *str) +{ + + char *tmpstr; + char *delim = DEFAULT_DELIM; + register unsigned long i, j, k; + + k = strlen(str) + 1; + if ((tmpstr = (char *) MALLOC(k)) == NULL) { + fprintf(stderr, "Word(%lu, %s): Unable to allocate memory -- %s.\n", + index, str, strerror(errno)); + return ((char *) NULL); + } + *tmpstr = 0; + for (i = 0, j = 0; j < index && str[i]; j++) { + for (; isspace(str[i]); i++); + switch (str[i]) { + case '\"': + delim = "\""; + i++; + break; + case '\'': + delim = "\'"; + i++; + break; + default: + delim = DEFAULT_DELIM; + } + for (k = 0; str[i] && !strchr(delim, str[i]);) { + if (str[i] == '\\') { + if (str[i + 1] == '\'' || str[i + 1] == '\"') { + i++; + } + } + tmpstr[k++] = str[i++]; + } + switch (str[i]) { + case '\"': + case '\'': + i++; + break; + } + tmpstr[k] = 0; + } + + if (j != index) { + FREE(tmpstr); + D_STRINGS(("Word(%lu, %s) returning NULL.\n", index, str)); + return ((char *) NULL); + } else { + tmpstr = (char *) REALLOC(tmpstr, strlen(tmpstr) + 1); + D_STRINGS(("Word(%lu, %s) returning \"%s\".\n", index, str, tmpstr)); + return (tmpstr); + } +} + +/* Return pointer into str to index-th word in str. "..." counts as 1 word. */ +char * +PWord(unsigned long index, char *str) +{ + + register char *tmpstr = str; + register unsigned long j; + + if (!str) + return ((char *) NULL); + for (; isspace(*tmpstr) && *tmpstr; tmpstr++); + for (j = 1; j < index && *tmpstr; j++) { + for (; !isspace(*tmpstr) && *tmpstr; tmpstr++); + for (; isspace(*tmpstr) && *tmpstr; tmpstr++); + } + + if (*tmpstr == '\"' || *tmpstr == '\'') { + tmpstr++; + } + if (*tmpstr == '\0') { + D_STRINGS(("PWord(%lu, %s) returning NULL.\n", index, str)); + return ((char *) NULL); + } else { + D_STRINGS(("PWord(%lu, %s) returning \"%s\"\n", index, str, tmpstr)); + return tmpstr; + } +} + +/* Returns the number of words in str, for use with Word() and PWord(). "..." counts as 1 word. */ +unsigned long +NumWords(const char *str) +{ + + register unsigned long cnt = 0; + char *delim = DEFAULT_DELIM; + register unsigned long i; + + for (i = 0; str[i] && strchr(delim, str[i]); i++); + for (; str[i]; cnt++) { + switch (str[i]) { + case '\"': + delim = "\""; + i++; + break; + case '\'': + delim = "\'"; + i++; + break; + default: + delim = DEFAULT_DELIM; + } + for (; str[i] && !strchr(delim, str[i]); i++); + switch (str[i]) { + case '\"': + case '\'': + i++; + break; + } + for (; str[i] && isspace(str[i]); i++); + } + + D_STRINGS(("NumWords() returning %lu\n", cnt)); + return (cnt); +} + +char * +StripWhitespace(register char *str) +{ + + register unsigned long i, j; + + if ((j = strlen(str))) { + for (i = j - 1; isspace(*(str + i)); i--); + str[j = i + 1] = 0; + for (i = 0; isspace(*(str + i)); i++); + j -= i; + memmove(str, str + i, j + 1); + } + return (str); +} + +char * +LowerStr(char *str) +{ + + register char *tmp; + + for (tmp = str; *tmp; tmp++) + *tmp = tolower(*tmp); + D_STRINGS(("LowerStr() returning %s\n", str)); + return (str); +} + +char * +UpStr(char *str) +{ + + register char *tmp; + + for (tmp = str; *tmp; tmp++) + *tmp = toupper(*tmp); + D_STRINGS(("UpStr() returning %s\n", str)); + return (str); +} + +char * +StrCaseStr(char *haystack, register const char *needle) +{ + + register char *t; + register size_t len = strlen(needle); + + for (t = haystack; t && *t; t++) { + if (!strncasecmp(t, needle, len)) { + return (t); + } + } + return (NULL); +} + +char * +StrCaseChr(char *haystack, register char needle) +{ + + register char *t; + + for (t = haystack; t && *t; t++) { + if (tolower(*t) == tolower(needle)) { + return (t); + } + } + return (NULL); +} + +char * +StrCasePBrk(char *haystack, register char *needle) +{ + + register char *t; + + for (t = haystack; t && *t; t++) { + if (StrCaseChr(needle, *t)) { + return (t); + } + } + return (NULL); +} + +char * +StrRev(register char *str) +{ + + register int i, j; + + i = strlen(str); + for (j = 0, i--; i > j; i--, j++) { + cswap(str[j], str[i]); + } + return (str); + +} + +#if !(HAVE_STRSEP) +char * +strsep(char **str, register char *sep) +{ + + register char *s = *str; + char *sptr; + + D_STRINGS(("StrSep(%s, %s) called.\n", *str, sep)); + sptr = s; + for (; *s && !strchr(sep, *s); s++); + if (!*s) { + if (s != sptr) { + *str = s; + D_STRINGS(("Reached end of string with token \"%s\" in buffer\n", sptr)); + return (sptr); + } else { + D_STRINGS(("Reached end of string\n")); + return ((char *) NULL); + } + } + *s = 0; + *str = s + 1; + D_STRINGS(("Got token \"%s\", *str == \"%s\"\n", sptr, *str)); + return (sptr); +} +#endif + +char * +GarbageCollect(char *buff, size_t len) +{ + + register char *tbuff = buff, *pbuff = buff; + register unsigned long i, j; + + D_STRINGS(("Garbage collecting on %lu bytes at %10.8p\n", len, buff)); + for (i = 0, j = 0; j < len; j++) + if (pbuff[j]) + tbuff[i++] = pbuff[j]; + tbuff[i++] = '\0'; + D_STRINGS(("Garbage collecting gives: \n%s\n", buff)); + return ((char *) REALLOC(buff, sizeof(char) * i)); +} + +char * +FGarbageCollect(char *buff, size_t len) +{ + + register char *tbuff = buff, *pbuff = buff; + char *tmp1, *tmp2; + register unsigned long j; + + D_STRINGS(("File garbage collecting on %lu bytes at %10.8p\n", len, buff)); + for (j = 0; j < len;) { + switch (pbuff[j]) { + case '#': + for (; !strchr("\r\n", pbuff[j]) && j < len; j++) + pbuff[j] = '\0'; /* First null out the line up to the CR and/or LF */ + for (; strchr("\r\n", pbuff[j]) && j < len; j++) + pbuff[j] = '\0'; /* Then null out the CR and/or LF */ + break; + case '\r': + case '\n': + case '\f': + case ' ': + case '\t': + case '\v': + for (; isspace(pbuff[j]) && j < len; j++) + pbuff[j] = '\0'; /* Null out the whitespace */ + break; + default: + /* Find the end of this line and the occurence of the + next mid-line comment. */ + tmp1 = strpbrk(pbuff + j, "\r\n"); + tmp2 = strstr(pbuff + j, " #"); + + /* If either is null, take the non-null one. Otherwise, + take the lesser of the two. */ + if (!tmp1 || !tmp2) { + tbuff = ((tmp1) ? (tmp1) : (tmp2)); + } else { + tbuff = ((tmp1 < tmp2) ? (tmp1) : (tmp2)); + } + + /* Now let j catch up so that pbuff+j = tbuff; i.e., let + pbuff[j] refer to the same character that tbuff does */ + j += tbuff - (pbuff + j); + + /* Finally, change whatever is at pbuff[j] to a newline. + This will accomplish several things at once: + o It will change a \r to a \n if that's what's there + o If it's a \n, it'll stay the same. No biggie. + o If it's a space, it will end the line there and the + next line will begin with a comment, which is handled + above. */ + if (j < len) + pbuff[j++] = '\n'; + + } + } + + /* Change all occurances of a backslash followed by a newline to nulls + and null out all whitespace up to the next non-whitespace character. + This handles support for breaking a string across multiple lines. */ + for (j = 0; j < len; j++) { + if (pbuff[j] == '\\' && pbuff[j + 1] == '\n') { + pbuff[j++] = '\0'; + for (; isspace(pbuff[j]) && j < len; j++) + pbuff[j] = '\0'; /* Null out the whitespace */ + } + } + + /* And the final step, garbage collect the buffer to condense all + those nulls we just put in. */ + return (GarbageCollect(buff, len)); +} + +char * +CondenseWhitespace(char *s) +{ + + register unsigned char gotspc = 0; + register char *pbuff = s, *pbuff2 = s; + + D_STRINGS(("CondenseWhitespace(%s) called.\n", s)); + for (; *pbuff2; pbuff2++) { + if (isspace(*pbuff2)) { + if (!gotspc) { + *pbuff = ' '; + gotspc = 1; + pbuff++; + } + } else { + *pbuff = *pbuff2; + gotspc = 0; + pbuff++; + } + } + if ((pbuff >= s) && (isspace(*(pbuff - 1)))) + pbuff--; + *pbuff = 0; + D_STRINGS(("CondenseWhitespace() returning \"%s\"\n", s)); + return (REALLOC(s, strlen(s) + 1)); +} + +void +HexDump(void *buff, register size_t count) +{ + + register unsigned long j, k, l; + register unsigned char *ptr; + unsigned char buffr[9]; + + fprintf(stderr, " Address | Size | Offset | 00 01 02 03 04 05 06 07 | ASCII \n"); + fprintf(stderr, "---------+--------+---------+-------------------------+---------\n"); + for (ptr = (unsigned char *) buff, j = 0; j < count; j += 8) { + fprintf(stderr, " %08x | %06lu | %07X | ", (unsigned int) buff, + (unsigned long) count, (unsigned int) j); + l = ((count - j < 8) ? (count - j) : (8)); + memset(buffr, 0, 9); + memcpy(buffr, ptr + j, l); + for (k = 0; k < l; k++) { + fprintf(stderr, "%02.2X ", buffr[k]); + } + for (; k < 8; k++) { + fprintf(stderr, " "); + } + fprintf(stderr, "| %-8s\n", SafeStr((char *) buffr, l)); + } +} diff --git a/libmej/strings.h b/libmej/strings.h new file mode 100644 index 0000000..342565c --- /dev/null +++ b/libmej/strings.h @@ -0,0 +1,106 @@ +/*************************************************************** + * STRINGS.H -- String manipulation routines * + * -- Michael Jennings * + * -- 08 January 1997 * + ***************************************************************/ +/* + * This file is original work by Michael Jennings . + * + * Copyright (C) 1997, Michael Jennings + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _STRINGS_H_ + +#define _STRINGS_H_ + +#include "global.h" +#include +#include +#include + +#ifndef TRUE +# define TRUE ((unsigned char)(1)) +# define FALSE ((unsigned char)(0)) +#endif + +#ifndef swap +# define swap(a, b) (((int)(b)) ^= ((int)(a)) ^= ((int)(b)) ^= ((int)(a))) +#endif + +#ifndef cswap +# define cswap(a, b) ((b) ^= (a) ^= (b) ^= (a)) +#endif + +#define DEFAULT_DELIM " \r\n\f\t\v" + +#define CONST_STRLEN(x) (sizeof(x) - 1) +#define BEG_STRCASECMP(s, constr) (strncasecmp(s, constr, CONST_STRLEN(constr))) + +#ifdef IRIX +# define regex_t char +# define NBRA 9 + extern char *braslist[NBRA]; + extern char *braelist[NBRA]; + extern int nbra, regerrno, reglength; + extern char *loc1, *loc2, *locs; + + extern "C" int step(const char *, const char *); + extern "C" int advance(const char *, char *); + extern "C" char *compile(const char *, char *, char *); +#elif defined(HAVE_REGEX_H) +# include +#endif + +#ifndef STRINGS_C +extern char *LeftStr(const char *, unsigned long); +extern char *MidStr(const char *, unsigned long, unsigned long); +extern char *RightStr(const char *, unsigned long); +#if defined(HAVE_REGEX_H) || defined(IRIX) +extern unsigned char Match(const char *, const char *); +#endif +extern char *Word(unsigned long index, const char *str); +extern char *PWord(unsigned long index, char *str); +extern char *StripWhitespace(char *); +extern char *LowerStr(char *); +extern char *UpStr(char *); +extern char *StrCaseStr(char *, const char *); +extern char *StrCaseChr(char *, char); +extern char *StrCasePBrk(char *, char *); +extern char *StrRev(char *); +#if !(HAVE_STRSEP) +extern char *strsep(char **, char *); +#endif +extern char *SafeStr(char *, unsigned short); +extern char *GarbageCollect(char *, size_t); +extern char *FGarbageCollect(char *, size_t); +extern char *CondenseWhitespace(char *); +extern void HexDump(void *, size_t); +#ifndef HAVE_MEMMEM +extern void *memmem(void *, size_t, void *, size_t); +#endif +#ifndef HAVE_USLEEP +extern void usleep(unsigned long); +#endif +/* +#ifndef HAVE_NANOSLEEP +extern void nanosleep(unsigned long); +#endif +*/ +#endif + +#endif /* _STRINGS_H_ */ diff --git a/libmej/strptime.c b/libmej/strptime.c new file mode 100644 index 0000000..6440e95 --- /dev/null +++ b/libmej/strptime.c @@ -0,0 +1,272 @@ + +/*************************************************************** + * STRPTIME.C -- strptime() for IRIX * + * -- Michael Jennings * + * -- 2 April 1997 * + ***************************************************************/ +/* + * This file is original work by Michael Jennings . + * + * Copyright (C) 1997, Michael Jennings + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +static const char cvs_ident[] = "$Id$"; + +#ifdef IRIX + +#include "global.h" +#include +#include +#include +#include +#define STRPTIME_C +#include "strptime.h" + +char * +strptime(char *buf, const char *format, struct tm *tm) +{ + + register char c; + register const char *tmp; + register int i, len; + + for (tmp = format; *tmp;) { + if (!(*buf)) + break; + + if ((c = *tmp++) != '%') { + if (!isspace(*buf) && c != *buf++) + return ((char *) NULL); + for (; *buf != 0 && isspace(*buf); buf++); + continue; + } + switch ((c = *tmp++)) { + case 0: + case '%': + if (*buf++ != '%') + return ((char *) NULL); + break; + + case 'C': + buf = strptime(buf, USMap.LocaleDateFormat, tm); + if (!buf) + return ((char *) NULL); + break; + + case 'c': + buf = strptime(buf, "%x %X", tm); + if (!buf) + return ((char *) NULL); + break; + + case 'D': + buf = strptime(buf, "%m/%d/%y", tm); + if (!buf) + return ((char *) NULL); + break; + + case 'R': + buf = strptime(buf, "%H:%M", tm); + if (!buf) + return ((char *) NULL); + break; + + case 'r': + buf = strptime(buf, "%I:%M:%S %p", tm); + if (!buf) + return ((char *) NULL); + break; + + case 'T': + buf = strptime(buf, "%H:%M:%S", tm); + if (!buf) + return ((char *) NULL); + break; + + case 'X': + buf = strptime(buf, USMap.TimeFormat, tm); + if (!buf) + return ((char *) NULL); + break; + + case 'x': + buf = strptime(buf, USMap.DateFormat, tm); + if (!buf) + return ((char *) NULL); + break; + + case 'j': + if (!isdigit(*buf)) + return ((char *) NULL); + for (i = 0; *buf != 0 && isdigit(*buf); buf++) { + i *= 10; + i += *buf - '0'; + } + if (i > 365) + return ((char *) NULL); + tm->tm_yday = i; + break; + + case 'M': + case 'S': + if (!(*buf) || isspace(*buf)) + break; + if (!isdigit(*buf)) + return ((char *) NULL); + for (i = 0; *buf != 0 && isdigit(*buf); buf++) { + i *= 10; + i += *buf - '0'; + } + if (i > 59) + return ((char *) NULL); + if (c == 'M') + tm->tm_min = i; + else + tm->tm_sec = i; + + if (*buf && isspace(*buf)) + for (; *tmp && !isspace(*tmp); tmp++); + break; + + case 'H': + case 'I': + case 'k': + case 'l': + if (!isdigit(*buf)) + return ((char *) NULL); + for (i = 0; *buf && isdigit(*buf); buf++) { + i *= 10; + i += *buf - '0'; + } + if (c == 'H' || c == 'k') { + if (i > 23) + return ((char *) NULL); + } else if (i > 11) + return ((char *) NULL); + tm->tm_hour = i; + if (*buf && isspace(*buf)) + for (; *tmp && !isspace(*tmp); tmp++); + break; + + case 'p': + len = strlen(USMap.AM); + if (!strncasecmp(buf, USMap.AM, len)) { + if (tm->tm_hour > 12) + return ((char *) NULL); + if (tm->tm_hour == 12) + tm->tm_hour = 0; + buf += len; + break; + } + len = strlen(USMap.PM); + if (!strncasecmp(buf, USMap.PM, len)) { + if (tm->tm_hour > 12) + return ((char *) NULL); + if (tm->tm_hour != 12) + tm->tm_hour += 12; + buf += len; + break; + } + return ((char *) NULL); + + case 'A': + case 'a': + for (i = 0; i < NUM_DAYS; i++) { + len = strlen(USMap.Days[i]); + if (!strncasecmp(buf, USMap.Days[i], len)) + break; + len = strlen(USMap.DaysAbbrev[i]); + if (!strncasecmp(buf, USMap.DaysAbbrev[i], len)) + break; + } + if (i == NUM_DAYS) + return ((char *) NULL); + tm->tm_wday = i; + buf += len; + break; + + case 'd': + case 'e': + if (!isdigit(*buf)) + return ((char *) NULL); + for (i = 0; *buf && isdigit(*buf); buf++) { + i *= 10; + i += *buf - '0'; + } + if (i > 31) + return ((char *) NULL); + tm->tm_mday = i; + if (*buf && isspace(*buf)) + for (; *tmp && !isspace(*tmp); tmp++); + break; + + case 'B': + case 'b': + case 'h': + for (i = 0; i < NUM_MONTHS; i++) { + len = strlen(USMap.Months[i]); + if (!strncasecmp(buf, USMap.Months[i], len)) + break; + len = strlen(USMap.MonthsAbbrev[i]); + if (!strncasecmp(buf, USMap.MonthsAbbrev[i], len)) + break; + } + if (i == NUM_MONTHS) + return ((char *) NULL); + tm->tm_mon = i; + buf += len; + break; + + case 'm': + if (!isdigit(*buf)) + return ((char *) NULL); + for (i = 0; *buf && isdigit(*buf); buf++) { + i *= 10; + i += *buf - '0'; + } + if (i < 1 || i > 12) + return ((char *) NULL); + tm->tm_mon = i - 1; + if (*buf && isspace(*buf)) + for (; *tmp && !isspace(*tmp); tmp++); + break; + + case 'Y': + case 'y': + if (!(*buf) || isspace(*buf)) + break; + if (!isdigit(*buf)) + return ((char *) NULL); + for (i = 0; *buf && isdigit(*buf); buf++) { + i *= 10; + i += *buf - '0'; + } + if (c == 'Y') + i -= 1900; + if (i < 0) + return ((char *) NULL); + tm->tm_year = i; + if (*buf && isspace(*buf)) + for (; *tmp && !isspace(*tmp); tmp++); + break; + } + } + return (buf); +} + +#endif diff --git a/libmej/strptime.h b/libmej/strptime.h new file mode 100644 index 0000000..888dd7c --- /dev/null +++ b/libmej/strptime.h @@ -0,0 +1,76 @@ +/*************************************************************** + * STRPTIME.H -- Header file for strptime() * + * -- Michael Jennings * + * -- 2 April 1997 * + ***************************************************************/ +/* + * This file is original work by Michael Jennings . + * + * Copyright (C) 1997, Michael Jennings + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _STRPTIME_H_ + +#define _STRPTIME_H_ + +#define sizeofone(s) (sizeof(s) / sizeof((s)[0])) + +#define NUM_MONTHS 12 +#define NUM_DAYS 7 + +typedef struct dtmap_struct { + char *Months[NUM_MONTHS]; + char *MonthsAbbrev[NUM_MONTHS]; + char *Days[NUM_DAYS]; + char *DaysAbbrev[NUM_DAYS]; + char *DateFormat; + char *TimeFormat; + char *DateTimeFormat; + char *LocaleDateFormat; + char *AM; + char *PM; +} DTMap; + +static DTMap USMap = { + { "January", "February", "March", "April", + "May", "June", "July", "August", + "September", "October", "November", "December" }, + { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }, + { "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday" }, + { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }, + "%m/%d/%y", + "%H:%M:%S", + "%a %b %e %T %Z %Y", + "%A, %B, %e, %Y", + "AM", + "PM" +}; + +#ifndef STRPTIME_C +# ifdef __cplusplus +extern "C" { +# else +extern { +# endif + extern char *strptime(char *, const char *, struct tm *); +} +#endif + +#endif /* _STRPTIME_H_ */ diff --git a/missing b/missing new file mode 100644 index 0000000..cbe2b0e --- /dev/null +++ b/missing @@ -0,0 +1,188 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright (C) 1996, 1997 Free Software Foundation, Inc. +# Franc,ois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing - GNU libit 0.0" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`configure.in'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`configure.in'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`configure.in'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER([^):]*:\([^)]*\)).*/\1/p' configure.in` + if test -z "$files"; then + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^):]*\)).*/\1/p' configure.in` + test -z "$files" || files="$files.in" + else + files=`echo "$files" | sed -e 's/:/ /g'` + fi + test -z "$files" && files="config.h.in" + touch $files + ;; + + automake) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print \ + | sed 's/^\(.*\).am$/touch \1.in/' \ + | sh + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100644 index 0000000..91f6d04 --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,32 @@ +#!/bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Last modified: 1994-03-25 +# Public domain + +errstatus=0 + +for file in ${1+"$@"} ; do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d in ${1+"$@"} ; do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" 1>&2 + mkdir "$pathcomp" || errstatus=$? + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/reformat-code b/reformat-code new file mode 100755 index 0000000..c2f14ce --- /dev/null +++ b/reformat-code @@ -0,0 +1,9 @@ +#!/bin/sh + +for i in *.c src/*.c utils/*.c ; do + if test -f $i; then + echo Reformatting $i + indent -bap -br -ce -ci4 -cli2 -cs -di1 -i2 -l140 -lp -lps -nbc -npcs -nss -nsob -psl $i + fi +done + diff --git a/src/.cvsignore b/src/.cvsignore new file mode 100644 index 0000000..b608744 --- /dev/null +++ b/src/.cvsignore @@ -0,0 +1,10 @@ +Makefile +Makefile.in +.deps +.libs +Eterm +libEterm.la +feature.h +VERSION.h +*.lo +*.da diff --git a/src/Eterm.xpm b/src/Eterm.xpm new file mode 100644 index 0000000..6e39081 --- /dev/null +++ b/src/Eterm.xpm @@ -0,0 +1,822 @@ +/* XPM */ +static char * Eterm_xpm[] = { +"48 48 771 2", +" c None", +". c #282722", +"+ c #2E2C27", +"@ c #33332C", +"# c #3A382F", +"$ c #403E36", +"% c #44433B", +"& c #47463C", +"* c #515048", +"= c #58584E", +"- c #5B5B52", +"; c #757469", +"> c #918F83", +", c #8B897D", +"' c #7F7E70", +") c #807E6F", +"! c #878576", +"~ c #8C8C7A", +"{ c #010103", +"] c #020204", +"^ c #32322B", +"/ c #3B382E", +"( c #434035", +"_ c #48473D", +": c #505044", +"< c #565647", +"[ c #5A584A", +"} c #5B5B4A", +"| c #5C5B4D", +"1 c #5E5B50", +"2 c #5E5C50", +"3 c #6D6A5C", +"4 c #757362", +"5 c #787764", +"6 c #7D7B6B", +"7 c #81806F", +"8 c #848372", +"9 c #888675", +"0 c #949484", +"a c #A8A796", +"b c #B3B3A0", +"c c #B9B6A4", +"d c #B4B39F", +"e c #A6A592", +"f c #959482", +"g c #928F7E", +"h c #92917E", +"i c #928F7D", +"j c #3B3A32", +"k c #454337", +"l c #71705B", +"m c #706F5B", +"n c #6C6C5A", +"o c #727261", +"p c #757263", +"q c #757363", +"r c #757563", +"s c #787563", +"t c #787663", +"u c #787863", +"v c #797963", +"w c #7C7969", +"x c #7C7C69", +"y c #7D7C6B", +"z c #7D7D6B", +"A c #7E7D6B", +"B c #807D6B", +"C c #827F6C", +"D c #848270", +"E c #8F8B7D", +"F c #A7A693", +"G c #B2B1A0", +"H c #B6B3A2", +"I c #B6B6A2", +"J c #B3B1A0", +"K c #ADAA99", +"L c #9A9988", +"M c #8C8979", +"N c #8D8A7A", +"O c #8D8D7A", +"P c #8D8B7B", +"Q c #3E3E34", +"R c #34342C", +"S c #726E5C", +"T c #72705E", +"U c #6A6A56", +"V c #72705C", +"W c #71705C", +"X c #716F5E", +"Y c #6D6D5B", +"Z c #6C6B5B", +"` c #6A6758", +" . c #69695A", +".. c #656556", +"+. c #666656", +"@. c #615F53", +"#. c #5F5E4F", +"$. c #5E5D50", +"%. c #5C5950", +"&. c #5C5B4E", +"*. c #59574C", +"=. c #5A594C", +"-. c #5C5D50", +";. c #727166", +">. c #807D71", +",. c #818176", +"'. c #808078", +"). c #7D7D74", +"!. c #777770", +"~. c #6F6E66", +"{. c #5C5C56", +"]. c #717162", +"^. c #8A8874", +"/. c #8A8876", +"(. c #8A8A78", +"_. c #3B3B34", +":. c #706F5D", +"<. c #515044", +"[. c #30312A", +"}. c #2E2D26", +"|. c #2C2B26", +"1. c #2A2A24", +"2. c #282824", +"3. c #272926", +"4. c #252523", +"5. c #262421", +"6. c #232221", +"7. c #282625", +"8. c #232321", +"9. c #212420", +"0. c #1A1919", +"a. c #141411", +"b. c #111214", +"c. c #171616", +"d. c #2C2B2F", +"e. c #404040", +"f. c #484746", +"g. c #4C4C4C", +"h. c #494949", +"i. c #4A4A4A", +"j. c #414146", +"k. c #323235", +"l. c #31312E", +"m. c #62625A", +"n. c #868574", +"o. c #878574", +"p. c #878575", +"q. c #3D3D31", +"r. c #6E6D5B", +"s. c #706E5C", +"t. c #535045", +"u. c #161610", +"v. c #13140D", +"w. c #121519", +"x. c #0B0A0F", +"y. c #0F0F0E", +"z. c #0F0F0D", +"A. c #09090A", +"B. c #060606", +"C. c #060608", +"D. c #050507", +"E. c #07080B", +"F. c #090C14", +"G. c #070708", +"H. c #07080A", +"I. c #1F211F", +"J. c #2D2D2E", +"K. c #333535", +"L. c #323234", +"M. c #343436", +"N. c #353634", +"O. c #373735", +"P. c #373736", +"Q. c #30302F", +"R. c #2B2B29", +"S. c #615F56", +"T. c #82816F", +"U. c #82816D", +"V. c #838172", +"W. c #3C3B34", +"X. c #6C6A5B", +"Y. c #6F6E5C", +"Z. c #5D5D4D", +"`. c #202712", +" + c #1B2C0C", +".+ c #0A0B11", +"++ c #0E1117", +"@+ c #0C0C0D", +"#+ c #111013", +"$+ c #131314", +"%+ c #131310", +"&+ c #101011", +"*+ c #0F1419", +"=+ c #121419", +"-+ c #12110F", +";+ c #1A1B1B", +">+ c #363634", +",+ c #313130", +"'+ c #313131", +")+ c #2F2F31", +"!+ c #343334", +"~+ c #343534", +"{+ c #343433", +"]+ c #333434", +"^+ c #2B2C2C", +"/+ c #232324", +"(+ c #5F5E54", +"_+ c #807F6F", +":+ c #817F6C", +"<+ c #7F7E6C", +"[+ c #434138", +"}+ c #5E5E4E", +"|+ c #6D6A5B", +"1+ c #686554", +"2+ c #101911", +"3+ c #061307", +"4+ c #0B0C09", +"5+ c #0F111D", +"6+ c #0A0D0F", +"7+ c #0A0B09", +"8+ c #0A0A0B", +"9+ c #08080A", +"0+ c #050506", +"a+ c #040405", +"b+ c #040507", +"c+ c #070B11", +"d+ c #0B0C10", +"e+ c #16151A", +"f+ c #202021", +"g+ c #232323", +"h+ c #222625", +"i+ c #292A27", +"j+ c #2B2A2C", +"k+ c #2C2B2D", +"l+ c #2B2B2C", +"m+ c #292929", +"n+ c #242424", +"o+ c #131615", +"p+ c #54584C", +"q+ c #7E7B6C", +"r+ c #7E7E6C", +"s+ c #44443A", +"t+ c #424238", +"u+ c #6D6B5B", +"v+ c #171815", +"w+ c #030203", +"x+ c #040709", +"y+ c #07081E", +"z+ c #01030A", +"A+ c #02070C", +"B+ c #010204", +"C+ c #03030C", +"D+ c #03030B", +"E+ c #010107", +"F+ c #020213", +"G+ c #020208", +"H+ c #040715", +"I+ c #0E0F18", +"J+ c #141412", +"K+ c #1A1A1A", +"L+ c #1E1C21", +"M+ c #202022", +"N+ c #222224", +"O+ c #252524", +"P+ c #242422", +"Q+ c #222120", +"R+ c #1A1D1C", +"S+ c #0F100F", +"T+ c #55544A", +"U+ c #7A7964", +"V+ c #7A7968", +"W+ c #404038", +"X+ c #6A6A57", +"Y+ c #6C6B59", +"Z+ c #22241E", +"`+ c #040403", +" @ c #030506", +".@ c #04090C", +"+@ c #010303", +"@@ c #03060F", +"#@ c #03030D", +"$@ c #030314", +"%@ c #020306", +"&@ c #02030B", +"*@ c #0A1016", +"=@ c #131A1F", +"-@ c #141717", +";@ c #181814", +">@ c #1D1C18", +",@ c #1E1D20", +"'@ c #202020", +")@ c #202026", +"!@ c #1F1E1D", +"~@ c #1C1D1E", +"{@ c #151515", +"]@ c #0D0F0F", +"^@ c #54544C", +"/@ c #787668", +"(@ c #787664", +"_@ c #7A7664", +":@ c #434136", +"<@ c #6B6A57", +"[@ c #6D695B", +"}@ c #302F29", +"|@ c #020415", +"1@ c #010306", +"2@ c #06070E", +"3@ c #030608", +"4@ c #030609", +"5@ c #020307", +"6@ c #050714", +"7@ c #04030A", +"8@ c #0E0F20", +"9@ c #161834", +"0@ c #121418", +"a@ c #171816", +"b@ c #181A1B", +"c@ c #1B1B17", +"d@ c #1C1C1C", +"e@ c #1B1B1F", +"f@ c #1A191A", +"g@ c #171519", +"h@ c #100D0B", +"i@ c #07090D", +"j@ c #454945", +"k@ c #757564", +"l@ c #767668", +"m@ c #777664", +"n@ c #4A493E", +"o@ c #686753", +"p@ c #696955", +"q@ c #403F37", +"r@ c #080807", +"s@ c #050505", +"t@ c #040415", +"u@ c #05050E", +"v@ c #03060A", +"w@ c #04050D", +"x@ c #050708", +"y@ c #030305", +"z@ c #04060B", +"A@ c #02030A", +"B@ c #090916", +"C@ c #131327", +"D@ c #101012", +"E@ c #111113", +"F@ c #151213", +"G@ c #171618", +"H@ c #171714", +"I@ c #161614", +"J@ c #151614", +"K@ c #141413", +"L@ c #0F1012", +"M@ c #070707", +"N@ c #090808", +"O@ c #464339", +"P@ c #737060", +"Q@ c #727263", +"R@ c #727262", +"S@ c #47473F", +"T@ c #696958", +"U@ c #090907", +"V@ c #0D0E13", +"W@ c #0B0B09", +"X@ c #0E0E11", +"Y@ c #0B0B0C", +"Z@ c #090A0D", +"`@ c #09090E", +" # c #030504", +".# c #020205", +"+# c #060605", +"@# c #09090B", +"## c #0C0C0B", +"$# c #0E0E12", +"%# c #11120D", +"&# c #121212", +"*# c #121214", +"=# c #121311", +"-# c #0F0F12", +";# c #0B0C0A", +"># c #030304", +",# c #0C0D0D", +"'# c #4C4C42", +")# c #70705C", +"!# c #727162", +"~# c #47453D", +"{# c #545345", +"]# c #676658", +"^# c #535143", +"/# c #0C0C0A", +"(# c #121314", +"_# c #141517", +":# c #131312", +"<# c #080A08", +"[# c #060707", +"}# c #040506", +"|# c #080806", +"1# c #0A0A0A", +"2# c #0B0D0D", +"3# c #0E0E0C", +"4# c #0E0E0E", +"5# c #0A0A0C", +"6# c #060505", +"7# c #45443C", +"8# c #6F6C5A", +"9# c #726F5D", +"0# c #72715C", +"a# c #47463D", +"b# c #34342A", +"c# c #696858", +"d# c #585648", +"e# c #2E1911", +"f# c #290704", +"g# c #0E0F0C", +"h# c #090B0B", +"i# c #0C0C10", +"j# c #181919", +"k# c #0C0D0A", +"l# c #0B0D12", +"m# c #0A0D0D", +"n# c #010305", +"o# c #020304", +"p# c #0B0B0A", +"q# c #0D0B0C", +"r# c #0C0B0A", +"s# c #0A0B0E", +"t# c #0B0B0B", +"u# c #0C0C0C", +"v# c #0B0A0B", +"w# c #090905", +"x# c #050608", +"y# c #373733", +"z# c #696959", +"A# c #6E6D5C", +"B# c #4F4D43", +"C# c #323229", +"D# c #686553", +"E# c #5A594D", +"F# c #3D201B", +"G# c #480904", +"H# c #111012", +"I# c #111114", +"J# c #080A09", +"K# c #121515", +"L# c #0A0F10", +"M# c #0F1219", +"N# c #0B1217", +"O# c #010608", +"P# c #030605", +"Q# c #0E0E0F", +"R# c #111010", +"S# c #0C1011", +"T# c #090A0E", +"U# c #070706", +"V# c #060709", +"W# c #080608", +"X# c #050404", +"Y# c #030204", +"Z# c #666555", +"`# c #6E6B5C", +" $ c #6D6B5A", +".$ c #4D4D3F", +"+$ c #313129", +"@$ c #656553", +"#$ c #5E5D4D", +"$$ c #3B2B22", +"%$ c #510905", +"&$ c #181829", +"*$ c #101021", +"=$ c #161318", +"-$ c #0D0C15", +";$ c #070811", +">$ c #04040C", +",$ c #050611", +"'$ c #03040F", +")$ c #010105", +"!$ c #020103", +"~$ c #050504", +"{$ c #060604", +"]$ c #171817", +"^$ c #090908", +"/$ c #242420", +"($ c #626154", +"_$ c #6B6A5C", +":$ c #4E4B41", +"<$ c #272721", +"[$ c #605F4F", +"}$ c #616050", +"|$ c #343328", +"1$ c #300805", +"2$ c #170E0E", +"3$ c #110A0A", +"4$ c #0B0713", +"5$ c #0A0511", +"6$ c #090813", +"7$ c #0B0814", +"8$ c #0F0A1C", +"9$ c #09021C", +"0$ c #0B0320", +"a$ c #0A0329", +"b$ c #050337", +"c$ c #020240", +"d$ c #05054E", +"e$ c #0B0C4E", +"f$ c #0E0E30", +"g$ c #0D1022", +"h$ c #080B1A", +"i$ c #050812", +"j$ c #050810", +"k$ c #050711", +"l$ c #070716", +"m$ c #08080C", +"n$ c #61604F", +"o$ c #6A6A59", +"p$ c #4E4D3F", +"q$ c #1E1F1B", +"r$ c #5A5A4C", +"s$ c #646152", +"t$ c #3A392F", +"u$ c #200906", +"v$ c #150303", +"w$ c #0E0303", +"x$ c #0E0203", +"y$ c #210A03", +"z$ c #0D0203", +"A$ c #100403", +"B$ c #1B0603", +"C$ c #210503", +"D$ c #260703", +"E$ c #270803", +"F$ c #120605", +"G$ c #090909", +"H$ c #09093B", +"I$ c #020224", +"J$ c #03033A", +"K$ c #02023E", +"L$ c #030335", +"M$ c #04043A", +"N$ c #030336", +"O$ c #030324", +"P$ c #23231C", +"Q$ c #5F5F52", +"R$ c #6A6855", +"S$ c #6A6A58", +"T$ c #545348", +"U$ c #4E4D42", +"V$ c #636453", +"W$ c #424036", +"X$ c #190C09", +"Y$ c #110403", +"Z$ c #0B0103", +"`$ c #130103", +" % c #210603", +".% c #110203", +"+% c #070203", +"@% c #0B0203", +"#% c #1B0703", +"$% c #1F0603", +"%% c #0E0E10", +"&% c #04043F", +"*% c #020216", +"=% c #020229", +"-% c #020233", +";% c #020238", +">% c #020234", +",% c #020327", +"'% c #20201C", +")% c #5C5C4D", +"!% c #69685A", +"~% c #676756", +"{% c #545143", +"]% c #010102", +"^% c #4B493F", +"/% c #626454", +"(% c #4E4C3F", +"_% c #343128", +":% c #292921", +"<% c #27231D", +"[% c #281F19", +"}% c #221A13", +"|% c #1A1512", +"1% c #1A1311", +"2% c #13100F", +"3% c #17100E", +"4% c #1E100D", +"5% c #1E0C0B", +"6% c #110B09", +"7% c #080809", +"8% c #0C0D1A", +"9% c #060619", +"0% c #02020F", +"a% c #020212", +"b% c #020219", +"c% c #02021C", +"d% c #02021A", +"e% c #1B1B1A", +"f% c #59594A", +"g% c #676655", +"h% c #666657", +"i% c #000001", +"j% c #46453C", +"k% c #626254", +"l% c #5D5D4E", +"m% c #5C5C4E", +"n% c #5F5E50", +"o% c #5C5C4B", +"p% c #5A594B", +"q% c #585749", +"r% c #585447", +"s% c #515143", +"t% c #4E4C41", +"u% c #4B4B3F", +"v% c #4A453A", +"w% c #413F35", +"x% c #3D3D33", +"y% c #363442", +"z% c #312F41", +"A% c #2A293C", +"B% c #26263A", +"C% c #222238", +"D% c #1E1E2F", +"E% c #1A1A2B", +"F% c #18162A", +"G% c #161528", +"H% c #272636", +"I% c #59594F", +"J% c #686455", +"K% c #676556", +"L% c #555548", +"M% c #3A3930", +"N% c #625F4F", +"O% c #5E5E50", +"P% c #606052", +"Q% c #646254", +"R% c #636254", +"S% c #656454", +"T% c #656354", +"U% c #646454", +"V% c #636354", +"W% c #656254", +"X% c #636253", +"Y% c #605F51", +"Z% c #616051", +"`% c #5F6150", +" & c #605F50", +".& c #5D5D4F", +"+& c #5B5A53", +"@& c #595751", +"#& c #555550", +"$& c #514F4F", +"%& c #53504C", +"&& c #616052", +"*& c #636454", +"=& c #646455", +"-& c #585948", +";& c #20201D", +">& c #625F4E", +",& c #605D4D", +"'& c #626153", +")& c #626152", +"!& c #646354", +"~& c #626553", +"{& c #636553", +"]& c #595949", +"^& c #4B4941", +"/& c #524F44", +"(& c #5C5C4C", +"_& c #605E4E", +":& c #636153", +"<& c #626050", +"[& c #626051", +"}& c #5D6F4C", +"|& c #3D9F32", +"1& c #35A92D", +"2& c #59764B", +"3& c #59574B", +"4& c #4A483D", +"5& c #4F4C41", +"6& c #515043", +"7& c #565548", +"8& c #595846", +"9& c #5C5A4B", +"0& c #5F5E4E", +"a& c #5F6750", +"b& c #507F44", +"c& c #4B8640", +"d& c #5D6B4F", +"e& c #504F43", +"f& c #555546", +"g& c #535246", +"h& c #514F40", +"i& c #4F4D40", +"j& c #4C4C40", +"k& c #4D4A40", +"l& c #4A4A3F", +"m& c #49493E", +"n& c #49483E", +"o& c #4A483E", +"p& c #4A493C", +"q& c #505042", +"r& c #525242", +"s& c #555248", +"t& c #585748", +"u& c #5C5949", +"v& c #5C5B4C", +"w& c #5D5A4E", +"x& c #5E5D4E", +"y& c #5F5C4D", +"z& c #5F5E51", +"A& c #5F5F50", +"B& c #5F5E4C", +"C& c #5E5E4C", +"D& c #5D5A4A", +"E& c #5A5848", +"F& c #565445", +"G& c #535144", +"H& c #4F4E43", +"I& c #4D4D40", +"J& c #4A4A40", +"K& c #4B4A3C", +"L& c #4B4B3E", +"M& c #4E4E40", +"N& c #333329", +"O& c #2E2E27", +"P& c #303029", +"Q& c #4D4D44", +"R& c #575547", +"S& c #5C594C", +"T& c #605D4C", +"U& c #605E4C", +"V& c #5E5D4C", +"W& c #5F5D4C", +"X& c #5D5B4A", +"Y& c #5B5A4A", +"Z& c #585848", +"`& c #535345", +" * c #524F42", +".* c #3C3A34", +"+* c #414138", +"@* c #45453D", +"#* c #484638", +"$* c #464638", +"%* c #525248", +"&* c #595749", +"** c #5A584C", +"=* c #5D5D4C", +"-* c #5F5E4D", +";* c #5E5E4D", +">* c #000000", +",* c #21211D", +"'* c #23231F", +")* c #2D2D25", +"!* c #302E27", +"~* c #302E26", +"{* c #37352E", +"]* c #4C4B40", +"^* c #525144", +"/* c #5F5F5F", +"(* c #BFBFBF", +"_* c #8F8F8F", +":* c #FFFFFF", +"<* c #3F3F3F", +"[* c #6F6F6F", +"}* c #7F7F7F", +"|* c #1F1F1F", +"1* c #FEFEFE", +"2* c #2F2F2F", +"3* c #EFEFEF", +"4* c #DFDFDF", +"5* c #9F9F9F", +"6* c #0F0F0F", +" ", +" ", +" ", +" ", +" . + @ # $ % & * = - ; > , ' ) ! ~ @ { ] ", +" ^ / ( _ : < [ } | 1 2 2 3 4 5 6 7 8 9 0 a b c c d e f g h i j { ] ", +" k l m n o 4 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 ` ...+.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.{ ] ", +" W :.<.[.}.|.1.2.3.4.5.6.7.8.9.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.C.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.{ ] ", +" X.Y.Z.`. +.+++@+#+$+%+&+y.&+*+=+-+;+>+,+'+)+!+~+{+]+^+/+(+_+:+<+[+{ ] ", +" }+|+1+2+3+4+5+6+7+8+9+0+a+a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+r+r+s+{ ] ", +" t+n 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+U+W+{ ] ", +" X+Y+Z+`+ @.@+@@@] #@$@%@@@&@*@=@-@;@>@,@'@'@)@!@~@{@]@^@/@(@_@:@{ ] ", +" <@[@}@0+`+|@1@2@] 3@4@5@6@7@8@9@0@$+a@b@c@d@e@f@g@h@i@j@k@l@m@n@{ ] ", +" o@p@q@r@s@t@u@v@w@C.x@y@z@A@B@C@D@E@F@G@H@I@J@K@L@M@N@O@P@Q@R@S@{ ] ", +" #.T@n@U@M@V@W@X@Y@Z@`@ #.#.#+#@###$#%#&#*#$+=#-#;#>#,#'#)#!#V ~#{ ] ", +" {#]#^#/#G.(#_#:#<#[#}#] { { >#|#1#2#3#z.-#4#3#5#6#] 8+7#8#9#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#] ] C.y#z#A#A#B#{ ] ", +" C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#r@V#W#X#Y#] ] ] . Z#`# $.${ ] ", +" +$@$#$$$%$&$*$=$-$;$>$,$'$)${ !$`+~$>#{$]$^$] ] ] ] ] /$($_$X.:${ ] ", +" <$[$}$|$1$2$3$4$5$6$7$8$9$0$a$b$c$d$e$f$g$h$i$j$k$l$m$. n$o$U p${ ] ", +" q$r$s$t$u$v$w$x$y$z$A$B$C$D$E$F$a+G$b.H$I$J$K$L$M$N$O$P$Q$R$S$T${ ] ", +" U$V$W$X$Y$Z$`$ %.%+%@%#%$%C$A${ D.%%&%*%=%-%;%;%>%,%'%)%!%~%{%{ ]% ", +" ^%/%(%_%:%<%[%}%|%1%2%3%4%5%6%7%E.8%9%0%a%b%b%c%d%F+e%f%g%h%^#{ i% ", +" j%k%l%m%n%Z.o%p%q%r%s%t%u%v%w%x%y#y%z%A%B%C%D%E%F%G%H%I%J%K%L%{ i% ", +" M%N%O%P%N%k%Q%R%Q%S%T%U%V%W%X%s$Y%Z%`% &#..&+&@&#&$&%&&&*&=&-&{ ", +" ;&>&,&n%'&'&k%'&)&'&W%W%k%Q%R%Q%*&W%R%R%W%W%S%!&Q%~&{&W%R%W%]&]% ", +" ^&: /&(&_&'&:&<&'&[&k%k%k%W%R%W%R%R%V%k%R%k%R%k%}&|&1&2&Q%3&]% ", +" 4&5&6&T$7&8&9&0&N%k%k%R%k%N%k%R%R%Q%R%k%a&b&c&d&Z%p%]% ", +" e&f&g&h&i&j&k&l&m&n&o&p&'#q&r&s&7&t&u&v&w&x&y&z&A&[$0& ", +" i&B&B&B&C&C&v&D&E&d#t&F&G&<.<.H&I&J&K&L&J&j&M&H&N&O&}@ ", +" P&Q&R&S&T&C&B&B&C&U&B&V&W&T&o%X&Y&&.p%Z&L%`& *U# ", +" .*W++*@*#*$*%*&***Y&=*-*B&;*;*C&]% ", +" >*>*>*>*>*>*>*>*>* ,*'*<$)*!*~*{*]*^* ", +" >*/*(*(*(*(*(*(*(*_*>* >*>* ", +" >*>*:*:*<*>*>*_*(*>*>*[*}*>* ", +" >*>*:*:*<*>*<*|*(*>*/*1*}*>* >*>*>*>* >*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>* ", +" >*>*:*:*<*>*}*<*2*/*3*:*4*(*>*>*_*(*(*2*>*/*(*(*/*_*(*/*>*(*(*(*(*(*(*>*/*(*_*>* ", +" >*>*:*:*[*[*:*<*>*>*(*:*}*>*>*}*:*>*}*:*2*>*(*:*4*(*:*}*>*<*:*:*>*}*:*3*/*(*:*}*>* ", +" >*>*:*:*5*5*:*<*>*>*(*:*}*>*|*(*:*>*}*:*(*>*(*:*}*>*}*<*>*<*:*:*>*}*:*(*>*(*:*}*>* ", +" >*>*:*:*<*6*5*<*>*>*(*:*}*>*<*:*:*(*4*:*(*>*(*:*}*>*>*>*>*<*:*:*>*}*:*(*>*(*:*}*>* ", +" >*>*:*:*<*>*/*2*6*|*(*:*}*>*<*:*:*>*>*>*>*>*(*:*}*>* >*<*:*:*>*}*:*(*>*(*:*}*>* ", +" >*>*:*:*<*>*>*>*<*}*(*:*}*>*<*:*:*/*>*>*/*>*(*:*}*>* >*<*:*:*>*}*:*(*>*(*:*}*>* ", +" >*>*:*:*<*>*>*_*5*|*(*:*}*_*6*5*:*3*(*(*2*>*(*:*}*>* >*<*:*:*>*}*:*(*>*(*:*}*>* ", +" >*/*(*(*(*(*(*(*(*_*>*>*(*(*2*>*>*_*(*(*2*>*/*(*(*(*2*>* >*(*(*(*(*(*(*(*(*(*(*(*2*>* ", +" >*>*>*>*>*>*>*>*>* >*>*>* >*>*>*>* >*>*>*>*>* >*>*>*>*>*>*>*>*>*>*>*>* ", +" "}; diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..429a74b --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,30 @@ +# $Id$ + +lib_LTLIBRARIES = libEterm.la + +libEterm_la_SOURCES = activeconfig.c activeeterm.c activetags.c command.c \ + graphics.c grkelot.c menubar.c misc.c netdisp.c options.c \ + pixmap.c screen.c scrollbar.c system.c threads.c utmp.c + +libEterm_la_LDFLAGS = -version-info 8:9:8 + +bin_PROGRAMS = Eterm + +Eterm_SOURCES = main.c + +Eterm_DEPENDENCIES = ../libmej/libmej.la feature.h + +INCLUDES = -I. -I../libmej -I.. -I$(includedir) -I$(prefix)/include $(X_CFLAGS) + +Eterm_LDFLAGS = -rpath $(libdir):$(pkglibdir) +LDADD = -L$(DIST_ROOT)/src/.libs -lEterm -L$(DIST_ROOT)/libmej/.libs -L$(libdir) -L$(prefix)/lib $(LIBS) -lmej $(GRLIBS) $(X_LIBS) + +EXTRA_DIST = activeconfig.h activeeterm.h activetags.h command.h debug.h \ + eterm_imlib.h feature.h.in graphics.h grkelot.h grx.h main.h \ + menubar.h misc.h options.h pixmap.h profile.h screen.h scrollbar.h \ + system.h threads.h graphics/Makefile.am graphics/Makefile.in \ + graphics/README graphics/data graphics/grxlib.c graphics/grxlib.h \ + graphics/qplot.c Eterm.xpm + +feature.h: feature.h.in + $(FEATURE_CMD) diff --git a/src/activeconfig.c b/src/activeconfig.c new file mode 100644 index 0000000..902798c --- /dev/null +++ b/src/activeconfig.c @@ -0,0 +1,623 @@ +/*--------------------------------*-C-*---------------------------------* + * File: activeconfig.c + * + * Copyright 1997 Nat Friedman, Massachusetts Institute of Technology + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + *----------------------------------------------------------------------*/ + +/* This file contains all the config file parsing functionality */ + +static const char cvs_ident[] = "$Id$"; + +#include "feature.h" +#ifdef USE_ACTIVE_TAGS + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "activeconfig.h" + +/* The basic design of the config file parsing routines revolves around the + dispatch table below. The dispatch table relates file tokens with + their parsing functions. In order to add a new config file token + (for example "Foo=something"), simply define TAG_CONFIG_FOO, write + parse_config_tag_foo, and then add the following line to the dispatch + table: + + {TAG_CONFIG_FOO, parse_config_tag_foo} + + and it will magically work. */ + +/* This is the actual dispatch table. It should be terminated by a struct + config_entry whose parser field is NULL. */ +struct config_entry config_dispatch[] = +{ + {TAG_CONFIG_LOAD, parse_config_load}, + {TAG_CONFIG_DEFAULT_BINDING, parse_config_default_binding}, + {TAG_CONFIG_DEFAULT_HIGHLIGHT, parse_config_default_highlight}, + {TAG_CONFIG_DEFAULT_SEARCH_LINES, parse_config_default_search_lines}, + {TAG_CONFIG_NEW_TAG, parse_config_tag_begin}, + {TAG_CONFIG_END_TAG, parse_config_tag_end}, + {TAG_CONFIG_LATENT, parse_config_tag_latent}, + {TAG_CONFIG_BINDING, parse_config_tag_binding}, + {TAG_CONFIG_HIGHLIGHT, parse_config_tag_highlight}, + {TAG_CONFIG_MODES, parse_config_tag_modes}, + {TAG_CONFIG_REGEXP, parse_config_tag_regexp}, + {TAG_CONFIG_ACTION, parse_config_tag_action}, + {TAG_CONFIG_OUTPUT, parse_config_tag_output}, + {TAG_CONFIG_SEARCH_LINES, parse_config_tag_search_lines}, + {TAG_CONFIG_CLUE, parse_config_tag_clue}, + {TAG_CONFIG_ENV, parse_config_tag_env}, + {"", NULL} +}; + +/* + Dispatch Functions + */ + +int +parse_config_tag_env(char *envlist, struct config_info *config_info) +{ + char *p, *q; + int nenvs = 0; + + p = envlist; + do { + printf("Env...\n"); + if ((q = strchr(p, ',')) == NULL) + q = p + strlen(p); + strncpy(tag[config_info->curr_tag].env[nenvs], p, q - p); + tag[config_info->curr_tag].env[nenvs][q - p] = '\0'; + printf("got env: %s\n", tag[config_info->curr_tag].env[nenvs]); + nenvs++; + if (*q != ',') + p = NULL; + else + p = q + 1; + } while (p != NULL); + tag[config_info->curr_tag].num_envs = nenvs; + + printf("Got envs for tag:\n"); + for (nenvs = 0; nenvs < tag[config_info->curr_tag].num_envs; nenvs++) + printf("Env %d: (%s)\n", nenvs, tag[config_info->curr_tag].env[nenvs]); + return 1; +} + +int +parse_config_load(char *filename, struct config_info *config_info) +{ + struct config_info new_config_info; + + /* Scope on Defaults is per-file */ + set_config_defaults(&new_config_info); + new_config_info.curr_tag = config_info->curr_tag; + + /* If it's a relative file name, make it absolute */ + if (*filename != '/') { + char new_filename[1024]; + char *p, *q; + + if ((p = strrchr(config_info->filename, '/')) == NULL) + configerror(config_info, "Could not determine path to file!"); + q = config_info->filename; + + strcpy(new_filename, q); + new_filename[p - q] = '\0'; + strcat(new_filename, "/"); + strcat(new_filename, filename); + printf("Filename: %s\n", new_filename); + strcpy(filename, new_filename); + } + /* FIXME: This implementation forces pathnames to be absolute. We should + allow relative pathnames somehow. */ + parse_tag_file(filename, &new_config_info); + + config_info->curr_tag = new_config_info.curr_tag; + + return 1; +} + +int +parse_config_default_binding(char *def, + struct config_info *config_info) +{ + config_info->default_binding = string_to_binding_mask(config_info, def); + if (!(config_info->default_binding & (TAG_BINDING_BUTTON1 | TAG_BINDING_BUTTON2 | + TAG_BINDING_BUTTON3))) { + configerror(config_info, "Error reading default binding: binding _must_ " + "include either Button1, Button2, or Button3. Reverting to " + "compiled default."); + config_info->default_binding = TAG_DEFAULT_BINDING_MASK; + } + return 1; +} + +int +parse_config_default_highlight(char *def, + struct config_info *config_info) +{ + string_to_highlight(config_info, &config_info->default_highlight, def); + return 1; +} + +int +parse_config_default_search_lines(char *def, + struct config_info *config_info) +{ + if ((config_info->default_search_lines = atoi(def)) == 0) { + configerror(config_info, "Invalid default number of search lines. " + "Reverting to compiled default.\n"); + config_info->default_search_lines = TAG_DEFAULT_SEARCH_LINES; + } + if (config_info->default_search_lines > MAX_SEARCH_LINES) { + configerror(config_info, "Default number of search lines > maximum. " + "Reverting to compiled default.\n"); + config_info->default_search_lines = TAG_DEFAULT_SEARCH_LINES; + } + return 1; +} + +int +parse_config_tag_begin(char *s, struct config_info *config_info) +{ + fprintf(stderr, "New tag\n"); + if (config_info->in_tag) { + configerror(config_info, "Open brace inside braces"); + disable_tags(); + return -1; + } + if ((config_info->curr_tag + 1) >= MAX_TAGS) { + configerror(config_info, "Too many tags! Increase the maximum number " + "of tags and recompile!\n"); + disable_tags(); + return -1; + } + config_info->in_tag = 1; + + /* Initialize the new tag with all the default values. */ + tag[config_info->curr_tag].binding_mask = config_info->default_binding; + tag[config_info->curr_tag].search_lines = config_info->default_search_lines; + tag[config_info->curr_tag].highlight.attributes = + config_info->default_highlight.attributes; + tag[config_info->curr_tag].highlight.fg_color = + config_info->default_highlight.fg_color; + tag[config_info->curr_tag].highlight.bg_color = + config_info->default_highlight.bg_color; + tag[config_info->curr_tag].num_modes = 0; + tag[config_info->curr_tag].latent = 0; + tag[config_info->curr_tag].output_type = TAG_OUTPUT_NULL; + +#ifdef ACTIVE_TAGS_SPENCER_REGEXP + tag[config_info->curr_tag].rx = NULL; +#endif + + return 1; +} + +int +parse_config_tag_end(char *s, struct config_info *config_info) +{ + if (!config_info->in_tag) { + configerror(config_info, "close brace without open brace"); + disable_tags(); + return -1; + } + /* Make sure that the tag was setup properly before advancing to the next + one in the list */ + + /* FIXME: we need a way of figuring this out if we're using POSIX regex */ +#ifdef ACTIVE_TAGS_SPENCER_REGEXP + if (tag[config_info->curr_tag].rx == NULL) { + configerror("No regular epxression supplied for tag. Tag ignored."); + config_info->curr_tag--; + } +#endif + + config_info->in_tag = 0; + config_info->curr_tag++; + + return 1; +} + +int +parse_config_tag_latent(char *latent, struct config_info *config_info) +{ + if (!strcasecmp(latent, "true")) + tag[config_info->curr_tag].latent = 1; + return 1; +} + +int +parse_config_tag_search_lines(char *sl, struct config_info *config_info) +{ + if (atoi(sl)) + tag[config_info->curr_tag].search_lines = atoi(sl); + + D_TAGS(("==> Setting tag %d's search lines to %d\n", config_info->curr_tag, atoi(sl))); + + return 1; +} + +int +parse_config_tag_binding(char *s, struct config_info *config_info) +{ + tag[config_info->curr_tag].binding_mask = string_to_binding_mask(config_info, s); + return 1; +} + +int +parse_config_tag_highlight(char *s, struct config_info *config_info) +{ + string_to_highlight(config_info, &tag[config_info->curr_tag].highlight, s); + return 1; +} + +int +parse_config_tag_modes(char *s, struct config_info *config_info) +{ + char *mode, *p; + + mode = s; + + while (mode != NULL) { + if ((p = strchr(mode, ',')) != NULL) + *p = '\0'; + strcpy(tag[config_info->curr_tag].mode[tag[config_info->curr_tag].num_modes], mode); + if (p != NULL) + mode = p + 1; + else + mode = NULL; + + tag[config_info->curr_tag].num_modes++; + } + + return 1; +} + +int +parse_config_tag_regexp(char *regexp, struct config_info *config_info) +{ +#ifdef ACTIVE_TAGS_SPENCER_REGEXP + if ((tag[config_info->curr_tag].rx = regcomp(regexp)) == NULL) +#else + if (regcomp(&tag[config_info->curr_tag].rx, regexp, REG_EXTENDED) != 0) +#endif + { + configerror(config_info, "Couldn't compile regular expression"); + return -1; + } + return 1; +} + +int +parse_config_tag_action(char *action, struct config_info *config_info) +{ + strcpy(tag[config_info->curr_tag].action, action); + return 1; +} + +int +parse_config_tag_output(char *output, struct config_info *config_info) +{ + if (!strcasecmp(output, "null")) + tag[config_info->curr_tag].output_type = TAG_OUTPUT_NULL; + else if (!strcasecmp(output, "loop")) + tag[config_info->curr_tag].output_type = TAG_OUTPUT_LOOP; + else if (!strcasecmp(output, "replace")) + tag[config_info->curr_tag].output_type = TAG_OUTPUT_REPL; + else if (!strcasecmp(output, "popup")) + tag[config_info->curr_tag].output_type = TAG_OUTPUT_POPUP; + else { + configerror(config_info, "Unknown output method; defaulting to NULL"); + tag[config_info->curr_tag].output_type = TAG_OUTPUT_NULL; + } + + return 1; +} + +int +parse_config_tag_clue(char *clue, struct config_info *config_info) +{ + strcpy(tag[config_info->curr_tag].clue, clue); + return 1; +} + + + +void +set_config_defaults(struct config_info *config_info) +{ + config_info->default_binding = TAG_DEFAULT_BINDING_MASK; + config_info->default_search_lines = TAG_DEFAULT_SEARCH_LINES; + config_info->default_highlight.bg_color = TAG_DEFAULT_HIGHLIGHT_BG; + config_info->default_highlight.fg_color = TAG_DEFAULT_HIGHLIGHT_FG; + config_info->default_highlight.attributes = TAG_DEFAULT_HIGHLIGHT_ATT; + config_info->curr_tag = 0; + config_info->line_num = 0; + config_info->in_tag = 0; +} + +/* parse_tag_config actually reads the file and calls the dispatch functions + where appropriate */ +void +parse_tag_config(char *tag_config_file) +{ + char file_name[1024]; + struct passwd *user; + + struct config_info config_info; + + /* Set the defaults */ + set_config_defaults(&config_info); + + if (tag_config_file != NULL) + if (!parse_tag_file(tag_config_file, &config_info)) { + fprintf(stderr, "parse_tag_config: Couldn't open tag config" + "file: %s\n", tag_config_file); + tag_config_file = NULL; + } + if (tag_config_file == NULL) { + user = getpwuid(getuid()); + sprintf(file_name, "%s/%s", user->pw_dir, TAG_CONFIG_USER_FILENAME); + if (!parse_tag_file(file_name, &config_info)) { + fprintf(stderr, "parse_tag_config: Couldn't open user tag config " + "file: %s\n", file_name); + fprintf(stderr, "parse_tag_config: Trying system config file\n"); + + /* Try the system-wide config file */ + if (!parse_tag_file(TAG_CONFIG_SYSTEM_FILENAME, &config_info)) { + fprintf(stderr, "parse_tag_config: Error parsing config file: " + "%s\n", TAG_CONFIG_SYSTEM_FILENAME); + disable_tags(); + return; + } + } + } + num_tags = config_info.curr_tag; + printf("Num tags: %d\n", num_tags); + { + int i; + + for (i = 0; i < num_tags; i++) + printf("Tag action(%d): %s\n", i, tag[i].action); + } +} + +int +parse_tag_file(const char *filename, struct config_info *config_info) +{ + FILE *tag_file; + char line[1024]; + int i; + + if ((tag_file = fopen(filename, "r")) == NULL) + return 0; + + strcpy(config_info->filename, filename); + + /* Loop through the config file lines */ + while (!feof(tag_file)) { + fgets(line, sizeof(line), tag_file); + config_info->line_num++; + + if (feof(tag_file)) + break; + + if (line[strlen(line) - 1] != '\n') { + configerror(config_info, "line too long?"); + exit(1); + } + line[strlen(line) - 1] = '\0'; + + /* Loop through the config file lines, calling the appropriate + functions from the dispatch table as we go. If there is no + corresponding function, flag a warning and try to continue. */ + if ((line[0] != '#') && (!isspace(line[0])) && (strlen(line) != 0)) { + for (i = 0; config_dispatch[i].parser != NULL; i++) + if (TAG_CONFIG(config_dispatch[i].token)) { + if ((strchr(line, '=') == NULL) && (*line != '{') && + (*line != '}') && !TAG_CONFIG(TAG_CONFIG_LOAD)) + configerror(config_info, "'=' not found"); + else { + char *p; + + p = line + strlen(config_dispatch[i].token) + 1; + if (strchr(line, '=') != NULL) { + p = strchr(line, '=') + 1; + while (isspace(*p)) + p++; + } + if (!((config_dispatch[i].parser) (p, config_info))) + return 0; + break; + } + } + if (config_dispatch[i].parser == NULL) + configerror(config_info, "Unrecognized token"); + } + } + fclose(tag_file); + + return 1; +} + +/* + Internal Functions + */ + +/* Use this function to display errors encountered while parsing the config + file to keep them looking uniform */ +void +configerror(struct config_info *config_info, char *message) +{ + fprintf(stderr, "active tags: error on line %d of config file %s: %s\n", + config_info->line_num, config_info->filename, message); +} + +void +string_to_color(struct config_info *config_info, tag_highlight_t * highlight, + char *c) +{ +#if 0 + int color; + +#endif + int color = 0; + int bg = 0; + char *p; + + p = c; + + /* Background colors are prefaced by a '*' */ + if (*p == '*') { + bg = 1; + p++; + } + if (!strcasecmp(p, "Black")) + color = TAG_HIGHLIGHT_BLACK; + else if (!strcasecmp(p, "White")) + color = TAG_HIGHLIGHT_WHITE; + else if (!strcasecmp(p, "Red")) + color = TAG_HIGHLIGHT_RED; + else if (!strcasecmp(p, "Green")) + color = TAG_HIGHLIGHT_GREEN; + else if (!strcasecmp(p, "Yellow")) + color = TAG_HIGHLIGHT_YELLOW; + else if (!strcasecmp(p, "Blue")) + color = TAG_HIGHLIGHT_BLUE; + else if (!strcasecmp(p, "Magenta")) + color = TAG_HIGHLIGHT_MAGENTA; + else if (!strcasecmp(p, "Cyan")) + color = TAG_HIGHLIGHT_CYAN; + else if (!strcasecmp(p, "Normal")) + color = TAG_HIGHLIGHT_NORMAL; + else + configerror(config_info, "Unrecognized highlight token"); + + if (bg) + highlight->bg_color = color; + else + highlight->fg_color = color; +} + +void +string_to_highlight(struct config_info *config_info, tag_highlight_t * + highlight, char *s) +{ + char *h_bit; + + /* att_set is 0 if we've set an attribute value and 1 otherwise. We have to + keep track of this because setting an attribute value should override the + default, so we can't blindly OR the new values with whatever was in + highlight->attribute before. So, if we've already overriden the value, + we OR. If we haven't yet overriden it, then we do so and set att_set to + 1. */ + int att_set = 0; + + h_bit = strtok(s, "&"); + + while (h_bit != NULL) { + if (!strcasecmp(h_bit, "Underline")) { + if (att_set) + highlight->attributes |= TAG_HIGHLIGHT_ULINE; + else { + highlight->attributes = TAG_HIGHLIGHT_ULINE; + highlight->fg_color = TAG_HIGHLIGHT_NORMAL; + highlight->bg_color = TAG_HIGHLIGHT_NORMAL; + att_set = 1; + } + } else if (!strcasecmp(h_bit, "Bold")) { + if (att_set) + highlight->attributes |= TAG_HIGHLIGHT_BOLD; + else { + highlight->attributes = TAG_HIGHLIGHT_BOLD; + highlight->fg_color = TAG_HIGHLIGHT_NORMAL; + highlight->bg_color = TAG_HIGHLIGHT_NORMAL; + att_set = 1; + } + } else if (!strcasecmp(h_bit, "RVid")) { + if (att_set) + highlight->attributes |= TAG_HIGHLIGHT_RVID; + else { + highlight->attributes = TAG_HIGHLIGHT_RVID; + highlight->fg_color = TAG_HIGHLIGHT_NORMAL; + highlight->bg_color = TAG_HIGHLIGHT_NORMAL; + att_set = 1; + } + } else if (!strcasecmp(h_bit, "Blink")) { + if (att_set) + highlight->attributes |= TAG_HIGHLIGHT_BLINK; + else { + highlight->attributes = TAG_HIGHLIGHT_BLINK; + highlight->fg_color = TAG_HIGHLIGHT_NORMAL; + highlight->bg_color = TAG_HIGHLIGHT_NORMAL; + att_set = 1; + } + } else { + if (att_set) + string_to_color(config_info, highlight, h_bit); + else { + att_set = 1; + highlight->fg_color = TAG_HIGHLIGHT_NORMAL; + highlight->bg_color = TAG_HIGHLIGHT_NORMAL; + highlight->attributes = 0; + string_to_color(config_info, highlight, h_bit); + } + } + + h_bit = strtok(NULL, "&"); + } +} + +unsigned int +string_to_binding_mask(struct config_info *config_info, char *s) +{ + char *b_bit; + unsigned int mask = 0; + + b_bit = strtok(s, "&"); + while (b_bit != NULL) { + if (!strcasecmp(b_bit, "Button1")) + mask |= TAG_BINDING_BUTTON1; + else if (!strcasecmp(b_bit, "Button2")) + mask |= TAG_BINDING_BUTTON2; + else if (!strcasecmp(b_bit, "Button3")) + mask |= TAG_BINDING_BUTTON3; + else if (!strcasecmp(b_bit, "Shift")) + mask |= TAG_BINDING_SHIFT; + else if (!strcasecmp(b_bit, "Control")) + mask |= TAG_BINDING_CONTROL; + else if (!strcasecmp(b_bit, "Meta")) + mask |= TAG_BINDING_META; + else + configerror(config_info, "Unknown binding token"); + + b_bit = strtok(NULL, "&"); + } + + return mask; +} + +#endif /* USE_ACTIVE_TAGS */ diff --git a/src/activeconfig.h b/src/activeconfig.h new file mode 100644 index 0000000..f5bda86 --- /dev/null +++ b/src/activeconfig.h @@ -0,0 +1,106 @@ +/*--------------------------------*-C-*---------------------------------* + * File: activeconfig.h + * + * Copyright 1996,1997 Nat Friedman, Massachusetts Institute of Technology + * + * + * You can do what you like with this source code as long as + * you don't try to make money out of it and you include an + * unaltered copy of this message (including the copyright). + * + * The author accepts no responsibility for anything whatsoever, nor does he + * guarantee anything, nor are any guarantees, promises, or covenants implicit + * with the use of this software. + * + * For information regarding this particular module, please see + * README.ActiveTags. + * + *----------------------------------------------------------------------*/ + +#ifdef ACTIVE_TAGS_SPENCER_REGEXP +#include "regexp/regexp.h" +#else +#include +#endif + +#include "activetags.h" + +/* The default locations for the config file */ +#define TAG_CONFIG_USER_FILENAME ".active.tags" +#define TAG_CONFIG_SYSTEM_FILENAME "/etc/active.tags" + +/* Defaults */ +#define TAG_DEFAULT_SEARCH_LINES 1 +#define TAG_DEFAULT_BINDING_MASK TAG_BINDING_BUTTON3 +#define TAG_DEFAULT_HIGHLIGHT_BG TAG_HIGHLIGHT_NORMAL +#define TAG_DEFAULT_HIGHLIGHT_FG TAG_HIGHLIGHT_BLUE +#define TAG_DEFAULT_HIGHLIGHT_ATT 0 + +/* These are the config file tokens. */ +#define TAG_CONFIG_DEFAULT_BINDING "DefaultBinding" +#define TAG_CONFIG_DEFAULT_HIGHLIGHT "DefaultHighlight" +#define TAG_CONFIG_DEFAULT_SEARCH_LINES "DefaultSearchLines" +#define TAG_CONFIG_SEARCH_LINES "SearchLines" +#define TAG_CONFIG_NEW_TAG "{" +#define TAG_CONFIG_END_TAG "}" +#define TAG_CONFIG_OUTPUT "Output" +#define TAG_CONFIG_LATENT "Latent" +#define TAG_CONFIG_BINDING "Binding" +#define TAG_CONFIG_HIGHLIGHT "Highlight" +#define TAG_CONFIG_MODES "Modes" +#define TAG_CONFIG_REGEXP "Regexp" +#define TAG_CONFIG_ACTION "Action" +#define TAG_CONFIG_LOOPACTION "LoopAction" +#define TAG_CONFIG_CLUE "Clue" +#define TAG_CONFIG_LOAD "Load" +#define TAG_CONFIG_ENV "Env" + +/* Macros for parsing the config file */ +#define TAG_CONFIG(x) (!strncmp(line, (x), strlen(x))) + +/* The config_info structure holds all the information that each individual + configuration parsing function needs as it runs */ +struct config_info { + int line_num; + int default_binding; + tag_highlight_t default_highlight; + int default_search_lines; + int in_tag; + int curr_tag; + char filename[1024]; +}; + +/* Each dispatch table entry is of the following form */ +struct config_entry { + char * token; + int (*parser)(char *, struct config_info *); +}; + +/* Configuration dispatch function prototypes */ +int parse_config_default_binding(char *, struct config_info *); +int parse_config_default_highlight(char *, struct config_info *); +int parse_config_default_search_lines(char *, struct config_info *); +int parse_config_tag_begin(char *, struct config_info *); +int parse_config_tag_end(char *, struct config_info *); +int parse_config_tag_latent(char *, struct config_info *); +int parse_config_tag_binding(char *, struct config_info *); +int parse_config_tag_highlight(char *, struct config_info *); +int parse_config_tag_modes(char *, struct config_info *); +int parse_config_tag_regexp(char *, struct config_info *); +int parse_config_tag_action(char *, struct config_info *); +int parse_config_tag_search_lines(char *, struct config_info *); +int parse_config_tag_output(char *, struct config_info *); +int parse_config_tag_clue(char *, struct config_info *); +int parse_config_load(char * filename, struct config_info * config_info); +int parse_config_tag_env(char * envlist, struct config_info * config_info); + +/* Internal helper functin prototypes */ +void configerror(struct config_info * config_info, char * message); +void string_to_color(struct config_info * config_info, tag_highlight_t * + highlight, char * c); +void string_to_highlight(struct config_info * config_info, tag_highlight_t * + highlight, char * s); +unsigned int string_to_binding_mask(struct config_info * config_info, + char * s); +void set_config_defaults(struct config_info * config_info); +int parse_tag_file(const char * filename, struct config_info * config_info); diff --git a/src/activeeterm.c b/src/activeeterm.c new file mode 100644 index 0000000..3f3d775 --- /dev/null +++ b/src/activeeterm.c @@ -0,0 +1,390 @@ +/*--------------------------------*-C-*---------------------------------* + * File: activeeterm.c + * + * Copyright 1997 Nat Friedman, Massachusetts Institute of Technology + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + *----------------------------------------------------------------------*/ + +/* This file contains the glue functions to make active tags work in eterm. */ + +/* + In order to dingify a program, this plugin file must define the following + functions with the specified behavior. Note that functions can be defined + as macros just fine. + + The functions are broken up into two groups. The first group of functions + are the wrapper functions which get called by the main program. These + functions call the internal active tags functions. The second group of + functions are the internal functions which are called by the active + tags functions. + + WRAPPER FUNCTIONS + + int tag_click( ... ) + This should call tag_activate after it has properly assembled the + binding mask and determined the row and column properly. tag_click() + is called from inside the main program. + + void tag_pointer_new_position( ... ) + This should call show_tag after it has computed the row and column + properly and done whatever processing it needs to do. + + void tag_scroll( ... ) + void tag_init ( ... ) + void tag_sig_child ( ... ) + void tag_hide ( ... ) + + INTERNAL FUNCTIONS + + void get_tag_mode(char * mode) + This function stores a string containing the current mode in the + mode parameter. This can be very simple (for example + strcpy(mode, "browser") might be sufficient), or somewhat more complex + for those programs which can change modes, such as rxvt. + + int row_width(void) + returns the maximum width of each row. + + const char ** get_rows(void) + returns the comparison region. current_row() and current_col() should + be indexes into this region. + + void set_tag_highlight(int row, int col, tag_highlight_t highlight) + Highlights the specified character with the specified highlighting. + + tag_highlight_t get_tag_highlight(int row, int col) + Returns the current highlighting information for the specified + character. + */ + +static const char cvs_ident[] = "$Id$"; + +#include "feature.h" +#ifdef USE_ACTIVE_TAGS + +#include +#include +#include + +#include "activetags.h" +#include "activeeterm.h" +#include "mem.h" /* From libmej */ + +/* + WRAPPER FUNCTIONS + */ + +void +tag_pointer_new_position(int x, int y) +{ + int row, col; + + if (!active_tags_enabled) + return; + + col = Pixel2Col(x); + row = Pixel2Row(y); + +#ifdef ACTIVE_TAG_CLICK_CLUES + if (show_tag(row, col)) + set_click_clue_timer(); + else { + destroy_click_clue(); + unset_click_clue_timer(); + } +#else + show_tag(row, col); +#endif +} + +void +tag_scroll(int nlines, int row1, int row2) +{ + if (!active_tags_enabled) + return; + +#ifdef ACTIVE_TAG_CLICK_CLUES + if (tag_screen_scroll(nlines, row1, row2)) { + destroy_click_clue(); + unset_click_clue_timer(); + } +#else + (void) tag_screen_scroll(nlines, row1, row2); +#endif +} + +void +tag_init(void) +{ + if (!active_tags_enabled) + return; + + tag_env = "X"; + +#ifdef ACTIVE_TAG_CLICK_CLUES + init_click_clues(); +#endif + + initialize_tags(); +} + +#if 0 +void +#endif +inline void +tag_hide(void) +{ + if (!active_tags_enabled) + return; + + erase_tag_highlighting(); +} + +int +tag_click(int x, int y, unsigned int button, unsigned int keystate) +{ + int binding_mask; + int row, col; + int retval; + + if (!active_tags_enabled) + return 0; + +#ifdef ACTIVE_TAG_CLICK_CLUES + destroy_click_clue(); + unset_click_clue_timer(); +#endif + + /* Build the binding mask. Button3 == 3. We need it to be 4 + (100 binary) to fit in the binding mask properly. */ + if (button == Button3) + button = TAG_BINDING_BUTTON3; + + binding_mask = button; + + if (keystate & ShiftMask) + binding_mask |= TAG_BINDING_SHIFT; + if (keystate & ControlMask) + binding_mask |= TAG_BINDING_CONTROL; + if (keystate & Mod1Mask) + binding_mask |= TAG_BINDING_META; + + row = Pixel2Row(y); + col = Pixel2Col(x); + retval = tag_activate(row, col, binding_mask); + return retval; +} + +/* + INTERNAL FUNCTIONS + */ + +/* This function finds the current tag mode and stores it in the 'mode' + parameter. The current mode is equivalent to argv[0] of the program + currently controlling the eterm's terminal. */ +void +get_tag_mode(char *mode) +{ + char proc_name[1024]; + FILE *f; + pid_t pid; + + if ((pid = tcgetpgrp(cmd_fd)) == -1) { + fprintf(stderr, "Couldn't get tag mode!\n"); + strcpy(mode, ""); + return; + } + sprintf(proc_name, "/proc/%d/cmdline", pid); + if ((f = fopen(proc_name, "r")) == NULL) { + fprintf(stderr, "Couldn't open proc!\n"); + strcpy(mode, ""); + return; + } + fscanf(f, "%s", mode); + fclose(f); +} + +/* These were changed to macros and moved into activeeterm.h. -vendu */ + +#if 0 +int +row_width(void) +{ + return TermWin.ncol; +} + +int +tag_min_row(void) +{ + return 0; +} + +int +tag_max_row(void) +{ + return TermWin.nrow - 1; +} +#endif + +void +tag_get_row(int row_num, char **row) +{ +/* FIXME: I guess this works :) -vendu */ + *row = drawn_text[row_num]; +} + +int +tag_eterm_color(int tag_color) +{ + switch (tag_color) { + case TAG_HIGHLIGHT_BLACK: + return 2; + case TAG_HIGHLIGHT_WHITE: + return 1; + case TAG_HIGHLIGHT_RED: + return 3; + case TAG_HIGHLIGHT_GREEN: + return 4; + case TAG_HIGHLIGHT_YELLOW: + return 5; + case TAG_HIGHLIGHT_BLUE: + return 6; + case TAG_HIGHLIGHT_MAGENTA: + return 7; + case TAG_HIGHLIGHT_CYAN: + return 8; + default: + return -1; + } +} + +int +eterm_tag_color(int eterm_color) +{ + switch (eterm_color) { + case 0: + return TAG_HIGHLIGHT_NORMAL; + case 7: + return TAG_HIGHLIGHT_MAGENTA; + case 1: + return TAG_HIGHLIGHT_WHITE; + case 2: + return TAG_HIGHLIGHT_BLACK; + case 3: + return TAG_HIGHLIGHT_RED; + case 4: + return TAG_HIGHLIGHT_GREEN; + case 5: + return TAG_HIGHLIGHT_YELLOW; + case 6: + return TAG_HIGHLIGHT_BLUE; + case 8: + return TAG_HIGHLIGHT_CYAN; + default: + return TAG_HIGHLIGHT_NORMAL; + } +} + +void +set_tag_highlight(int row, int col, tag_highlight_t highlight) +{ + unsigned int rend_mask = 0; + unsigned int back; + unsigned int fore; + +/* rend_t ** rp = &(screen.rend[row + TermWin.saveLines - TermWin.view_start][col]); */ + + if (highlight.attributes & TAG_HIGHLIGHT_RVID) + rend_mask |= RS_RVid; + if (highlight.attributes & TAG_HIGHLIGHT_ULINE) + rend_mask |= RS_Uline; + if (highlight.attributes & TAG_HIGHLIGHT_BOLD) + rend_mask |= RS_Bold; + + if (highlight.fg_color == TAG_HIGHLIGHT_NORMAL) + fore = SET_FGCOLOR(0, fgColor); + else + fore = SET_FGCOLOR(0, tag_eterm_color(highlight.fg_color)); + + if (highlight.bg_color == TAG_HIGHLIGHT_NORMAL) + back = SET_BGCOLOR(0, bgColor); + else + back = SET_BGCOLOR(0, tag_eterm_color(highlight.bg_color)); + + screen.rend[row + TermWin.saveLines - TermWin.view_start][col] = + rend_mask | fore | back; +} + +void +get_tag_highlight(int row, int col, tag_highlight_t * highlight) +{ + unsigned int rend; + + rend = screen.rend[row + TermWin.saveLines - TermWin.view_start][col]; + + highlight->attributes = 0; + if (rend & RS_RVid) + highlight->attributes |= TAG_HIGHLIGHT_RVID; + if (rend & RS_Uline) + highlight->attributes |= TAG_HIGHLIGHT_ULINE; + if (rend & RS_Bold) + highlight->attributes |= TAG_HIGHLIGHT_BOLD; + if (rend & RS_Blink) + highlight->attributes |= TAG_HIGHLIGHT_BLINK; + + highlight->fg_color = eterm_tag_color(GET_FGCOLOR(rend)); + highlight->bg_color = eterm_tag_color(GET_BGCOLOR(rend)); +} + +/* Set the UID appropriately */ +int +set_tag_uid(void) +{ + return 1; +} + +/* Set stdout for loop actions */ +int +set_tag_stdout(void) +{ + if (close(1) < 0) { + perror("close"); + return 0; + } + if (dup(cmd_fd) < 0) { + perror("dup"); + return 0; + } + return 1; +} + +/* Set the PWD to the pwd of the process eterm is running */ +int +set_tag_pwd(void) +{ + char dir[1024]; + + sprintf(dir, "/proc/%d/cwd", cmd_pid); + if (chdir(dir) < 0) + return 0; + + return 1; +} + +#endif /* USE_ACTIVE_TAGS */ diff --git a/src/activeeterm.h b/src/activeeterm.h new file mode 100644 index 0000000..e01d23a --- /dev/null +++ b/src/activeeterm.h @@ -0,0 +1,48 @@ +/*--------------------------------*-C-*---------------------------------* + * File: activeeterm.h + * + * Copyright 1997 Nat Friedman, Massachusetts Institute of Technology + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + *----------------------------------------------------------------------*/ + +#ifndef _ACTIVEETERM_H +# define ACTIVEETERM_H + +# include "screen.h" +# include "command.h" +# include "main.h" /* for TermWin */ +/* #include "rxvtgrx.h" */ + +/* #define MAX_RXVT_ROWS 1024 */ + +int tag_click(int x, int y, unsigned int button, unsigned int keystate); +void tag_pointer_new_position(int x, int y); +void tag_init(void); + +extern int cmd_fd; +extern screen_t screen; + +extern text_t **drawn_text; +extern rend_t **drawn_rend; + +# define row_width() (TermWin.ncol) +# define tag_min_row() (0) +# define tag_max_row() (TermWin.nrow - 1) + +#endif /* ACTIVEETERM_H */ diff --git a/src/activetags.c b/src/activetags.c new file mode 100644 index 0000000..86ff516 --- /dev/null +++ b/src/activetags.c @@ -0,0 +1,524 @@ +/*--------------------------------*-C-*---------------------------------* + * File: activetags.c + * + * Copyright 1997 Nat Friedman, Massachusetts Institute of Technology + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + *----------------------------------------------------------------------*/ + +/* + This file contains all of the basic active tags functionality. These + are the generalized routines which can be plugged into just about anything. + If I've designed everything properly, which I believe I have, you should + not have to change anything in this file in order to plug active tags into + an application. + + See activeeterm.c for the routines which interface these functions with Eterm + */ + +static const char cvs_ident[] = "$Id$"; + +#include "feature.h" +#ifdef USE_ACTIVE_TAGS + +#include +#include +#include +#include +#include +#include + +#include "activetags.h" +#include "activeeterm.h" + +/* ============================ Global Variables =========================== */ + +/* This is for run-time enabling and disabling of tags. It is 1 if tags are + enabled at 0 otherwise. */ +int active_tags_enabled = 1; + +/* This is the global array of tag configurations. Each of the tags in the + configuration file corresponds to a tag in this global array. These are + allocated statically just to reduce the complexity of the code. Increase + MAX_TAGS in activetags.h if you run out. */ +struct active_tag tag[MAX_TAGS]; +int num_tags = 0; + +/* The tag environment (e.g. "X", "console", ... */ +char *tag_env; + +/* The data regarding the last tag highlighted on the screen. NB: this model + limits the number of highlighted tags on the screen to one. */ +int last_h_tag_index = -1, last_h_tag_begin_row = -1, last_h_tag_end_row = -1, last_h_tag_begin_col = -1, last_h_tag_end_col = -1; +tag_highlight_t old_highlighting[MAX_SEARCH_LINES][MAX_SEARCH_COLS]; + +char *tag_config_file = NULL; + +static char *thingy = "ActiveTags 1.0b4 -- Copyright 1997,1998 Nat Friedman -- DINGUS UBER ALLES"; + +/* ============================== Tag Routines ============================= */ + +/* This is the tag intialization routine. It needs to be called upon + startup. */ +void +initialize_tags(void) +{ + /* Parse the config file */ + parse_tag_config(tag_config_file); +} + +void +disable_tags(void) +{ + fprintf(stderr, "Active tags are disabled.\n"); + active_tags_enabled = 0; +} + +/* check_tag_mode returns true if the mode parameter is one of the modes + for which the tag indexed by tag_index is active. Otherwise, it returns + false. */ +int +check_tag_mode(int tag_index, char *mode) +{ + int i; + + /* If no modes are listed for a particular tag, that tag is always active. */ + if (tag[tag_index].num_modes == 0) + return 1; + + for (i = 0; i < tag[tag_index].num_modes; i++) + if (!strcmp(mode, tag[tag_index].mode[i])) + return 1; + + return 0; +} + +int +check_tag_env(int tag_index) +{ + int i; + + if (!tag[tag_index].num_envs) + return 1; + + for (i = 0; i < tag[tag_index].num_envs; i++) + if (!strcasecmp(tag_env, tag[tag_index].env[i])) + return 1; + + return 0; +} + +/* Check the position specified by (row,col) for a tag. If there is + a tag there, set tag_begin and tag_end to the proper offsets into + screen.text and screen.rend, and set tag_index to the index of the + tag that was identified. If no tag is found, return 0. Otherwise, + return 1. If binding_mask is set, then only search tags whose + binding mask matches the binding_mask passed to the function. + Tag searching begins at the specified index, tag_begin_index. */ +int +find_tag(int row, int col, int *tag_begin_row, int *tag_begin_col, + int *tag_end_row, int *tag_end_col, int *tag_index, + unsigned int binding_mask, int tag_begin_index) +{ + char *curr_row; + static char mode[1024]; + static int mode_check_count = 0; + char compare_region[MAX_SEARCH_CHARS]; + int compare_offset, compare_region_pointer_position; + int done; + unsigned int region_size; + unsigned int last_region_size = 0; + + int start_row, end_row, i, dest_offset; + + char *start_match_p, *end_match_p; + +#ifndef ACTIVE_TAGS_SPENCER_REGEXP + regmatch_t regmatch[5]; + +#endif + + D_TAGS(("==> find_tag(row=%d, col=%d, ..., binding=%d, begin=%d)\n", row, col, binding_mask, tag_begin_index)); + if (!mode_check_count) + get_tag_mode(mode); + + mode_check_count++; + if (mode_check_count == MAX_MODE_CHECK_COUNT) + mode_check_count = 0; + for (*tag_index = tag_begin_index; *tag_index < num_tags; (*tag_index)++) { + D_TAGS((" ==> tag: %d (sl=%d)\n", *tag_index, tag[*tag_index].search_lines)); + if (((binding_mask == 0) && (!tag[*tag_index].latent)) || + (binding_mask && (binding_mask == tag[*tag_index].binding_mask))) + if (check_tag_mode(*tag_index, mode) && (check_tag_env(*tag_index))) { + start_row = row - tag[*tag_index].search_lines / 2; + end_row = row + tag[*tag_index].search_lines / 2; + + if (start_row < tag_min_row()) + start_row = tag_min_row(); + + if (end_row > tag_max_row()) + end_row = tag_max_row(); + + compare_region_pointer_position = ((row - start_row) * row_width()) + + col; + + region_size = (row_width()) * (end_row - start_row + 1); + + if (region_size > MAX_SEARCH_CHARS) { + fprintf(stderr, "search region too large: reduce number of " + "search lines.\n"); + fprintf(stderr, "row_width: %d end_row: %d start_row: %d\n", + row_width(), end_row, start_row); + break; + } + if (region_size != last_region_size) { + D_TAGS((" ==> region_size == %d\tlast_region_size == %d\n", region_size, last_region_size)); + i = start_row; + dest_offset = 0; + while (i <= end_row) { + tag_get_row(i, &curr_row); + D_TAGS(("Memcpying row into place...\n")); + memcpy(compare_region + dest_offset, curr_row, row_width()); + D_TAGS(("Done\n")); + dest_offset += row_width(); + i++; + } + compare_region[dest_offset + 1] = '\0'; + } + last_region_size = region_size; + + + done = 0; + compare_offset = 0; + + while (!done) { +#ifdef ACTIVE_TAGS_SPENCER_REGEXP + if (regexec(tag[*tag_index].rx, compare_region + compare_offset)) +#else + if (!regexec(&tag[*tag_index].rx, compare_region + compare_offset, + 4, regmatch, REG_NOTBOL | REG_NOTEOL)) +#endif + + { +#ifdef ACTIVE_TAGS_SPENCER_REGEXP + start_match_p = tag[*tag_index].rx->startp[0]; + end_match_p = tag[*tag_index].rx->endp[0]; +#else + start_match_p = compare_region + compare_offset + + regmatch[0].rm_so; + end_match_p = compare_region + compare_offset + + regmatch[0].rm_eo; +#endif + + if ((start_match_p <= + (compare_region + compare_region_pointer_position)) && + (end_match_p > + (compare_region + compare_region_pointer_position))) { + *tag_begin_row = ((start_match_p - + compare_region) / row_width()) + + start_row; + *tag_begin_col = (start_match_p - + compare_region) - + ((start_match_p - compare_region) / + row_width()) * row_width(); + + *tag_end_row = ((end_match_p - + compare_region) / row_width()) + + start_row; + *tag_end_col = (end_match_p - + compare_region) - + ((end_match_p - compare_region) / + row_width()) * row_width(); + D_TAGS(("Found tag: begin_row: %d begin_col: %d\nend_row : %d end_col : %d\n", *tag_begin_row, *tag_begin_col, + *tag_end_row, *tag_end_col)); + return 1; + + } else + compare_offset = (end_match_p - + compare_region); + } else + done = 1; + } + } + } + + return 0; +} + +/* tag_scroll -- This is to notify the tag functionality that the screen + has scrolled nlines lines (positive means scrolled up, negative means + scrolled down) from start_row to end_row (inclusive) */ +int +tag_screen_scroll(int nlines, int start_row, int end_row) +{ + + D_TAGS(("tag_scroll(%d, %d, %d)\n", nlines, start_row, end_row)); + D_TAGS(("\tlast_brow: %d last_erow: %d\n", last_h_tag_begin_row, last_h_tag_end_row)); + if (!nlines) + return 0; + + if (last_h_tag_index == -1) + return 0; + + /* If the last highlighted tag is not part of the region that scrolled, + we don't need to do anything. */ + if (last_h_tag_begin_row > end_row) + return 0; + + if (last_h_tag_end_row < start_row) + return 0; + + /* Otherwise, update the position of the tag last highlighted */ + last_h_tag_begin_row += nlines; + last_h_tag_end_row += nlines; + + /* Erase the tag */ + (void) show_tag(last_h_tag_begin_row - nlines, last_h_tag_begin_col + 1); + return 1; +} + +/* This function restores the rendering information for the currently + highlighted tag to its status before the tag was highlighted. */ +void +erase_tag_highlighting(void) +{ + int row, col; + int final_highlight_col; + int start_highlight_col; + + if (last_h_tag_index != -1) { + for (row = last_h_tag_begin_row; row <= last_h_tag_end_row; row++) { + final_highlight_col = (row == last_h_tag_end_row) ? + last_h_tag_end_col : row_width(); + start_highlight_col = (row == last_h_tag_begin_row) ? + last_h_tag_begin_col : 0; + for (col = start_highlight_col; col < final_highlight_col; col++) { + set_tag_highlight(row, col, + old_highlighting[row - last_h_tag_begin_row][col]); + } + } + } + /* We don't need to keep erasing now that nothing is highlighted */ + last_h_tag_index = -1; +} + +/* Highlight a tag if one exists at the location specified in pixels. + If no tag exists there and a tag is currently highlighted, we need + to erase that tag's highlighting. */ +int +show_tag(int row, int col) +{ + unsigned int tag_begin_col, tag_end_col, tag_begin_row, tag_end_row, tag_index; + int final_highlight_col; + int start_highlight_col; + tag_highlight_t highlight; + + D_TAGS(("==> show_tag(%d,%d)\n", row, col)); + + /* If there's no tag there and a tag is currently highlighted, we need + to erase its highlighting. */ + if (!find_tag(row, col, &tag_begin_row, &tag_begin_col, &tag_end_row, + &tag_end_col, &tag_index, 0, 0)) { + D_TAGS((" ==> no tag, erasing highlighting and leaving.\n")); + /* Erase the old highlighting */ + tag_hide(); + + return 0; + } + /* If we've come this far, then we are on a tag, and it needs to be + highlighted. */ + + /* If we're on the same tag as last time, there's no need to do + anything. */ + if ((tag_index == last_h_tag_index) && + (tag_begin_row == last_h_tag_begin_row) && + (tag_end_row == last_h_tag_end_row) && + (tag_begin_col == last_h_tag_begin_col) && + (tag_end_col == last_h_tag_end_col)) + return 1; + + /* Erase the old highlighting */ + tag_hide(); + + /* Add the new highlighting */ + for (row = tag_begin_row; row <= tag_end_row; row++) { + final_highlight_col = (row == tag_end_row) ? tag_end_col : + row_width(); + start_highlight_col = (row == tag_begin_row) ? tag_begin_col : 0; + for (col = start_highlight_col; col < final_highlight_col; col++) { + get_tag_highlight(row, col, &highlight); + memcpy((void *) &old_highlighting[row - tag_begin_row][col], + (void *) &highlight, sizeof(tag_highlight_t)); + + set_tag_highlight(row, col, tag[tag_index].highlight); + } + } + + /* Store the old values to erase later */ + last_h_tag_index = tag_index; + last_h_tag_begin_row = tag_begin_row; + last_h_tag_end_row = tag_end_row; + last_h_tag_begin_col = tag_begin_col; + last_h_tag_end_col = tag_end_col; + + return 1; +} + +/* Check to see if there's a tag at the location specified by (x,y) (in + pixels). If so, execute the corresponding action. Return 0 if there's + no tag there, otherwise return 1. */ +int +tag_activate(int row, int col, unsigned int binding_mask) +{ + int tag_begin_row, tag_end_row, tag_index, tag_begin_col, tag_end_col; + + D_TAGS(("tag_activate(row==%d, col==%d, ...)\n", row, col)); + + /* If there is no tag to be activated here, return. */ + if (!find_tag(row, col, &tag_begin_row, &tag_begin_col, &tag_end_row, + &tag_end_col, &tag_index, binding_mask, 0)) + return 0; + + /* Otherwise, activate the tag. */ + execute_tag(tag_begin_row, tag_begin_col, tag_end_row, tag_end_col, + tag_index); + + return 1; +} + +/* Execute the tag specified by tag_index and contained between the + indices specified by tag_begin and tag_end. */ + +void +execute_tag(int tag_begin_row, int tag_begin_col, + int tag_end_row, int tag_end_col, int tag_index) +{ + char tagstr[MAX_SEARCH_CHARS]; + char cmd[MAX_TAG_COMMAND_LENGTH]; + char *p, *q; + pid_t pid; + int dest_offset; + int i, start_column, end_column; + char *curr_row; + + printf("==> Activating tag %d:\n ==> Action: [%s]\n Env: [%s] ==> Output: %s\n", + tag_index, tag[tag_index].action, tag_env, + (tag[tag_index].output_type == TAG_OUTPUT_NULL) ? "NULL" : + ((tag[tag_index].output_type == TAG_OUTPUT_POPUP) ? "POPUP" : + ((tag[tag_index].output_type == TAG_OUTPUT_LOOP) ? "LOOP" : + ((tag[tag_index].output_type == TAG_OUTPUT_REPL) ? "REPL" : + "UNKNOWN")))); + + /* If the tag's action is TAG_ACTION_RELOAD, then we simply + relaod the tag config file. */ + if (!strcmp(tag[tag_index].action, TAG_ACTION_RELOAD)) { + for (i = 0; i < num_tags; i++) +#ifdef ACTIVE_TAGS_SPENCER_REGEXP + regfree(tag[i].rx); +#else + regfree(&tag[i].rx); +#endif + num_tags = 0; + parse_tag_config(tag_config_file); + return; + } + if (!strcmp(tag[tag_index].action, TAG_ACTION_DISABLE)) { + disable_tags(); + return; + } + /* For debugging */ + if (!strcmp(tag[tag_index].action, TAG_ACTION_MODE)) { + char mode[1024]; + + get_tag_mode(mode); + fprintf(stderr, "Mode: %s\n", mode); + return; + } + /* Fork off a separate process to execute the new tag. */ + pid = fork(); + + if (pid == 0) { /* child */ + + D_TAGS(("Child\n")); + + i = tag_begin_row; + dest_offset = 0; + + while (i <= tag_end_row) { + start_column = i == tag_begin_row ? tag_begin_col : 0; + end_column = i == tag_end_row ? tag_end_col : row_width(); + D_TAGS(("row: %d Start col: %d end_col: %d\n", i, start_column, end_column)); + tag_get_row(i, &curr_row); + memcpy(tagstr + dest_offset, + curr_row + start_column, + end_column - start_column); + + dest_offset += end_column - start_column; + i++; + } + + tagstr[dest_offset] = '\0'; + D_TAGS(("\t==> tag string: {%s}\n", tagstr)); + /* Initialize the command string */ + *cmd = '\0'; + + /* Build the command string from the action string by replacing + all occurences of ${} in the action string with the tag string. */ + q = p = tag[tag_index].action; + while ((p = strstr(q, "${}")) != NULL) { + *p = '\0'; + strcat(cmd, q); + + strcat(cmd, tagstr); + + /* Step over the remaining characters of the ${} */ + q = p + 3; + } + + strcat(cmd + strlen(cmd), q); + + if (!set_tag_pwd()) + fprintf(stderr, "Active Tags: couldn't set the pwd!\n"); + + + /* Set the UID appropriately so we don't act as the wrong user */ + if (!set_tag_uid()) { + fprintf(stderr, "Active Tags: tag action: Couldn't set the uid!\n"); + exit(1); + } + /* For a loop action, we connect stdout on the tag process to stdin on + the terminal's executing process */ + if (tag[tag_index].output_type == TAG_OUTPUT_LOOP) + /* I wonder if screwing around with Eterm's stdin is a good idea >:) + * -vendu + */ + if (!set_tag_stdout()) { + fprintf(stderr, "Active Tags: tag action: Couldn't set stdout for " + "a loop action!\n"); + exit(1); + } + system(cmd); +#if 0 + exit(1); /* This might be a bad idea :) Makes Eterm exit, at + * least if run from another Eterm. -vendu */ +#endif + return; + } +} + +#endif /* USE_ACTIVE_TAGS */ diff --git a/src/activetags.h b/src/activetags.h new file mode 100644 index 0000000..20152e0 --- /dev/null +++ b/src/activetags.h @@ -0,0 +1,182 @@ +/*--------------------------------*-C-*---------------------------------* + * File: activetags.h + * + * Copyright 1996,1997 Nat Friedman, Massachusetts Institute of Technology + * + * + * You can do what you like with this source code as long as + * you don't try to make money out of it and you include an + * unaltered copy of this message (including the copyright). + * + * The author accepts no responsibility for anything whatsoever, nor does he + * guarantee anything, nor are any guarantees, promises, or covenants implicit + * with the use of this software. + * + * For information regarding this particular module, please see + * README.ActiveTags. + * + *----------------------------------------------------------------------*/ + +#ifndef _ACTIVE_TAGS_H +#define _ACTIVE_TAGS_H + +#ifndef ACTIVE_TAGS +#define ACTIVE_TAGS +#endif + +#ifdef ACTIVE_TAGS_SPENCER_REGEXP +#include "regexp/regexp.h" +#else +#include +#include +#endif + +#include + +#define TAG_ACTION_RELOAD "*reload*" +#define TAG_ACTION_DISABLE "*disable*" + +/* Debugging actions */ +#define TAG_ACTION_MODE "*mode*" + + +#define TAG_DRAG_THRESHHOLD 500 + +/* Maximums */ +#define MAX_TAGS 128 +#define MAX_SEARCH_CHARS 32767 +#define MAX_SEARCH_LINES 25 +#define MAX_SEARCH_COLS 300 +#define MAX_SCREEN_ROWS 128 +#define MAX_TAG_MODES 32 +#define MAX_TAG_MODE_LEN 32 +#define MAX_TAG_COMMAND_LENGTH 2048 +#define MAX_REGEXP_LEN 1024 +#define MAX_ACTION_LEN 1024 +#define MAX_CLUE_LENGTH 1024 +#define MAX_MODE_CHECK_COUNT 25 +#define MAX_TAG_ENVS 8 +#define MAX_TAG_ENV_LEN 16 + +/* Output Types */ +#define TAG_OUTPUT_POPUP 1 +#define TAG_OUTPUT_LOOP 2 +#define TAG_OUTPUT_NULL 3 +#define TAG_OUTPUT_REPL 4 + +/* Binding fields */ +#define TAG_BINDING_BUTTON1 (1<<0) +#define TAG_BINDING_BUTTON2 (1<<1) +#define TAG_BINDING_BUTTON3 (1<<2) +#define TAG_BINDING_SHIFT (1<<3) +#define TAG_BINDING_CONTROL (1<<4) +#define TAG_BINDING_META (1<<5) + +/* Highlight fields */ +#define TAG_HIGHLIGHT_RVID (1L<<0) +#define TAG_HIGHLIGHT_BOLD (1L<<1) +#define TAG_HIGHLIGHT_ULINE (1L<<2) +#define TAG_HIGHLIGHT_BLINK (1L<<3) + +#define TAG_HIGHLIGHT_BLACK (1L<<0) +#define TAG_HIGHLIGHT_WHITE (1L<<1) +#define TAG_HIGHLIGHT_RED (1L<<2) +#define TAG_HIGHLIGHT_GREEN (1L<<3) +#define TAG_HIGHLIGHT_YELLOW (1L<<4) +#define TAG_HIGHLIGHT_BLUE (1L<<5) +#define TAG_HIGHLIGHT_MAGENTA (1L<<6) +#define TAG_HIGHLIGHT_CYAN (1L<<7) +#define TAG_HIGHLIGHT_NORMAL -1 + +typedef struct tag_highlight { + /* Underline, Reverse Video, Bold */ + int attributes; + + /* Highlighting colors */ + int fg_color; + int bg_color; + +} tag_highlight_t; + +struct active_tag { + + /* rx is the compiled regular expression for the tag */ +#ifdef ACTIVE_TAGS_SPENCER_REGEXP + regexp * rx; +#else + regex_t rx; +#endif + + /* The action is a program to be executed. The string ${} in the action + will be replaced with the tag. */ + char action[MAX_ACTION_LEN]; + + tag_highlight_t highlight; + + /* The button/key combo that activates this tag. */ + unsigned int binding_mask; + + /* Number of lines to search for this tag */ + int search_lines; + + char mode[MAX_TAG_MODES][MAX_TAG_MODE_LEN]; + int num_modes; + + char env[MAX_TAG_ENVS][MAX_TAG_ENV_LEN]; + int num_envs; + + /* See TAG_OUTPUT_* */ + int output_type; + + /* Whether or not the tag is latent. */ + int latent; + + char clue[MAX_CLUE_LENGTH]; +}; + + +/* Template prototypes */ +void get_tag_mode(char * mode); +/* int row_width(void); */ +void tag_get_row(int row_num, char ** row); +/* int tag_min_row(void); */ +/* int tag_max_row(void); */ +void set_tag_highlight(int row, int col, tag_highlight_t highlight); +void get_tag_highlight(int row, int col, tag_highlight_t * highlight); +int set_tag_stdout(void); +int set_tag_pwd(void); +int set_tag_uid(void); + +/* Prototypes */ +void parse_tag_config(char * tag_config_file); +int find_tag(int row, int col, int * tag_begin_row, int * tag_begin_col, + int * tag_end_row, int * tag_end_col, + int * tag_index, unsigned int binding_mask, int tag_begin_index); +int show_tag(int x, int y); +int tag_activate(int row, int col, unsigned int binding_mask); +void execute_tag(int tag_begin_row, int tag_begin_col, int tag_end_row, int tag_end_col, int tag_index); +void initialize_tags(void); +int tag_screen_scroll(int nlines, int start_row, int end_row); +void reap_tag_process(pid_t pid); +void erase_tag_highlighting(void); +void disable_tags(void); +void tag_hide(void); + +/* Externs */ +extern int active_tags_enabled; +extern struct active_tag tag[MAX_TAGS]; +extern int num_tags; +extern int last_h_tag_begin_row; +extern int last_h_tag_begin_col; +extern int last_h_tag_index; +extern char * tag_env; + +#endif /* _ACTIVE_TAGS_H */ + + + + + + + + diff --git a/src/command.c b/src/command.c new file mode 100644 index 0000000..c01d776 --- /dev/null +++ b/src/command.c @@ -0,0 +1,7123 @@ +/*--------------------------------*-C-*---------------------------------* + * File: command.c + */ +/* notes: */ +/*----------------------------------------------------------------------* + * Copyright 1992 John Bovey, University of Kent at Canterbury. + * + * You can do what you like with this source code as long as + * you don't try to make money out of it and you include an + * unaltered copy of this message (including the copyright). + * + * This module has been very heavily modified by R. Nation + * + * No additional restrictions are applied + * + * Additional modification by Garrett D'Amore to + * allow vt100 printing. No additional restrictions are applied. + * + * Integrated modifications by Steven Hirsch to + * properly support X11 mouse report mode and support for DEC + * "private mode" save/restore functions. + * + * Integrated key-related changes by Jakub Jelinek + * to handle Shift+function keys properly. + * Should be used with enclosed termcap / terminfo database. + * + * Extensive modifications by mj olesen + * No additional restrictions. + * + * Further modification and cleanups for Solaris 2.x and Linux 1.2.x + * by Raul Garcia Garcia . No additional restrictions. + * + * As usual, the author accepts no responsibility for anything, nor does + * he guarantee anything whatsoever. + *----------------------------------------------------------------------*/ + +static const char cvs_ident[] = "$Id$"; + +/* includes: */ +#include "feature.h" +#include "config.h" + +/* System Headers */ +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#if !defined(SIGSYS) +# if defined(SIGUNUSED) +# define SIGSYS SIGUNUSED +# else +# define SIGSYS ((int) 0) +# endif +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_FCNTL_H +# include +#endif +#ifdef HAVE_SYS_IOCTL_H +# include +#endif +#include +#include + +/* X11 Headers */ +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef OFFIX_DND +# define DndFile 2 +# define DndDir 5 +# define DndLink 7 +#endif +#include +#ifndef NO_XLOCALE +# if (XtVersion < 11005) +# define NO_XLOCALE +# include +# else +# include +# endif +#endif /* NO_XLOCALE */ +#ifdef USE_GETGRNAME +# include +#endif +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#if defined (__svr4__) +# include /* for struct rlimit */ +# include /* for I_PUSH */ +# ifdef HAVE_SYS_STRTIO_H +# include +# endif +# ifdef HAVE_BSDTTY_H +# include +# endif +# define _NEW_TTY_CTRL /* to get proper defines in */ +#endif +#ifdef HAVE_SYS_SELECT_H +# include +#endif +#ifdef HAVE_TERMIOS_H +# include +#else +# include +#endif +#if defined(__sun) && defined(__SVR4) +# include +#endif +#include +#include +#if defined(linux) +# include /* For N_TTY_BUF_SIZE. */ +#endif +#if defined(linux) +# include /* For strsep(). -vendu */ +#endif + +/* Eterm-specific Headers */ +#ifdef USE_ACTIVE_TAGS +# include "activetags.h" +# include "activeeterm.h" +#endif +#include "command.h" +#include "main.h" +#include "../libmej/debug.h" +#include "debug.h" +#include "../libmej/mem.h" +#include "../libmej/strings.h" +#include "string.h" +#include "graphics.h" +#include "grkelot.h" +#include "scrollbar.h" +#include "menubar.h" +#include "screen.h" +#include "options.h" +#include "pixmap.h" +#ifdef USE_POSIX_THREADS +# include "threads.h" +#endif +#ifdef PROFILE +# include "profile.h" +#endif + +#ifdef PIXMAP_SCROLLBAR +extern pixmap_t sbPixmap; + +#endif +#ifdef PIXMAP_MENUBAR +extern pixmap_t mbPixmap; + +#endif + + +/* terminal mode defines: */ +/* ways to deal with getting/setting termios structure */ +#ifdef HAVE_TERMIOS_H +typedef struct termios ttymode_t; + +# ifdef TCSANOW /* POSIX */ +# define GET_TERMIOS(fd,tios) tcgetattr (fd, tios) +# define SET_TERMIOS(fd,tios) do {\ +cfsetospeed (tios, BAUDRATE);\ +cfsetispeed (tios, BAUDRATE);\ +tcsetattr (fd, TCSANOW, tios);\ +} while (0) +# else +# ifdef TIOCSETA +# define GET_TERMIOS(fd,tios) ioctl (fd, TIOCGETA, tios) +# define SET_TERMIOS(fd,tios) do {\ +tios->c_cflag |= BAUDRATE;\ +ioctl (fd, TIOCSETA, tios);\ +} while (0) +# else +# define GET_TERMIOS(fd,tios) ioctl (fd, TCGETS, tios) +# define SET_TERMIOS(fd,tios) do {\ +tios->c_cflag |= BAUDRATE;\ +ioctl (fd, TCSETS, tios);\ +} while (0) +# endif +# endif +# define SET_TTYMODE(fd,tios) SET_TERMIOS (fd, tios) +#else +/* sgtty interface */ +typedef struct { + struct sgttyb sg; + struct tchars tc; + struct ltchars lc; + int line; + int local; +} ttymode_t; + +# define SET_TTYMODE(fd,tt) \ +do { \ +tt->sg.sg_ispeed = tt->sg.sg_ospeed = BAUDRATE;\ +ioctl (fd, TIOCSETP, &(tt->sg));\ +ioctl (fd, TIOCSETC, &(tt->tc));\ +ioctl (fd, TIOCSLTC, &(tt->lc));\ +ioctl (fd, TIOCSETD, &(tt->line));\ +ioctl (fd, TIOCLSET, &(tt->local));\ +} while (0) +#endif /* HAVE_TERMIOS_H */ + +/* use the fastest baud-rate */ +#ifdef B38400 +# define BAUDRATE B38400 +#else +# ifdef B19200 +# define BAUDRATE B19200 +# else +# define BAUDRATE B9600 +# endif +#endif + +/* Disable special character functions */ +#ifdef _POSIX_VDISABLE +# define VDISABLE _POSIX_VDISABLE +#else +# define VDISABLE 255 +#endif + +/*----------------------------------------------------------------------* + * system default characters if defined and reasonable + */ +#ifndef CINTR +# define CINTR '\003' /* ^C */ +#endif +#ifndef CQUIT +# define CQUIT '\034' /* ^\ */ +#endif +#ifndef CERASE +# ifdef linux +# define CERASE '\177' /* ^? */ +# else +# define CERASE '\010' /* ^H */ +# endif +#endif +#ifndef CKILL +# define CKILL '\025' /* ^U */ +#endif +#ifndef CEOF +# define CEOF '\004' /* ^D */ +#endif +#ifndef CSTART +# define CSTART '\021' /* ^Q */ +#endif +#ifndef CSTOP +# define CSTOP '\023' /* ^S */ +#endif +#ifndef CSUSP +# define CSUSP '\032' /* ^Z */ +#endif +#ifndef CDSUSP +# define CDSUSP '\031' /* ^Y */ +#endif +#ifndef CRPRNT +# define CRPRNT '\022' /* ^R */ +#endif +#ifndef CFLUSH +# define CFLUSH '\017' /* ^O */ +#endif +#ifndef CWERASE +# define CWERASE '\027' /* ^W */ +#endif +#ifndef CLNEXT +# define CLNEXT '\026' /* ^V */ +#endif + +#ifndef VDISCRD +# ifdef VDISCARD +# define VDISCRD VDISCARD +# endif +#endif + +#ifndef VWERSE +# ifdef VWERASE +# define VWERSE VWERASE +# endif +#endif + +/* defines: */ + +#define KBUFSZ 8 /* size of keyboard mapping buffer */ +#define STRING_MAX 512 /* max string size for process_xterm_seq() */ +#define ESC_ARGS 32 /* max # of args for esc sequences */ + +/* a large REFRESH_PERIOD causes problems with `cat' */ + +#ifndef REFRESH_PERIOD +# define REFRESH_PERIOD 3 +#endif + +#ifndef MULTICLICK_TIME +# define MULTICLICK_TIME 500 +#endif +#ifndef SCROLLBAR_INITIAL_DELAY +# define SCROLLBAR_INITIAL_DELAY 40 +#endif +#ifndef SCROLLBAR_CONTINUOUS_DELAY +# define SCROLLBAR_CONTINUOUS_DELAY 2 +#endif + +/* time factor to slow down a `jumpy' mouse */ +#define MOUSE_THRESHOLD 50 +#define CONSOLE "/dev/console" /* console device */ + +/* + * key-strings: if only these keys were standardized + */ +#ifdef LINUX_KEYS +# define KS_HOME "\033[1~" /* Home == Find */ +# define KS_END "\033[4~" /* End == Select */ +#else +# define KS_HOME "\033[7~" /* Home */ +# define KS_END "\033[8~" /* End */ +#endif + +/* and this one too! */ +#ifdef NO_DELETE_KEY +# undef KS_DELETE /* use X server definition */ +#else +# ifndef KS_DELETE +# define KS_DELETE "\033[3~" /* Delete = Execute */ +# endif +#endif + +/* + * ESC-Z processing: + * + * By stealing a sequence to which other xterms respond, and sending the + * same number of characters, but having a distinguishable sequence, + * we can avoid having a timeout (when not under an Eterm) for every login + * shell to auto-set its DISPLAY. + * + * This particular sequence is even explicitly stated as obsolete since + * about 1985, so only very old software is likely to be confused, a + * confusion which can likely be remedied through termcap or TERM. Frankly, + * I doubt anyone will even notice. We provide a #ifdef just in case they + * don't care about auto-display setting. Just in case the ancient + * software in question is broken enough to be case insensitive to the 'c' + * character in the answerback string, we make the distinguishing + * characteristic be capitalization of that character. The length of the + * two strings should be the same so that identical read(2) calls may be + * used. + */ +#define VT100_ANS "\033[?1;2c" /* vt100 answerback */ +#ifndef ESCZ_ANSWER +# define ESCZ_ANSWER VT100_ANS /* obsolete ANSI ESC[c */ +#endif + +/* Global attributes */ +extern XWindowAttributes attr; +extern XSetWindowAttributes Attributes; +extern char *orig_argv0; + +#ifdef PIXMAP_SUPPORT +extern short bg_needs_update; + +#endif + +/* extern functions referenced */ +extern char *ptsname(); + +#ifdef DISPLAY_IS_IP +extern char *network_display(const char *display); + +#endif + +extern void get_initial_options(int, char **); +extern void menubar_read(const char *filename); + +#ifdef USE_POSIX_THREADS +extern static void **retval; +extern static int join_value; +extern static pthread_t main_loop_thr; +extern static pthread_attr_t main_loop_attr; + +# ifdef MUTEX_SYNCH +extern pthread_mutex_t mutex; + +# endif +#endif + +#ifdef PIXMAP_SUPPORT +extern void render_pixmap(Window win, imlib_t image, pixmap_t pmap, + int which, renderop_t renderop); + +# ifdef BACKING_STORE +extern const char *rs_saveUnder; + +# endif + +extern char *rs_noCursor; + +# ifdef USE_IMLIB +extern ImlibData *imlib_id; + +# endif +#endif + +/* extern variables referenced */ +extern int my_ruid, my_rgid, my_euid, my_egid; + +#ifdef PIXMAP_OFFSET +extern unsigned int rs_shadePct; +extern unsigned long rs_tintMask; + +#endif + +#ifdef PIXMAP_OFFSET +extern Pixmap desktop_pixmap, viewport_pixmap; + +#endif + +/* extern variables declared here */ +extern TermWin_t TermWin; +extern Display *Xdisplay; /* display */ + +extern char *rs_color[NRS_COLORS]; +extern Pixel PixColors[NRS_COLORS + NSHADOWCOLORS]; + +extern unsigned long Options; + +extern const char *display_name; +extern char *rs_name; /* client instance (resource name) */ + +#ifndef NO_BOLDFONT +extern const char *rs_boldFont; + +#endif +extern const char *rs_font[NFONTS]; + +#ifdef KANJI +extern const char *rs_kfont[NFONTS]; + +#endif + +#ifdef PRINTPIPE +extern char *rs_print_pipe; + +#endif + +extern char *rs_cutchars; + +/* local variables */ +extern Cursor TermWin_cursor; /* cursor for vt window */ +extern unsigned int colorfgbg; +extern menuBar_t menuBar; +unsigned char keypress_exit = 0; + +extern XSizeHints szHint; + +extern char *def_colorName[]; + +#ifdef KANJI +/* Kanji font names, roman fonts sized to match */ +extern const char *def_kfontName[]; + +#endif /* KANJI */ +extern const char *def_fontName[]; + +/* extern functions referenced */ +#ifdef PIXMAP_SUPPORT +/* the originally loaded pixmap and its scaling */ +extern pixmap_t bgPixmap; +extern void set_bgPixmap(const char * /* file */ ); + +# ifdef USE_IMLIB +extern imlib_t imlib_bg; + +# endif +# ifdef PIXMAP_SCROLLBAR +extern pixmap_t sbPixmap; +extern pixmap_t upPixmap, up_clkPixmap; +extern pixmap_t dnPixmap, dn_clkPixmap; +extern pixmap_t saPixmap, sa_clkPixmap; + +# ifdef USE_IMLIB +extern imlib_t imlib_sb, imlib_sa, imlib_saclk; + +# endif +# endif +# ifdef PIXMAP_MENUBAR +extern pixmap_t mbPixmap, mb_selPixmap; + +# ifdef USE_IMLIB +extern imlib_t imlib_mb, imlib_ms; + +# endif +# endif + +extern int scale_pixmap(const char *geom, pixmap_t * pmap); + +#endif /* PIXMAP_SUPPORT */ + +/* have we changed the font? Needed to avoid race conditions + * while window resizing */ +extern int font_change_count; + +static void resize(void); + +/* extern functions referenced */ +#ifdef UTMP_SUPPORT +extern void cleanutent(void); +extern void makeutent(const char *, const char *); + +#else +# define cleanutent() ((void)(0)) +# define makeutent(pty, hostname) ((void)(0)) +#endif + +/* extern variables referenced */ +extern int my_ruid, my_rgid, my_euid, my_egid; + +/* extern variables declared here */ + +/* local variables */ +/* static unsigned char segv=0; */ +char initial_dir[PATH_MAX + 1]; +static char *ptydev = NULL, *ttydev = NULL; /* pty/tty name */ + +#ifdef USE_ACTIVE_TAGS +int cmd_fd = -1; /* file descriptor connected to the command */ +pid_t cmd_pid = -1; /* process id if child */ + +#else +static int cmd_fd = -1; /* file descriptor connected to the command */ +static pid_t cmd_pid = -1; /* process id if child */ + +#endif +static int Xfd = -1; /* file descriptor of X server connection */ +static unsigned int num_fds = 0; /* number of file descriptors being used */ +static struct stat ttyfd_stat; /* original status of the tty we will use */ + +#ifdef SCROLLBAR_BUTTON_CONTINUAL_SCROLLING +static int scroll_arrow_delay; + +#endif + +#ifdef META8_OPTION +static unsigned char meta_char = 033; /* Alt-key prefix */ + +#endif + +unsigned long PrivateModes = PrivMode_Default; +static unsigned long SavedModes = PrivMode_Default; + +#ifndef USE_POSIX_THREADS +static int refresh_count = 0, refresh_limit = 1; + +#else +int refresh_count = 0, refresh_limit = 1; + +#endif + +/* Why? -vendu */ +/* static int refresh_type = SLOW_REFRESH; */ +static int refresh_type = FAST_REFRESH; + +static Atom wmDeleteWindow; + +/* OffiX Dnd (drag 'n' drop) support */ +#ifdef OFFIX_DND +static Atom DndProtocol, DndSelection; + +#endif /* OFFIX_DND */ + +#ifndef NO_XLOCALE +static char *rs_inputMethod = ""; /* XtNinputMethod */ +static char *rs_preeditType = NULL; /* XtNpreeditType */ +static XIC Input_Context; /* input context */ + +#endif /* NO_XLOCALE */ + +/* command input buffering */ + +#if defined(linux) && defined(N_TTY_BUF_SIZE) +# define CMD_BUF_SIZE N_TTY_BUF_SIZE +#else +# ifndef CMD_BUF_SIZE +# define CMD_BUF_SIZE 4096 +# endif +#endif + +#ifndef USE_POSIX_THREADS +static unsigned char cmdbuf_base[CMD_BUF_SIZE], *cmdbuf_ptr, *cmdbuf_endp; + +#else +unsigned char cmdbuf_base[CMD_BUF_SIZE], *cmdbuf_ptr, *cmdbuf_endp; + +#endif + +/* local functions referenced */ +void privileges(int mode); + +RETSIGTYPE Child_signal(int); +RETSIGTYPE Exit_signal(int); +int get_pty(void); +int get_tty(void); +int run_command(char * /* argv */ []); +unsigned char cmd_getc(void); + +#if 0 +void lookup_key(XEvent * /* ev */ ); + +#endif +inline void lookup_key(XEvent * /* ev */ ); +void process_x_event(XEvent * /* ev */ ); + +/*static void process_string (int); */ +#ifdef PRINTPIPE +void process_print_pipe(void); + +#endif +void process_escape_seq(void); +void process_csi_seq(void); +void process_xterm_seq(void); +void process_window_mode(unsigned int, int[]); +void process_terminal_mode(int, int, unsigned int, int[]); +void process_sgr_mode(unsigned int, int[]); +void process_graphics(void); + +void tt_winsize(int); + +#ifndef NO_XLOCALE +void init_xlocale(void); + +#else +# define init_xlocale() ((void)0) +#endif + +/*for Big Paste Handling */ +static int v_doPending(void); +static void v_writeBig(int, char *, int); + +/*----------------------------------------------------------------------*/ + +/* Substitutes for missing system functions */ +#ifndef _POSIX_VERSION +# if defined (__svr4__) +int +getdtablesize(void) +{ + struct rlimit rlim; + + getrlimit(RLIMIT_NOFILE, &rlim); + return rlim.rlim_cur; +} +# endif +# endif + +/* Take care of suid/sgid super-user (root) privileges */ +void +privileges(int mode) +{ + +#ifdef __CYGWIN32__ + return; +#endif + + switch (mode) { + case IGNORE: + /* Revoke suid/sgid privs and return to normal uid/gid -- mej */ + D_UTMP(("[%ld]: Before privileges(REVERT): [ %ld, %ld ] [ %ld, %ld ]\n", + getpid(), getuid(), getgid(), geteuid(), getegid())); + +#ifdef HAVE_SETRESGID + setresgid(my_rgid, my_rgid, my_egid); +#elif defined(HAVE_SAVED_UIDS) + setregid(my_rgid, my_rgid); +#else + setregid(my_egid, -1); + setregid(-1, my_rgid); +#endif + +#ifdef HAVE_SETRESUID + setresuid(my_ruid, my_ruid, my_euid); +#elif defined(HAVE_SAVED_UIDS) + setreuid(my_ruid, my_ruid); +#else + setreuid(my_euid, -1); + setreuid(-1, my_ruid); +#endif + + D_UTMP(("[%ld]: After privileges(REVERT): [ %ld, %ld ] [ %ld, %ld ]\n", + getpid(), getuid(), getgid(), geteuid(), getegid())); + break; + + case SAVE: + break; + + case RESTORE: + D_UTMP(("[%ld]: Before privileges(INVOKE): [ %ld, %ld ] [ %ld, %ld ]\n", + getpid(), getuid(), getgid(), geteuid(), getegid())); + +#ifdef HAVE_SETRESUID + setresuid(my_ruid, my_euid, my_euid); +#elif defined(HAVE_SAVED_UIDS) + setreuid(my_ruid, my_euid); +#else + setreuid(-1, my_euid); + setreuid(my_ruid, -1); +#endif + +#ifdef HAVE_SETRESGID + setresgid(my_rgid, my_egid, my_egid); +#elif defined(HAVE_SAVED_UIDS) + setregid(my_rgid, my_egid); +#else + setregid(-1, my_egid); + setregid(my_rgid, -1); +#endif + + D_UTMP(("[%ld]: After privileges(INVOKE): [ %ld, %ld ] [ %ld, %ld ]\n", + getpid(), getuid(), getgid(), geteuid(), getegid())); + break; + } +} + +char * +sig_to_str(int sig) +{ + + /* NOTE: This can't be done with a switch because of possible conflicting + * conflicting signal types. -vendu + */ + +#ifdef SIGHUP + if (sig == SIGHUP) { + return ("SIGHUP"); + } +#endif + +#ifdef SIGINT + if (sig == SIGINT) { + return ("SIGINT"); + } +#endif + +#ifdef SIGQUIT + if (sig == SIGQUIT) { + return ("SIGQUIT"); + } +#endif + +#ifdef SIGILL + if (sig == SIGILL) { + return ("SIGILL"); + } +#endif + +#ifdef SIGTRAP + if (sig == SIGTRAP) { + return ("SIGTRAP"); + } +#endif + +#ifdef SIGABRT + if (sig == SIGABRT) { + return ("SIGABRT"); + } +#endif + +#ifdef SIGIOT + if (sig == SIGIOT) { + return ("SIGIOT"); + } +#endif + +#ifdef SIGEMT + if (sig == SIGEMT) { + return ("SIGEMT"); + } +#endif + +#ifdef SIGFPE + if (sig == SIGFPE) { + return ("SIGFPE"); + } +#endif + +#ifdef SIGKILL + if (sig == SIGKILL) { + return ("SIGKILL"); + } +#endif + +#ifdef SIGBUS + if (sig == SIGBUS) { + return ("SIGBUS"); + } +#endif + +#ifdef SIGSEGV + if (sig == SIGSEGV) { + return ("SIGSEGV"); + } +#endif + +#ifdef SIGSYS + if (sig == SIGSYS) { + return ("SIGSYS"); + } +#endif + +#ifdef SIGPIPE + if (sig == SIGPIPE) { + return ("SIGPIPE"); + } +#endif + +#ifdef SIGALRM + if (sig == SIGALRM) { + return ("SIGALRM"); + } +#endif + +#ifdef SIGTERM + if (sig == SIGTERM) { + return ("SIGTERM"); + } +#endif + +#ifdef SIGUSR1 + if (sig == SIGUSR1) { + return ("SIGUSR1"); + } +#endif + +#ifdef SIGUSR2 + if (sig == SIGUSR2) { + return ("SIGUSR2"); + } +#endif + +#ifdef SIGCHLD + if (sig == SIGCHLD) { + return ("SIGCHLD"); + } +#endif + +#ifdef SIGCLD + if (sig == SIGCLD) { + return ("SIGCLD"); + } +#endif + +#ifdef SIGPWR + if (sig == SIGPWR) { + return ("SIGPWR"); + } +#endif + +#ifdef SIGVTALRM + if (sig == SIGVTALRM) { + return ("SIGVTALRM"); + } +#endif + +#ifdef SIGPROF + if (sig == SIGPROF) { + return ("SIGPROF"); + } +#endif + +#ifdef SIGIO + if (sig == SIGIO) { + return ("SIGIO"); + } +#endif + +#ifdef SIGPOLL + if (sig == SIGPOLL) { + return ("SIGPOLL"); + } +#endif + +#ifdef SIGWINCH + if (sig == SIGWINCH) { + return ("SIGWINCH"); + } +#endif + +#ifdef SIGWINDOW + if (sig == SIGWINDOW) { + return ("SIGWINDOW"); + } +#endif + +#ifdef SIGSTOP + if (sig == SIGSTOP) { + return ("SIGSTOP"); + } +#endif + +#ifdef SIGTSTP + if (sig == SIGTSTP) { + return ("SIGTSTP"); + } +#endif + +#ifdef SIGCONT + if (sig == SIGCONT) { + return ("SIGCONT"); + } +#endif + +#ifdef SIGTTIN + if (sig == SIGTTIN) { + return ("SIGTTIN"); + } +#endif + +#ifdef SIGTTOU + if (sig == SIGTTOU) { + return ("SIGTTOU"); + } +#endif + +#ifdef SIGURG + if (sig == SIGURG) { + return ("SIGURG"); + } +#endif + +#ifdef SIGLOST + if (sig == SIGLOST) { + return ("SIGLOST"); + } +#endif + +#ifdef SIGRESERVE + if (sig == SIGRESERVE) { + return ("SIGRESERVE"); + } +#endif + +#ifdef SIGDIL + if (sig == SIGDIL) { + return ("SIGDIL"); + } +#endif + +#ifdef SIGXCPU + if (sig == SIGXCPU) { + return ("SIGXCPU"); + } +#endif + +#ifdef SIGXFSZ + if (sig == SIGXFSZ) { + return ("SIGXFSZ"); + } +#endif + return ("Unknown signal"); +} + +const char * +event_type_to_name(int type) +{ + + if (type == KeyPress) { + return "KeyPress"; + } + if (type == KeyRelease) { + return "KeyRelease"; + } + if (type == ButtonPress) { + return "ButtonPress"; + } + if (type == ButtonRelease) { + return "ButtonRelease"; + } + if (type == MotionNotify) { + return "MotionNotify"; + } + if (type == EnterNotify) { + return "EnterNotify"; + } + if (type == LeaveNotify) { + return "LeaveNotify"; + } + if (type == FocusIn) { + return "FocusIn"; + } + if (type == FocusOut) { + return "FocusOut"; + } + if (type == KeymapNotify) { + return "KeymapNotify"; + } + if (type == Expose) { + return "Expose"; + } + if (type == GraphicsExpose) { + return "GraphicsExpose"; + } + if (type == NoExpose) { + return "NoExpose"; + } + if (type == VisibilityNotify) { + return "VisibilityNotify"; + } + if (type == CreateNotify) { + return "CreateNotify"; + } + if (type == DestroyNotify) { + return "DestroyNotify"; + } + if (type == UnmapNotify) { + return "UnmapNotify"; + } + if (type == MapNotify) { + return "MapNotify"; + } + if (type == MapRequest) { + return "MapRequest"; + } + if (type == ReparentNotify) { + return "ReparentNotify"; + } + if (type == ConfigureNotify) { + return "ConfigureNotify"; + } + if (type == ConfigureRequest) { + return "ConfigureRequest"; + } + if (type == GravityNotify) { + return "GravityNotify"; + } + if (type == ResizeRequest) { + return "ResizeRequest"; + } + if (type == CirculateNotify) { + return "CirculateNotify"; + } + if (type == CirculateRequest) { + return "CirculateRequest"; + } + if (type == PropertyNotify) { + return "PropertyNotify"; + } + if (type == SelectionClear) { + return "SelectionClear"; + } + if (type == SelectionRequest) { + return "SelectionRequest"; + } + if (type == SelectionNotify) { + return "SelectionNotify"; + } + if (type == ColormapNotify) { + return "ColormapNotify"; + } + if (type == ClientMessage) { + return "ClientMessage"; + } + if (type == MappingNotify) { + return "MappingNotify"; + } + return "Bad Event!"; +} + +const char * +request_code_to_name(int code) +{ + + if (code == X_CreateWindow) { + return "XCreateWindow"; + } + if (code == X_ChangeWindowAttributes) { + return "XChangeWindowAttributes"; + } + if (code == X_GetWindowAttributes) { + return "XGetWindowAttributes"; + } + if (code == X_DestroyWindow) { + return "XDestroyWindow"; + } + if (code == X_DestroySubwindows) { + return "XDestroySubwindows"; + } + if (code == X_ChangeSaveSet) { + return "XChangeSaveSet"; + } + if (code == X_ReparentWindow) { + return "XReparentWindow"; + } + if (code == X_MapWindow) { + return "XMapWindow"; + } + if (code == X_MapSubwindows) { + return "XMapSubwindows"; + } + if (code == X_UnmapWindow) { + return "XUnmapWindow"; + } + if (code == X_UnmapSubwindows) { + return "XUnmapSubwindows"; + } + if (code == X_ConfigureWindow) { + return "XConfigureWindow"; + } + if (code == X_CirculateWindow) { + return "XCirculateWindow"; + } + if (code == X_GetGeometry) { + return "XGetGeometry"; + } + if (code == X_QueryTree) { + return "XQueryTree"; + } + if (code == X_InternAtom) { + return "XInternAtom"; + } + if (code == X_GetAtomName) { + return "XGetAtomName"; + } + if (code == X_ChangeProperty) { + return "XChangeProperty"; + } + if (code == X_DeleteProperty) { + return "XDeleteProperty"; + } + if (code == X_GetProperty) { + return "XGetProperty"; + } + if (code == X_ListProperties) { + return "XListProperties"; + } + if (code == X_SetSelectionOwner) { + return "XSetSelectionOwner"; + } + if (code == X_GetSelectionOwner) { + return "XGetSelectionOwner"; + } + if (code == X_ConvertSelection) { + return "XConvertSelection"; + } + if (code == X_SendEvent) { + return "XSendEvent"; + } + if (code == X_GrabPointer) { + return "XGrabPointer"; + } + if (code == X_UngrabPointer) { + return "XUngrabPointer"; + } + if (code == X_GrabButton) { + return "XGrabButton"; + } + if (code == X_UngrabButton) { + return "XUngrabButton"; + } + if (code == X_ChangeActivePointerGrab) { + return "XChangeActivePointerGrab"; + } + if (code == X_GrabKeyboard) { + return "XGrabKeyboard"; + } + if (code == X_UngrabKeyboard) { + return "XUngrabKeyboard"; + } + if (code == X_GrabKey) { + return "XGrabKey"; + } + if (code == X_UngrabKey) { + return "XUngrabKey"; + } + if (code == X_AllowEvents) { + return "XAllowEvents"; + } + if (code == X_GrabServer) { + return "XGrabServer"; + } + if (code == X_UngrabServer) { + return "XUngrabServer"; + } + if (code == X_QueryPointer) { + return "XQueryPointer"; + } + if (code == X_GetMotionEvents) { + return "XGetMotionEvents"; + } + if (code == X_TranslateCoords) { + return "XTranslateCoords"; + } + if (code == X_WarpPointer) { + return "XWarpPointer"; + } + if (code == X_SetInputFocus) { + return "XSetInputFocus"; + } + if (code == X_GetInputFocus) { + return "XGetInputFocus"; + } + if (code == X_QueryKeymap) { + return "XQueryKeymap"; + } + if (code == X_OpenFont) { + return "XOpenFont"; + } + if (code == X_CloseFont) { + return "XCloseFont"; + } + if (code == X_QueryFont) { + return "XQueryFont"; + } + if (code == X_QueryTextExtents) { + return "XQueryTextExtents"; + } + if (code == X_ListFonts) { + return "XListFonts"; + } + if (code == X_ListFontsWithInfo) { + return "XListFontsWithInfo"; + } + if (code == X_SetFontPath) { + return "XSetFontPath"; + } + if (code == X_GetFontPath) { + return "XGetFontPath"; + } + if (code == X_CreatePixmap) { + return "XCreatePixmap"; + } + if (code == X_FreePixmap) { + return "XFreePixmap"; + } + if (code == X_CreateGC) { + return "XCreateGC"; + } + if (code == X_ChangeGC) { + return "XChangeGC"; + } + if (code == X_CopyGC) { + return "XCopyGC"; + } + if (code == X_SetDashes) { + return "XSetDashes"; + } + if (code == X_SetClipRectangles) { + return "XSetClipRectangles"; + } + if (code == X_FreeGC) { + return "XFreeGC"; + } + if (code == X_ClearArea) { + return "XClearArea"; + } + if (code == X_CopyArea) { + return "XCopyArea"; + } + if (code == X_CopyPlane) { + return "XCopyPlane"; + } + if (code == X_PolyPoint) { + return "XPolyPoint"; + } + if (code == X_PolyLine) { + return "XPolyLine"; + } + if (code == X_PolySegment) { + return "XPolySegment"; + } + if (code == X_PolyRectangle) { + return "XPolyRectangle"; + } + if (code == X_PolyArc) { + return "XPolyArc"; + } + if (code == X_FillPoly) { + return "XFillPoly"; + } + if (code == X_PolyFillRectangle) { + return "XPolyFillRectangle"; + } + if (code == X_PolyFillArc) { + return "XPolyFillArc"; + } + if (code == X_PutImage) { + return "XPutImage"; + } + if (code == X_GetImage) { + return "XGetImage"; + } + if (code == X_PolyText8) { + return "XPolyText8"; + } + if (code == X_PolyText16) { + return "XPolyText16"; + } + if (code == X_ImageText8) { + return "XImageText8"; + } + if (code == X_ImageText16) { + return "XImageText16"; + } + if (code == X_CreateColormap) { + return "XCreateColormap"; + } + if (code == X_FreeColormap) { + return "XFreeColormap"; + } + if (code == X_CopyColormapAndFree) { + return "XCopyColormapAndFree"; + } + if (code == X_InstallColormap) { + return "XInstallColormap"; + } + if (code == X_UninstallColormap) { + return "XUninstallColormap"; + } + if (code == X_ListInstalledColormaps) { + return "XListInstalledColormaps"; + } + if (code == X_AllocColor) { + return "XAllocColor"; + } + if (code == X_AllocNamedColor) { + return "XAllocNamedColor"; + } + if (code == X_AllocColorCells) { + return "XAllocColorCells"; + } + if (code == X_AllocColorPlanes) { + return "XAllocColorPlanes"; + } + if (code == X_FreeColors) { + return "XFreeColors"; + } + if (code == X_StoreColors) { + return "XStoreColors"; + } + if (code == X_StoreNamedColor) { + return "XStoreNamedColor"; + } + if (code == X_QueryColors) { + return "XQueryColors"; + } + if (code == X_LookupColor) { + return "XLookupColor"; + } + if (code == X_CreateCursor) { + return "XCreateCursor"; + } + if (code == X_CreateGlyphCursor) { + return "XCreateGlyphCursor"; + } + if (code == X_FreeCursor) { + return "XFreeCursor"; + } + if (code == X_RecolorCursor) { + return "XRecolorCursor"; + } + if (code == X_QueryBestSize) { + return "XQueryBestSize"; + } + if (code == X_QueryExtension) { + return "XQueryExtension"; + } + if (code == X_ListExtensions) { + return "XListExtensions"; + } + if (code == X_ChangeKeyboardMapping) { + return "XChangeKeyboardMapping"; + } + if (code == X_GetKeyboardMapping) { + return "XGetKeyboardMapping"; + } + if (code == X_ChangeKeyboardControl) { + return "XChangeKeyboardControl"; + } + if (code == X_GetKeyboardControl) { + return "XGetKeyboardControl"; + } + if (code == X_Bell) { + return "XBell"; + } + if (code == X_ChangePointerControl) { + return "XChangePointerControl"; + } + if (code == X_GetPointerControl) { + return "XGetPointerControl"; + } + if (code == X_SetScreenSaver) { + return "XSetScreenSaver"; + } + if (code == X_GetScreenSaver) { + return "XGetScreenSaver"; + } + if (code == X_ChangeHosts) { + return "XChangeHosts"; + } + if (code == X_ListHosts) { + return "XListHosts"; + } + if (code == X_SetAccessControl) { + return "XSetAccessControl"; + } + if (code == X_SetCloseDownMode) { + return "XSetCloseDownMode"; + } + if (code == X_KillClient) { + return "XKillClient"; + } + if (code == X_RotateProperties) { + return "XRotateProperties"; + } + if (code == X_ForceScreenSaver) { + return "XForceScreenSaver"; + } + if (code == X_SetPointerMapping) { + return "XSetPointerMapping"; + } + if (code == X_GetPointerMapping) { + return "XGetPointerMapping"; + } + if (code == X_SetModifierMapping) { + return "XSetModifierMapping"; + } + if (code == X_GetModifierMapping) { + return "XGetModifierMapping"; + } + if (code == X_NoOperation) { + return "XNoOperation"; + } + return "Unknown"; +} + +/* Try to get a stack trace when we croak */ +#ifdef HAVE_U_STACK_TRACE +extern void U_STACK_TRACE(void); + +#endif + +void +dump_stack_trace(void) +{ + + char cmd[256]; + +#ifdef NO_STACK_TRACE + return; +#endif + + print_error("Attempting to dump a stack trace....\n"); + signal(SIGTSTP, exit); /* Don't block on tty output, just die */ + +#ifdef HAVE_U_STACK_TRACE + U_STACK_TRACE(); + return; +#elif defined(GDB) + snprintf(cmd, sizeof(cmd), "/bin/echo backtrace | " GDB " " APL_NAME " %d", getpid()); +#elif defined(PSTACK) + snprintf(cmd, sizeof(cmd), PSTACK " %d", getpid()); +#elif defined(DBX) +# ifdef _AIX + snprintf(cmd, sizeof(cmd), "/bin/echo 'where\ndetach' | " DBX " -a %d", getpid()); +# elif defined(__sgi) + snprintf(cmd, sizeof(cmd), "/bin/echo 'where\ndetach' | " DBX " -p %d", getpid()); +# else + snprintf(cmd, sizeof(cmd), "/bin/echo 'where\ndetach' | " DBX " %s %d", orig_argv0, getpid()); +# endif +#else + print_error("Your system does not support any of the methods Eterm uses. Exiting.\n"); + return; +#endif + system(cmd); +} + +/* signal handling, exit handler */ +/* + * Catch a SIGCHLD signal and exit if the direct child has died + */ +RETSIGTYPE +Child_signal(int sig) +{ + + int pid, save_errno = errno; + + D_CMD(("Received signal %s (%d)\n", sig_to_str(sig), sig)); + + do { + errno = 0; + } while ((-1 == (pid = waitpid(-1, NULL, WNOHANG))) && + (errno == EINTR)); + + D_CMD(("pid == %d, cmd_pid == %d\n", pid, cmd_pid)); + /* If the child that exited is the command we spawned, or if the + child exited before fork() returned in the parent, it must be + our immediate child that exited. We exit gracefully. */ + if (pid == cmd_pid || cmd_pid == -1) { + if (Options & Opt_pause) { + const char *message = "\r\nPress any key to exit " APL_NAME "...."; + + scr_refresh(SMOOTH_REFRESH); + scr_add_lines(message, 1, strlen(message)); + scr_refresh(SMOOTH_REFRESH); + keypress_exit = 1; + return; + } + exit(EXIT_SUCCESS); + } + errno = save_errno; + + D_CMD(("Child_signal: installing signal handler\n")); + signal(SIGCHLD, Child_signal); + +#ifdef NEED_EXPLICIT_RETURN + D_CMD(("FUN FUN FUN. Child_signal returned 0 :)\n")); + return ((RETSIGTYPE) 0); +#endif +} + +/* Handles signals usually sent by a user, like HUP, TERM, INT. */ +RETSIGTYPE +Exit_signal(int sig) +{ + + print_error("Received terminal signal %s (%d)", sig_to_str(sig), sig); + signal(sig, SIG_DFL); + +#ifdef UTMP_SUPPORT + privileges(INVOKE); + cleanutent(); + privileges(REVERT); +#endif + + /* No! This causes unhandled signal propogation! -- mej */ + /* kill(getpid(), sig); */ + + D_CMD(("Exit_signal(): exit(%s)\n", sig_to_str(sig))); + exit(sig); +} + +/* Handles abnormal termination signals -- mej */ +static RETSIGTYPE +SegvHandler(int sig) +{ + + print_error("Received terminal signal %s (%d)", sig_to_str(sig), sig); + signal(sig, SIG_DFL); /* Let the OS handle recursive seg faults */ + + /* Lock down security so we don't write any core files as root. */ + privileges(REVERT); + umask(077); + + /* Make an attempt to dump a stack trace */ + dump_stack_trace(); + + /* Exit */ + exit(sig); +} + +/* + * Exit gracefully, clearing the utmp entry and restoring tty attributes + * TODO: Also free up X resources, etc., if possible + */ +void +clean_exit(void) +{ + scr_release(); + privileges(INVOKE); + +#ifndef __CYGWIN32__ + if (ttydev) { + D_CMD(("Restoring \"%s\" to mode %03o, uid %d, gid %d\n", ttydev, ttyfd_stat.st_mode, + ttyfd_stat.st_uid, ttyfd_stat.st_gid)); + if (chmod(ttydev, ttyfd_stat.st_mode) != 0) { + D_UTMP(("chmod(\"%s\", %03o) failed: %s\n", ttydev, ttyfd_stat.st_mode, strerror(errno))); + } + if (chown(ttydev, ttyfd_stat.st_uid, ttyfd_stat.st_gid) != 0) { + D_UTMP(("chown(\"%s\", %d, %d) failed: %s\n", ttydev, ttyfd_stat.st_uid, ttyfd_stat.st_gid, strerror(errno))); + } + } +#endif /* __CYGWIN32__ */ + +#ifdef UTMP_SUPPORT + cleanutent(); +#endif + privileges(REVERT); +#ifdef USE_POSIX_THREADS + /* Get rid of threads if there are any running. Doesn't work yet. */ +# if 0 + D_THREADS(("pthread_kill_other_threads_np();\n")); + pthread_kill_other_threads_np(); + D_THREADS(("pthread_exit();\n")); +# endif +#endif + + /* Work around a nasty Solaris X bug. If we're not unmapped in + 3 seconds, it ain't gonna happen. Die anyway. -- mej */ +#ifdef HAVE__EXIT + signal(SIGALRM, _exit); +#else + signal(SIGALRM, abort); +#endif + alarm(3); + + /* Close the display connection to the X server. Unmap the windows + * first. + */ + D_X11(("XUnmapWindow(Xdisplay, TermWin.parent);\n")); + XUnmapWindow(Xdisplay, TermWin.parent); + D_X11(("XSync(Xdisplay, TRUE) - discarding events\n")); + /* XSync discards all events in the event queue. */ + XSync(Xdisplay, TRUE); + D_X11(("XCloseDisplay(Xdisplay);\n")); + XCloseDisplay(Xdisplay); +} +#if (MENUBAR_MAX) +inline void +map_menuBar(int map) +{ + + if (delay_menu_drawing) { + delay_menu_drawing++; + } else if (menubar_mapping(map)) { + resize(); + } + PrivMode(map, PrivMode_menuBar); +} +#endif /* MENUBAR_MAX */ + +inline void +map_scrollBar(int map) +{ + + if (scrollbar_mapping(map)) { + scr_touch(); + resize(); + } + PrivMode(map, PrivMode_scrollBar); +} + + +/* Returns true if running under E, false otherwise */ +inline unsigned char +check_for_enlightenment(void) +{ + static char have_e = -1; + + if (have_e == -1) { + if (XInternAtom(Xdisplay, "ENLIGHTENMENT_COMMS", True) != None) { + D_X11(("Enlightenment detected.\n")); + have_e = 1; + } else { + D_X11(("Enlightenment not detected.\n")); + have_e = 0; + } + } + return (have_e); +} + +/* Acquire a pseudo-teletype from the system. */ +/* + * On failure, returns -1. + * On success, returns the file descriptor. + * + * If successful, ttydev and ptydev point to the names of the + * master and slave parts + */ + +#ifdef __sgi +inline int +sgi_get_pty(void) +{ + + int fd = -1; + + ptydev = ttydev = _getpty(&fd, O_RDWR | O_NDELAY, 0622, 0); + return (ptydev == NULL ? -1 : fd); + +} +#endif + +#ifdef _AIX +inline int +aix_get_pty(void) +{ + + int fd = -1; + + if ((fd = open("/dev/ptc", O_RDWR)) < 0) + return (-1); + else + ptydev = ttydev = ttyname(fd); + return (fd); +} +#endif + +#ifdef ALL_NUMERIC_PTYS +inline int +sco_get_pty(void) +{ + + static char pty_name[] = "/dev/ptyp??\0\0\0"; + static char tty_name[] = "/dev/ttyp??\0\0\0"; + int idx; + int fd = -1; + + ptydev = pty_name; + ttydev = tty_name; + + for (idx = 0; idx < 256; idx++) { + + sprintf(ptydev, "%s%d", "/dev/ptyp", idx); + sprintf(ttydev, "%s%d", "/dev/ttyp", idx); + + if (access(ttydev, F_OK) < 0) { + idx = 256; + break; + } + if ((fd = open(ptydev, O_RDWR)) >= 0) { + if (access(ttydev, R_OK | W_OK) == 0) + return (fd); + close(fd); + } + } + return (-1); +} +#endif + +#if defined (__svr4__) || defined(__CYGWIN32__) || ((__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)) +inline int +svr_get_pty(void) +{ + + int fd = -1; + + /* open the STREAMS, clone device /dev/ptmx (master pty) */ + if ((fd = open("/dev/ptmx", O_RDWR)) < 0) { + return (-1); + } else { + if (grantpt(fd) != 0) { + print_error("grantpt(%d) failed: %s\n", fd, strerror(errno)); + return (-1); + } else if (unlockpt(fd) != 0) { + print_error("unlockpt(%d) failed: %s\n", fd, strerror(errno)); + return (-1); + } else { + ptydev = ttydev = ptsname(fd); + if (ttydev == NULL) { + print_error("ptsname(%d) failed: %s\n", fd, strerror(errno)); + return (-1); + } + } + } + return (fd); +} +#endif + +#define PTYCHAR1 "pqrstuvwxyz" +#define PTYCHAR2 "0123456789abcdefghijklmnopqrstuvwxyz" + +inline int +gen_get_pty(void) +{ + + static char pty_name[] = "/dev/pty??"; + static char tty_name[] = "/dev/tty??"; + int len = sizeof(tty_name); + char *c1, *c2; + int fd = -1; + + ptydev = pty_name; + ttydev = tty_name; + + for (c1 = PTYCHAR1; *c1; c1++) { + ptydev[len - 3] = ttydev[len - 3] = *c1; + for (c2 = PTYCHAR2; *c2; c2++) { + ptydev[len - 2] = ttydev[len - 2] = *c2; + if ((fd = open(ptydev, O_RDWR)) >= 0) { + if (access(ttydev, R_OK | W_OK) == 0) + return (fd); + close(fd); + } + } + } + return (-1); +} + +int +get_pty(void) +{ + + int fd = -1; + +#if defined(__sgi) + fd = sgi_get_pty(); +#elif defined(_AIX) + fd = aix_get_pty(); +#elif defined(__svr4__) || defined(__CYGWIN32__) + fd = svr_get_pty(); +#elif ((__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)) + fd = svr_get_pty(); +#elif defined(ALL_NUMERIC_PTYS) /* SCO OSr5 */ + fd = sco_get_pty(); +#endif + + /* Fall back on this method */ + if (fd == -1) { + fd = gen_get_pty(); + } + if (fd != -1) { + fcntl(fd, F_SETFL, O_NDELAY); + return (fd); + } else { + print_error("Can't open pseudo-tty -- %s", strerror(errno)); + return (-1); + } +} + +/* establish a controlling teletype for new session */ +/* + * On some systems this can be done with ioctl() but on others we + * need to re-open the slave tty. + */ +int +get_tty(void) +{ + int fd; + pid_t pid; + + /* + * setsid() [or setpgrp] must be before open of the terminal, + * otherwise there is no controlling terminal (Solaris 2.4, HP-UX 9) + */ +#ifndef ultrix +# ifdef NO_SETSID + pid = setpgrp(0, 0); +# else + pid = setsid(); +# endif + if (pid < 0) { + D_TTYMODE(("%s: setsid() failed: %s, PID == %d\n", rs_name, strerror(errno), pid)); + } +#endif /* ultrix */ + + privileges(INVOKE); + if (ttydev == NULL) { + print_error("Slave tty device name is NULL. Failed to open slave pty.\n"); + exit(EXIT_FAILURE); + } else if ((fd = open(ttydev, O_RDWR)) < 0) { + print_error("Can't open slave tty %s -- %s", ttydev, strerror(errno)); + exit(EXIT_FAILURE); + } else { + D_TTY(("Opened slave tty %s\n", ttydev)); + privileges(REVERT); + } + +#if defined (__svr4__) + /* + * Push STREAMS modules: + * ptem: pseudo-terminal hardware emulation module. + * ldterm: standard terminal line discipline. + * ttcompat: V7, 4BSD and XENIX STREAMS compatibility module. + */ + ioctl(fd, I_PUSH, "ptem"); + ioctl(fd, I_PUSH, "ldterm"); + ioctl(fd, I_PUSH, "ttcompat"); +#else /* __svr4__ */ + { + /* change ownership of tty to real uid and real group */ + unsigned int mode = 0620; + gid_t gid = my_rgid; + +# ifdef USE_GETGRNAME + { + struct group *gr = getgrnam(TTY_GRP_NAME); + + if (gr) { + /* change ownership of tty to real uid, "tty" gid */ + gid = gr->gr_gid; + mode = 0620; + } + } +# endif /* USE_GETGRNAME */ + + privileges(INVOKE); +# ifndef __CYGWIN32__ + fchown(fd, my_ruid, gid); /* fail silently */ + fchmod(fd, mode); +# endif + privileges(REVERT); + } +#endif /* __svr4__ */ + + /* + * Close all file descriptors. If only stdin/out/err are closed, + * child processes remain alive upon deletion of the window. + */ + { + int i; + + for (i = 0; i < num_fds; i++) { + if (i != fd) + close(i); + } + } + + /* Reopen stdin, stdout and stderr over the tty file descriptor */ + dup(fd); /* 0: stdin */ + dup(fd); /* 1: stdout */ + dup(fd); /* 2: stderr */ + + if (fd > 2) + close(fd); + + privileges(INVOKE); + +#ifdef ultrix + if ((fd = open("/dev/tty", O_RDONLY)) >= 0) { + ioctl(fd, TIOCNOTTY, 0); + close(fd); + } else { +# ifdef NO_SETSID + pid = setpgrp(0, 0); +# else + pid = setsid(); +# endif + if (pid < 0) { + D_TTYMODE(("%s: setsid() failed: %s, PID == %d\n", rs_name, strerror(errno), pid)); + } + } + + /* no error, we could run with no tty to begin with */ +#else /* ultrix */ + +# ifdef TIOCSCTTY + ioctl(0, TIOCSCTTY, 0); +# endif + + /* set process group */ +# if defined (_POSIX_VERSION) || defined (__svr4__) + tcsetpgrp(0, pid); +# elif defined (TIOCSPGRP) + ioctl(0, TIOCSPGRP, &pid); +# endif + + /* svr4 problems: reports no tty, no job control */ + /* # if !defined (__svr4__) && defined (TIOCSPGRP) */ + + close(open(ttydev, O_RDWR, 0)); + /* # endif */ +#endif /* ultrix */ + + privileges(REVERT); + + return (fd); +} + +/* debug_ttymode() */ +#if DEBUG >= DEBUG_TTYMODE && defined(HAVE_TERMIOS_H) + + /* cpp token stringize doesn't work on all machines */ +# define SHOW_TTY_FLAG(flag,name) do { \ + if ((ttymode->c_iflag) & (flag)) { \ + fprintf(stderr, "+%s ", name); \ + } else { \ + fprintf(stderr, "-%s ", name); \ + } \ + } while (0) +# define SHOW_CONT_CHAR(entry, name) fprintf(stderr, "%s=%#3o ", name, ttymode->c_cc[entry]) +static void +debug_ttymode(ttymode_t * ttymode) +{ + + /* c_iflag bits */ + fprintf(stderr, "Input flags: "); + SHOW_TTY_FLAG(IGNBRK, "IGNBRK"); + SHOW_TTY_FLAG(BRKINT, "BRKINT"); + SHOW_TTY_FLAG(IGNPAR, "IGNPAR"); + SHOW_TTY_FLAG(PARMRK, "PARMRK"); + SHOW_TTY_FLAG(INPCK, "INPCK"); + SHOW_TTY_FLAG(ISTRIP, "ISTRIP"); + SHOW_TTY_FLAG(INLCR, "INLCR"); + SHOW_TTY_FLAG(IGNCR, "IGNCR"); + SHOW_TTY_FLAG(ICRNL, "ICRNL"); + SHOW_TTY_FLAG(IXON, "IXON"); + SHOW_TTY_FLAG(IXOFF, "IXOFF"); +# ifdef IUCLC + SHOW_TTY_FLAG(IUCLC, "IUCLC"); +# endif +# ifdef IXANY + SHOW_TTY_FLAG(IXANY, "IXANY"); +# endif +# ifdef IMAXBEL + SHOW_TTY_FLAG(IMAXBEL, "IMAXBEL"); +# endif + fprintf(stderr, "\n"); + + fprintf(stderr, "Control character mappings: "); + SHOW_CONT_CHAR(VINTR, "VINTR"); + SHOW_CONT_CHAR(VQUIT, "VQUIT"); + SHOW_CONT_CHAR(VERASE, "VERASE"); + SHOW_CONT_CHAR(VKILL, "VKILL"); + SHOW_CONT_CHAR(VEOF, "VEOF"); + SHOW_CONT_CHAR(VEOL, "VEOL"); +# ifdef VEOL2 + SHOW_CONT_CHAR(VEOL2, "VEOL2"); +# endif +# ifdef VSWTC + SHOW_CONT_CHAR(VSWTC, "VSWTC"); +# endif +# ifdef VSWTCH + SHOW_CONT_CHAR(VSWTCH, "VSWTCH"); +# endif + SHOW_CONT_CHAR(VSTART, "VSTART"); + SHOW_CONT_CHAR(VSTOP, "VSTOP"); + SHOW_CONT_CHAR(VSUSP, "VSUSP"); +# ifdef VDSUSP + SHOW_CONT_CHAR(VDSUSP, "VDSUSP"); +# endif +# ifdef VREPRINT + SHOW_CONT_CHAR(VREPRINT, "VREPRINT"); +# endif +# ifdef VDISCRD + SHOW_CONT_CHAR(VDISCRD, "VDISCRD"); +# endif +# ifdef VWERSE + SHOW_CONT_CHAR(VWERSE, "VWERSE"); +# endif +# ifdef VLNEXT + SHOW_CONT_CHAR(VLNEXT, "VLNEXT"); +# endif + fprintf(stderr, "\n\n"); +} + +# undef SHOW_TTY_FLAG +# undef SHOW_CONT_CHAR +#endif /* DEBUG_TTYMODE */ + +/* get_ttymode() */ +static void +get_ttymode(ttymode_t * tio) +{ +#ifdef HAVE_TERMIOS_H + /* + * standard System V termios interface + */ + if (GET_TERMIOS(0, tio) < 0) { + /* return error - use system defaults */ + tio->c_cc[VINTR] = CINTR; + tio->c_cc[VQUIT] = CQUIT; + tio->c_cc[VERASE] = CERASE; + tio->c_cc[VKILL] = CKILL; + tio->c_cc[VSTART] = CSTART; + tio->c_cc[VSTOP] = CSTOP; + tio->c_cc[VSUSP] = CSUSP; +# ifdef VDSUSP + tio->c_cc[VDSUSP] = CDSUSP; +# endif +# ifdef VREPRINT + tio->c_cc[VREPRINT] = CRPRNT; +# endif +# ifdef VDISCRD + tio->c_cc[VDISCRD] = CFLUSH; +# endif +# ifdef VWERSE + tio->c_cc[VWERSE] = CWERASE; +# endif +# ifdef VLNEXT + tio->c_cc[VLNEXT] = CLNEXT; +# endif + } + tio->c_cc[VEOF] = CEOF; + tio->c_cc[VEOL] = VDISABLE; +# ifdef VEOL2 + tio->c_cc[VEOL2] = VDISABLE; +# endif +# ifdef VSWTC + tio->c_cc[VSWTC] = VDISABLE; +# endif +# ifdef VSWTCH + tio->c_cc[VSWTCH] = VDISABLE; +# endif +# if VMIN != VEOF + tio->c_cc[VMIN] = 1; +# endif +# if VTIME != VEOL + tio->c_cc[VTIME] = 0; +# endif + + /* input modes */ + tio->c_iflag = (BRKINT | IGNPAR | ICRNL | IXON +# ifdef IMAXBEL + | IMAXBEL +# endif + ); + + /* output modes */ + tio->c_oflag = (OPOST | ONLCR); + + /* control modes */ + tio->c_cflag = (CS8 | CREAD); + + /* line discipline modes */ + tio->c_lflag = (ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK +# if defined (ECHOCTL) && defined (ECHOKE) + | ECHOCTL | ECHOKE +# endif + ); + + /* + * guess an appropriate value for Backspace + */ + +#if defined(FORCE_BACKSPACE) && 0 + PrivMode(1, PrivMode_BackSpace); + tio->c_cc[VERASE] = '\b'; /* force ^H for stty setting... */ + SET_TERMIOS(0, tio); /* ...and make it stick -- casey */ +#elif defined(FORCE_DELETE) && 0 + PrivMode(0, PrivMode_BackSpace); + tio->c_cc[VERASE] = 0x7f; /* force ^? for stty setting... */ + SET_TERMIOS(0, tio); /* ...and make it stick -- casey */ +#else + PrivMode((tio->c_cc[VERASE] == '\b'), PrivMode_BackSpace); +#endif + +#else /* HAVE_TERMIOS_H */ + + /* + * sgtty interface + */ + + /* get parameters -- gtty */ + if (ioctl(0, TIOCGETP, &(tio->sg)) < 0) { + tio->sg.sg_erase = CERASE; /* ^H */ + tio->sg.sg_kill = CKILL; /* ^U */ + } + tio->sg.sg_flags = (CRMOD | ECHO | EVENP | ODDP); + + /* get special characters */ + if (ioctl(0, TIOCGETC, &(tio->tc)) < 0) { + tio->tc.t_intrc = CINTR; /* ^C */ + tio->tc.t_quitc = CQUIT; /* ^\ */ + tio->tc.t_startc = CSTART; /* ^Q */ + tio->tc.t_stopc = CSTOP; /* ^S */ + tio->tc.t_eofc = CEOF; /* ^D */ + tio->tc.t_brkc = -1; + } + /* get local special chars */ + if (ioctl(0, TIOCGLTC, &(tio->lc)) < 0) { + tio->lc.t_suspc = CSUSP; /* ^Z */ + tio->lc.t_dsuspc = CDSUSP; /* ^Y */ + tio->lc.t_rprntc = CRPRNT; /* ^R */ + tio->lc.t_flushc = CFLUSH; /* ^O */ + tio->lc.t_werasc = CWERASE; /* ^W */ + tio->lc.t_lnextc = CLNEXT; /* ^V */ + } + /* get line discipline */ + ioctl(0, TIOCGETD, &(tio->line)); +# ifdef NTTYDISC + tio->line = NTTYDISC; +# endif /* NTTYDISC */ + tio->local = (LCRTBS | LCRTERA | LCTLECH | LPASS8 | LCRTKIL); + + /* + * guess an appropriate value for Backspace + */ + +# ifdef FORCE_BACKSPACE + PrivMode(1, PrivMode_BackSpace); + tio->sg.sg_erase = '\b'; + SET_TTYMODE(0, tio); +# elif defined (FORCE_DELETE) + PrivMode(0, PrivMode_BackSpace); + tio->sg.sg_erase = 0x7f; + SET_TTYMODE(0, tio); +# else + PrivMode((tio->sg.sg_erase == '\b'), PrivMode_BackSpace); +# endif + +#endif /* HAVE_TERMIOS_H */ +} + +/* run_command() */ +/* + * Run the command in a subprocess and return a file descriptor for the + * master end of the pseudo-teletype pair with the command talking to + * the slave. + */ +int +run_command(char *argv[]) +{ + + ttymode_t tio; + int ptyfd; + + /* Save and then give up any super-user privileges */ + privileges(IGNORE); + + ptyfd = get_pty(); + if (ptyfd < 0) + return (-1); + + /* store original tty status for restoration clean_exit() -- rgg 04/12/95 */ + lstat(ttydev, &ttyfd_stat); + D_CMD(("Original settings of %s are mode %o, uid %d, gid %d\n", ttydev, ttyfd_stat.st_mode, + ttyfd_stat.st_uid, ttyfd_stat.st_gid)); + + /* install exit handler for cleanup */ +#ifdef HAVE_ATEXIT + atexit(clean_exit); +#else +# if defined (__sun__) + on_exit(clean_exit, NULL); /* non-ANSI exit handler */ +# else + print_error("no atexit(), UTMP entries can't be cleaned"); +# endif +#endif + + /* + * get tty settings before fork() + * and make a reasonable guess at the value for BackSpace + */ + get_ttymode(&tio); + /* add Backspace value */ + SavedModes |= (PrivateModes & PrivMode_BackSpace); + + /* add value for scrollBar */ + if (scrollbar_visible()) { + PrivateModes |= PrivMode_scrollBar; + SavedModes |= PrivMode_scrollBar; + } + if (menubar_visible()) { + PrivateModes |= PrivMode_menuBar; + SavedModes |= PrivMode_menuBar; + } +#if DEBUG >= DEBUG_TTYMODE && defined(HAVE_TERMIOS_H) + if (debug_level >= DEBUG_TTYMODE) { + debug_ttymode(&tio); + } +#endif + + /* spin off the command interpreter */ + signal(SIGHUP, Exit_signal); +#ifndef __svr4__ + signal(SIGINT, Exit_signal); +#endif + signal(SIGQUIT, SegvHandler); + signal(SIGTERM, Exit_signal); + signal(SIGCHLD, Child_signal); + signal(SIGSEGV, SegvHandler); + signal(SIGBUS, SegvHandler); + signal(SIGABRT, SegvHandler); + signal(SIGFPE, SegvHandler); + signal(SIGILL, SegvHandler); + signal(SIGSYS, SegvHandler); + + /* need to trap SIGURG for SVR4 (Unixware) rlogin */ + /* signal (SIGURG, SIG_DFL); */ + + D_CMD(("run_command(): forking\n")); + cmd_pid = fork(); + D_CMD(("After fork(), cmd_pid == %d\n", cmd_pid)); + if (cmd_pid < 0) { + print_error("fork(): %s", strerror(errno)); + return (-1); + } + if (cmd_pid == 0) { /* child */ + + /* signal (SIGHUP, Exit_signal); */ + /* signal (SIGINT, Exit_signal); */ +#ifdef HAVE_UNSETENV + /* avoid passing old settings and confusing term size */ + unsetenv("LINES"); + unsetenv("COLUMNS"); + /* avoid passing termcap since terminfo should be okay */ + unsetenv("TERMCAP"); +#endif /* HAVE_UNSETENV */ + /* establish a controlling teletype for the new session */ + get_tty(); + + /* initialize terminal attributes */ + SET_TTYMODE(0, &tio); + + /* become virtual console, fail silently */ + if (Options & Opt_console) { + int fd = 1; + + privileges(INVOKE); +#ifdef SRIOCSREDIR + fd = open(CONSOLE, O_WRONLY); + if (fd < 0 || ioctl(fd, SRIOCSREDIR, 0) < 0) { + if (fd >= 0) + close(fd); + } +#elif defined(TIOCCONS) + ioctl(0, TIOCCONS, &fd); +#endif /* SRIOCSREDIR */ + privileges(REVERT); + } + tt_winsize(0); /* set window size */ + + /* Permanently revoke all privileges for the child process. + Root shells for everyone are tres uncool.... ;^) -- mej */ +#ifdef _HPUX_SOURCE + setresuid(my_ruid, my_ruid, my_euid); + setresgid(my_rgid, my_rgid, my_egid); +#else + /* No special treatment is needed for systems with saved uids/gids, + because the exec*() calls reset the saved uid/gid to the + effective uid/gid -- mej */ +# ifndef __CYGWIN32__ + setregid(my_rgid, my_rgid); + setreuid(my_ruid, my_ruid); +# endif /* __CYGWIN32__ */ +#endif /* _HPUX_SOURCE */ + + D_UTMP(("Child process reset\n")); + my_euid = my_ruid; + my_egid = my_rgid; + + /* reset signals and spin off the command interpreter */ + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + signal(SIGSEGV, SIG_DFL); + signal(SIGBUS, SIG_DFL); + signal(SIGABRT, SIG_DFL); + signal(SIGFPE, SIG_DFL); + signal(SIGILL, SIG_DFL); + signal(SIGSYS, SIG_DFL); + signal(SIGALRM, SIG_DFL); + + /* + * mimick login's behavior by disabling the job control signals + * a shell that wants them can turn them back on + */ +#ifdef SIGTSTP + signal(SIGTSTP, SIG_IGN); + signal(SIGTTIN, SIG_IGN); + signal(SIGTTOU, SIG_IGN); +#endif /* SIGTSTP */ + + /* command interpreter path */ + D_CMD(("[%d] About to spawn shell\n", getpid())); + chdir(initial_dir); + if (argv != NULL) { +#if DEBUG >= DEBUG_CMD + if (debug_level >= DEBUG_CMD) { + int i; + + for (i = 0; argv[i]; i++) { + DPRINTF1(("argv[%d] = \"%s\"\n", i, argv[i])); + } + } +#endif + execvp(argv[0], argv); + print_error("execvp() failed, cannot execute \"%s\": %s", argv[0], strerror(errno)); + } else { + + const char *argv0, *shell; + + if ((shell = getenv("SHELL")) == NULL || *shell == '\0') + shell = "/bin/sh"; + + argv0 = my_basename(shell); + if (Options & Opt_loginShell) { + char *p = MALLOC((strlen(argv0) + 2) * sizeof(char)); + + p[0] = '-'; + strcpy(&p[1], argv0); + argv0 = p; + } + execlp(shell, argv0, NULL); + print_error("execlp() failed, cannot execute \"%s\": %s", shell, strerror(errno)); + } + sleep(3); /* Sleep to make sure fork() returns in the parent, and so user can read error message */ + exit(EXIT_FAILURE); + } +#ifdef UTMP_SUPPORT + privileges(RESTORE); + if (Options & Opt_utmpLogging) + makeutent(ttydev, display_name); /* stamp /etc/utmp */ + privileges(IGNORE); +#endif + +#if 0 + D_THREADS(("run_command(): pthread_join(resize_sub_thr)\n")); + pthread_join(resize_sub_thr, NULL); +#endif + + D_CMD(("run_command() returning\n")); + return (ptyfd); +} + +/* init_command() */ +void +init_command(char *argv[]) +{ + + /* Initialize the command connection. This should be called after + the X server connection is established. */ + + /* Enable delete window protocol */ + wmDeleteWindow = XInternAtom(Xdisplay, "WM_DELETE_WINDOW", False); + XSetWMProtocols(Xdisplay, TermWin.parent, &wmDeleteWindow, 1); + +#ifdef OFFIX_DND + /* Enable OffiX Dnd (drag 'n' drop) protocol */ + DndProtocol = XInternAtom(Xdisplay, "DndProtocol", False); + DndSelection = XInternAtom(Xdisplay, "DndSelection", False); +#endif /* OFFIX_DND */ + + init_xlocale(); + + /* get number of available file descriptors */ +#ifdef _POSIX_VERSION + num_fds = sysconf(_SC_OPEN_MAX); +#else + num_fds = getdtablesize(); +#endif + +#ifdef META8_OPTION + meta_char = (Options & Opt_meta8 ? 0x80 : 033); +#endif + +#ifdef GREEK_SUPPORT + greek_init(); +#endif + + Xfd = XConnectionNumber(Xdisplay); + D_CMD(("Xfd = %d\n", Xfd)); + cmdbuf_ptr = cmdbuf_endp = cmdbuf_base; + + if ((cmd_fd = run_command(argv)) < 0) { + print_error("aborting"); + exit(EXIT_FAILURE); + } +} + +/* Xlocale */ +#ifndef NO_XLOCALE +inline const char * +get_input_style_flags(XIMStyle style) +{ + + static char style_buff[256]; + + strcpy(style_buff, "("); + if (style & XIMPreeditCallbacks) { + strcat(style_buff, "XIMPreeditCallbacks"); + } else if (style & XIMPreeditPosition) { + strcat(style_buff, "XIMPreeditPosition"); + } else if (style & XIMPreeditArea) { + strcat(style_buff, "XIMPreeditArea"); + } else if (style & XIMPreeditNothing) { + strcat(style_buff, "XIMPreeditNothing"); + } else if (style & XIMPreeditNone) { + strcat(style_buff, "XIMPreeditNone"); + } + strcat(style_buff, " | "); + if (style & XIMStatusCallbacks) { + strcat(style_buff, "XIMStatusCallbacks"); + } else if (style & XIMStatusArea) { + strcat(style_buff, "XIMStatusArea"); + } else if (style & XIMStatusNothing) { + strcat(style_buff, "XIMStatusNothing"); + } else if (style & XIMStatusNone) { + strcat(style_buff, "XIMStatusNone"); + } + strcat(style_buff, ")"); + return style_buff; +} + +void +init_xlocale(void) +{ + + char *p, *s, buf[32], tmp[1024]; + XIM xim = NULL; + XIMStyle input_style; + XIMStyles *xim_styles = NULL; + int found, i, mc; + XFontSet fontset = 0; + char *fontname, **ml, *ds; + XVaNestedList list; + const char fs_base[] = ",-misc-fixed-*-r-*-*-*-120-*-*-*-*-*-*"; + + D_X11(("Initializing X locale and Input Method...\n")); + Input_Context = NULL; + if (rs_inputMethod && strlen(rs_inputMethod) >= sizeof(tmp)) { + print_error("Input Method too long, ignoring."); + rs_inputMethod = NULL; + } +# ifdef KANJI + setlocale(LC_CTYPE, ""); +# else + if (rs_inputMethod && !*rs_inputMethod) { + rs_inputMethod = NULL; + } +# endif + + if (rs_inputMethod == NULL) { + if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p) { + xim = XOpenIM(Xdisplay, NULL, NULL, NULL); + } + } else { + strcpy(tmp, rs_inputMethod); + for (s = tmp; *s; /*nil */ ) { + + char *end, *next_s; + + for (; *s && isspace(*s); s++); + if (!*s) + break; + end = s; + for (; *end && (*end != ','); end++); + next_s = end--; + for (; (end >= s) && isspace(*end); end--); + *(end + 1) = '\0'; + + if (*s) { + snprintf(buf, sizeof(buf), "@im=%s", s); + if ((p = XSetLocaleModifiers(buf)) != NULL && *p && (xim = XOpenIM(Xdisplay, NULL, NULL, NULL)) != NULL) { + break; + } + } + if (!*next_s) + break; + s = (next_s + 1); + } + } + + if (xim == NULL && (p = XSetLocaleModifiers("")) != NULL && *p) { + xim = XOpenIM(Xdisplay, NULL, NULL, NULL); + } + if (xim == NULL) { + D_X11(("Error: Failed to open Input Method\n")); + return; + } else { + D_X11(("Opened X Input Method. xim == 0x%08x\n", xim)); + } + + if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL) || !xim_styles) { + D_X11(("Error: Input Method doesn't support any style\n")); + XCloseIM(xim); + return; + } else { + D_X11((" -> Input Method supports %d styles.\n", xim_styles->count_styles)); + } + + /* We only support the Root preedit type */ + input_style = (XIMPreeditNothing | XIMStatusNothing); + D_X11((" -> input_style == 0x%08x\n", input_style)); + + for (i = 0, found = 0; i < xim_styles->count_styles; i++) { + D_X11((" -> Supported style flags: 0x%08x %s\n", xim_styles->supported_styles[i], get_input_style_flags(xim_styles->supported_styles[i]))); + D_X11((" -> 0x%08x %s\n", xim_styles->supported_styles[i] & input_style, + get_input_style_flags(xim_styles->supported_styles[i] & input_style))); + if ((xim_styles->supported_styles[i] & input_style) == (xim_styles->supported_styles[i])) { + input_style = xim_styles->supported_styles[i]; + found = 1; + break; + } + } + XFree(xim_styles); + + if (!found) { + D_X11(("Error: " APL_NAME " " VERSION " only supports the \"Root\" preedit type, which the Input Method does not support.\n")); + XCloseIM(xim); + return; + } + /* Create Font Set */ + +#ifdef KANJI + fontname = MALLOC(strlen(rs_font[0]) + strlen(rs_kfont[0]) + sizeof(fs_base) + 2); + if (fontname) { + strcpy(fontname, rs_font[0]); + strcat(fontname, fs_base); + strcat(fontname, ","); + strcat(fontname, rs_kfont[0]); + } +#else + fontname = MALLOC(strlen(rs_font[0]) + sizeof(fs_base) + 1); + if (fontname) { + strcpy(fontname, rs_font[0]); + strcat(fontname, fs_base); + } +#endif + if (fontname) { + setlocale(LC_ALL, ""); + fontset = XCreateFontSet(Xdisplay, fontname, &ml, &mc, &ds); + FREE(fontname); + if (mc) { + XFreeStringList(ml); + fontset = 0; + return; + } + } + list = XVaCreateNestedList(0, XNFontSet, fontset, NULL); + Input_Context = XCreateIC(xim, XNInputStyle, input_style, XNClientWindow, TermWin.parent, XNFocusWindow, TermWin.parent, + XNPreeditAttributes, list, XNStatusAttributes, list, NULL); + if (Input_Context == NULL) { + D_X11(("Error: Unable to create Input Context\n")); + XCloseIM(xim); + } +} +#endif /* NO_XLOCALE */ + +/* window resizing */ +/* + * Tell the teletype handler what size the window is. + * Called after a window size change. + */ +void +tt_winsize(int fd) +{ + + struct winsize ws; + + if (fd < 0) + return; + + ws.ws_col = (unsigned short) TermWin.ncol; + ws.ws_row = (unsigned short) TermWin.nrow; +#ifndef __CYGWIN32__ + ws.ws_xpixel = ws.ws_ypixel = 0; +#endif + ioctl(fd, TIOCSWINSZ, &ws); +} + +void +tt_resize(void) +{ + tt_winsize(cmd_fd); +} + +/* Convert the keypress event into a string */ +inline void +lookup_key(XEvent * ev) +{ + + static int numlock_state = 0; + static unsigned char kbuf[KBUFSZ]; + int ctrl, meta, shft, len; + KeySym keysym; + +#ifndef NO_XLOCALE + static Status status_return; + +#endif + +#if DEBUG >= DEBUG_CMD + static int debug_key = 1; /* accessible by a debugger only */ + +#endif +#ifdef GREEK_SUPPORT + static short greek_mode = 0; + +#endif + + /* + * use Num_Lock to toggle Keypad on/off. If Num_Lock is off, allow an + * escape sequence to toggle the Keypad. + * + * Always permit `shift' to override the current setting + */ + shft = (ev->xkey.state & ShiftMask); + ctrl = (ev->xkey.state & ControlMask); + meta = (ev->xkey.state & Mod1Mask); + if (numlock_state || (ev->xkey.state & Mod5Mask)) { + numlock_state = (ev->xkey.state & Mod5Mask); /* numlock toggle */ + PrivMode((!numlock_state), PrivMode_aplKP); + } +#ifndef NO_XLOCALE + if (Input_Context != NULL) { + len = XmbLookupString(Input_Context, &ev->xkey, kbuf, sizeof(kbuf), &keysym, &status_return); + if (status_return == XLookupNone) { + D_X11(("XmbLookupString() returned len == %d, status_return == XLookupNone\n", len)); + len = 0; + } else if (status_return == XBufferOverflow) { + D_X11(("XmbLookupString() returned len == %d, status_return == XBufferOverflow\n", len)); + print_error("XmbLookupString(): Buffer overflow, string too long."); + XmbResetIC(Input_Context); + } else if (status_return == XLookupKeySym) { + D_X11(("XmbLookupString() returned len == %d, status_return == XLookupKeySym\n", len)); + if ((keysym >= 0x0100) && (keysym < 0x0400)) { + len = 1; + kbuf[0] = (keysym & 0xff); + } + } else if (status_return == XLookupBoth) { + D_X11(("XmbLookupString() returned len == %d, status_return == XLookupBoth\n", len)); + if ((keysym >= 0x0100) && (keysym < 0x0400)) { + len = 1; + kbuf[0] = (keysym & 0xff); + } + } else if (status_return == XLookupChars) { + D_X11(("XmbLookupString() returned len == %d, status_return == XLookupChars\n", len)); + /* Nothing */ + } + } else { + len = XLookupString(&ev->xkey, kbuf, sizeof(kbuf), &keysym, NULL); + } +#else /* NO_XLOCALE */ + len = XLookupString(&ev->xkey, kbuf, sizeof(kbuf), &keysym, NULL); + /* + * have unmapped Latin[2-4] entries -> Latin1 + * good for installations with correct fonts, but without XLOCAL + */ + if (!len && (keysym >= 0x0100) && (keysym < 0x0400)) { + len = 1; + kbuf[0] = (keysym & 0xff); + } +#endif /* NO_XLOCALE */ + + if (len && (Options & Opt_homeOnInput)) + TermWin.view_start = 0; + + /* for some backwards compatibility */ +#if defined (HOTKEY_CTRL) || defined (HOTKEY_META) +# ifdef HOTKEY_CTRL +# define HOTKEY ctrl +# else +# ifdef HOTKEY_META +# define HOTKEY meta +# endif +# endif + if (HOTKEY) { + if (keysym == ks_bigfont) { + change_font(0, FONT_UP); + return; + } else if (keysym == ks_smallfont) { + change_font(0, FONT_DN); + return; + } + } +# undef HOTKEY +#endif + + if (shft) { + /* Shift + F1 - F10 generates F11 - F20 */ + if (keysym >= XK_F1 && keysym <= XK_F10) { + keysym += (XK_F11 - XK_F1); + shft = 0; /* turn off Shift */ + } else if (!ctrl && !meta && (PrivateModes & PrivMode_ShiftKeys)) { + + int lnsppg; /* Lines per page to scroll */ + +#ifdef PAGING_CONTEXT_LINES + lnsppg = TermWin.nrow - PAGING_CONTEXT_LINES; +#else + lnsppg = TermWin.nrow * 4 / 5; +#endif + + switch (keysym) { + /* normal XTerm key bindings */ + case XK_Prior: /* Shift+Prior = scroll back */ + if (TermWin.saveLines) { + scr_page(UP, lnsppg); + return; + } + break; + + case XK_Next: /* Shift+Next = scroll forward */ + if (TermWin.saveLines) { + scr_page(DN, lnsppg); + return; + } + break; + + case XK_Insert: /* Shift+Insert = paste mouse selection */ + selection_request(ev->xkey.time, ev->xkey.x, ev->xkey.y); + return; + break; + + /* Eterm extras */ + case XK_KP_Add: /* Shift+KP_Add = bigger font */ + change_font(0, FONT_UP); + return; + break; + + case XK_KP_Subtract: /* Shift+KP_Subtract = smaller font */ + change_font(0, FONT_DN); + return; + break; + } + } + } +#ifdef UNSHIFTED_SCROLLKEYS + else if (!ctrl && !meta) { + switch (keysym) { + case XK_Prior: + if (TermWin.saveLines) { + scr_page(UP, TermWin.nrow * 4 / 5); + return; + } + break; + + case XK_Next: + if (TermWin.saveLines) { + scr_page(DN, TermWin.nrow * 4 / 5); + return; + } + break; + } + } +#endif + + switch (keysym) { + case XK_Print: +#if DEBUG >= DEBUG_SELECTION + if (debug_level >= DEBUG_SELECTION) { + debug_selection(); + } +#endif +#ifdef PRINTPIPE + scr_printscreen(ctrl | shft); + return; +#endif + break; + + case XK_Mode_switch: +#ifdef GREEK_SUPPORT + greek_mode = !greek_mode; + if (greek_mode) { + xterm_seq(XTerm_title, (greek_getmode() == GREEK_ELOT928 ? "[Greek: iso]" : "[Greek: ibm]")); + greek_reset(); + } else + xterm_seq(XTerm_title, APL_NAME "-" VERSION); + return; +#endif + break; + } + + if (keysym >= 0xFF00 && keysym <= 0xFFFF) { +#ifdef KEYSYM_ATTRIBUTE + if (!(shft | ctrl) && KeySym_map[keysym - 0xFF00] != NULL) { + + const unsigned char *kbuf; + unsigned int len; + + kbuf = (KeySym_map[keysym - 0xFF00]); + len = *kbuf++; + + /* escape prefix */ + if (meta +# ifdef META8_OPTION + && (meta_char == 033) +# endif + ) { + const unsigned char ch = '\033'; + + tt_write(&ch, 1); + } + tt_write(kbuf, len); + return; + } else +#endif + switch (keysym) { + case XK_BackSpace: + len = 1; +#ifdef FORCE_BACKSPACE + kbuf[0] = (!(shft | ctrl) ? '\b' : '\177'); +#elif defined(FORCE_DELETE) + kbuf[0] = ((shft | ctrl) ? '\b' : '\177'); +#else + kbuf[0] = (((PrivateModes & PrivMode_BackSpace) ? !(shft | ctrl) : (shft | ctrl)) ? '\b' : '\177'); +#endif + break; + + case XK_Tab: + if (shft) { + len = 3; + strcpy(kbuf, "\033[Z"); + } + break; + +#ifdef XK_KP_Home + case XK_KP_Home: + /* allow shift to override */ + if ((PrivateModes & PrivMode_aplKP) ? !shft : shft) { + len = 3; + strcpy(kbuf, "\033Ow"); + break; + } + /* -> else FALL THROUGH */ +#endif + + case XK_Home: + len = strlen(strcpy(kbuf, KS_HOME)); + break; + +#ifdef XK_KP_Left + case XK_KP_Left: /* \033Ot or standard */ + case XK_KP_Up: /* \033Ox or standard */ + case XK_KP_Right: /* \033Ov or standard */ + case XK_KP_Down: /* \033Ow or standard */ + if ((PrivateModes && PrivMode_aplKP) ? !shft : shft) { + len = 3; + strcpy(kbuf, "\033OZ"); + kbuf[2] = ("txvw"[keysym - XK_KP_Left]); + break; + } else { + /* translate to std. cursor key */ + keysym = XK_Left + (keysym - XK_KP_Left); + } + /* FALL THROUGH */ +#endif + case XK_Left: /* "\033[D" */ + case XK_Up: /* "\033[A" */ + case XK_Right: /* "\033[C" */ + case XK_Down: /* "\033[B" */ + len = 3; + strcpy(kbuf, "\033[@"); + kbuf[2] = ("DACB"[keysym - XK_Left]); + if (PrivateModes & PrivMode_aplCUR) { + kbuf[1] = 'O'; + } else if (shft) { /* do Shift first */ + kbuf[2] = ("dacb"[keysym - XK_Left]); + } else if (ctrl) { + kbuf[1] = 'O'; + kbuf[2] = ("dacb"[keysym - XK_Left]); + } + break; +#ifndef UNSHIFTED_SCROLLKEYS +# ifdef XK_KP_Prior + case XK_KP_Prior: + /* allow shift to override */ + if ((PrivateModes & PrivMode_aplKP) ? !shft : shft) { + len = 3; + strcpy(kbuf, "\033Oy"); + break; + } + /* -> else FALL THROUGH */ +# endif /* XK_KP_Prior */ + case XK_Prior: + len = 4; + strcpy(kbuf, "\033[5~"); + break; +# ifdef XK_KP_Next + case XK_KP_Next: + /* allow shift to override */ + if ((PrivateModes & PrivMode_aplKP) ? !shft : shft) { + len = 3; + strcpy(kbuf, "\033Os"); + break; + } + /* -> else FALL THROUGH */ +# endif /* XK_KP_Next */ + case XK_Next: + len = 4; + strcpy(kbuf, "\033[6~"); + break; +#endif /* UNSHIFTED_SCROLLKEYS */ +#ifdef XK_KP_End + case XK_KP_End: + /* allow shift to override */ + if ((PrivateModes & PrivMode_aplKP) ? !shft : shft) { + len = 3; + strcpy(kbuf, "\033Oq"); + break; + } + /* -> else FALL THROUGH */ +#endif /* XK_KP_End */ + case XK_End: + len = strlen(strcpy(kbuf, KS_END)); + break; + + case XK_Select: + len = 4; + strcpy(kbuf, "\033[4~"); + break; + +#ifdef DXK_Remove /* support for DEC remove like key */ + case DXK_Remove: /* drop */ +#endif + case XK_Execute: + len = 4; + strcpy(kbuf, "\033[3~"); + break; + case XK_Insert: + len = 4; + strcpy(kbuf, "\033[2~"); + break; + + case XK_Menu: + len = 5; + strcpy(kbuf, "\033[29~"); + break; + case XK_Find: + len = 4; + strcpy(kbuf, "\033[1~"); + break; + case XK_Help: + len = 5; + strcpy(kbuf, "\033[28~"); + break; + + case XK_KP_Enter: + /* allow shift to override */ + if ((PrivateModes & PrivMode_aplKP) ? !shft : shft) { + len = 3; + strcpy(kbuf, "\033OM"); + } else { + len = 1; + kbuf[0] = '\r'; + } + break; + +#ifdef XK_KP_Begin + case XK_KP_Begin: + len = 3; + strcpy(kbuf, "\033Ou"); + break; + + case XK_KP_Insert: + len = 3; + strcpy(kbuf, "\033Op"); + break; + + case XK_KP_Delete: + len = 3; + strcpy(kbuf, "\033On"); + break; +#endif /* XK_KP_Begin */ + + case XK_KP_F1: /* "\033OP" */ + case XK_KP_F2: /* "\033OQ" */ + case XK_KP_F3: /* "\033OR" */ + case XK_KP_F4: /* "\033OS" */ + len = 3; + strcpy(kbuf, "\033OP"); + kbuf[2] += (keysym - XK_KP_F1); + break; + + case XK_KP_Multiply: /* "\033Oj" : "*" */ + case XK_KP_Add: /* "\033Ok" : "+" */ + case XK_KP_Separator: /* "\033Ol" : "," */ + case XK_KP_Subtract: /* "\033Om" : "-" */ + case XK_KP_Decimal: /* "\033On" : "." */ + case XK_KP_Divide: /* "\033Oo" : "/" */ + case XK_KP_0: /* "\033Op" : "0" */ + case XK_KP_1: /* "\033Oq" : "1" */ + case XK_KP_2: /* "\033Or" : "2" */ + case XK_KP_3: /* "\033Os" : "3" */ + case XK_KP_4: /* "\033Ot" : "4" */ + case XK_KP_5: /* "\033Ou" : "5" */ + case XK_KP_6: /* "\033Ov" : "6" */ + case XK_KP_7: /* "\033Ow" : "7" */ + case XK_KP_8: /* "\033Ox" : "8" */ + case XK_KP_9: /* "\033Oy" : "9" */ + /* allow shift to override */ + if ((PrivateModes & PrivMode_aplKP) ? !shft : shft) { + len = 3; + strcpy(kbuf, "\033Oj"); + kbuf[2] += (keysym - XK_KP_Multiply); + } else { + len = 1; + kbuf[0] = ('*' + (keysym - XK_KP_Multiply)); + } + break; + +#define FKEY(n,fkey) do { \ +len = 5; \ +sprintf(kbuf,"\033[%02d~", (int)((n) + (keysym - fkey))); \ +} while (0); + + case XK_F1: /* "\033[11~" */ + case XK_F2: /* "\033[12~" */ + case XK_F3: /* "\033[13~" */ + case XK_F4: /* "\033[14~" */ + case XK_F5: /* "\033[15~" */ + FKEY(11, XK_F1); + break; + + case XK_F6: /* "\033[17~" */ + case XK_F7: /* "\033[18~" */ + case XK_F8: /* "\033[19~" */ + case XK_F9: /* "\033[20~" */ + case XK_F10: /* "\033[21~" */ + FKEY(17, XK_F6); + break; + + case XK_F11: /* "\033[23~" */ + case XK_F12: /* "\033[24~" */ + case XK_F13: /* "\033[25~" */ + case XK_F14: /* "\033[26~" */ + FKEY(23, XK_F11); + break; + + case XK_F15: /* "\033[28~" */ + case XK_F16: /* "\033[29~" */ + FKEY(28, XK_F15); + break; + + case XK_F17: /* "\033[31~" */ + case XK_F18: /* "\033[32~" */ + case XK_F19: /* "\033[33~" */ + case XK_F20: /* "\033[34~" */ + case XK_F21: /* "\033[35~" */ + case XK_F22: /* "\033[36~" */ + case XK_F23: /* "\033[37~" */ + case XK_F24: /* "\033[38~" */ + case XK_F25: /* "\033[39~" */ + case XK_F26: /* "\033[40~" */ + case XK_F27: /* "\033[41~" */ + case XK_F28: /* "\033[42~" */ + case XK_F29: /* "\033[43~" */ + case XK_F30: /* "\033[44~" */ + case XK_F31: /* "\033[45~" */ + case XK_F32: /* "\033[46~" */ + case XK_F33: /* "\033[47~" */ + case XK_F34: /* "\033[48~" */ + case XK_F35: /* "\033[49~" */ + FKEY(31, XK_F17); + break; +#undef FKEY +#ifdef KS_DELETE + case XK_Delete: + len = strlen(strcpy(kbuf, KS_DELETE)); + break; +#endif + } + +#ifdef META8_OPTION + if (meta && (meta_char == 0x80) && len > 0) { + kbuf[len - 1] |= 0x80; + } +#endif + } else if (ctrl && keysym == XK_minus) { + len = 1; + kbuf[0] = '\037'; /* Ctrl-Minus generates ^_ (31) */ + } else { +#ifdef META8_OPTION + /* set 8-bit on */ + if (meta && (meta_char == 0x80)) { + + unsigned char *ch; + + for (ch = kbuf; ch < kbuf + len; ch++) + *ch |= 0x80; + meta = 0; + } +#endif +#ifdef GREEK_SUPPORT + if (greek_mode) + len = greek_xlat(kbuf, len); +#endif + } + + if (len <= 0) + return; /* not mapped */ + + /* + * these modifications only affect the static keybuffer + * pass Shift/Control indicators for function keys ending with `~' + * + * eg, + * Prior = "ESC[5~" + * Shift+Prior = "ESC[5~" + * Ctrl+Prior = "ESC[5^" + * Ctrl+Shift+Prior = "ESC[5@" + */ + if (kbuf[0] == '\033' && kbuf[1] == '[' && kbuf[len - 1] == '~') + kbuf[len - 1] = (shft ? (ctrl ? '@' : '$') : (ctrl ? '^' : '~')); + + /* escape prefix */ + if (meta +#ifdef META8_OPTION + && (meta_char == 033) +#endif + ) { + + const unsigned char ch = '\033'; + + tt_write(&ch, 1); + } +#if DEBUG >= DEBUG_CMD + if (debug_level >= DEBUG_CMD && debug_key) { /* Display keyboard buffer contents */ + + char *p; + int i; + + fprintf(stderr, "key 0x%04X[%d]: `", (unsigned int) keysym, len); + for (i = 0, p = kbuf; i < len; i++, p++) + fprintf(stderr, (*p >= ' ' && *p < '\177' ? "%c" : "\\%03o"), *p); + fprintf(stderr, "'\n"); + } +#endif /* DEBUG_CMD */ + tt_write(kbuf, len); +} + +#if (MENUBAR_MAX) + +/* attempt to `write' COUNT to the input buffer */ +unsigned int +cmd_write(const unsigned char *str, unsigned int count) +{ + + int n; + + n = (count - (cmdbuf_ptr - cmdbuf_base)); + /* need to insert more chars that space available in the front */ + if (n > 0) { + /* try and get more space from the end */ + unsigned char *src, *dst; + + dst = (cmdbuf_base + sizeof(cmdbuf_base) - 1); /* max pointer */ + + if ((cmdbuf_ptr + n) > dst) + n = (dst - cmdbuf_ptr); /* max # chars to insert */ + + if ((cmdbuf_endp + n) > dst) + cmdbuf_endp = (dst - n); /* truncate end if needed */ + + /* equiv: memmove ((cmdbuf_ptr+n), cmdbuf_ptr, n); */ + src = cmdbuf_endp; + dst = src + n; + /* FIXME: anything special to avoid possible pointer wrap? */ + while (src >= cmdbuf_ptr) + *dst-- = *src--; + + /* done */ + cmdbuf_ptr += n; + cmdbuf_endp += n; + } + while (count-- && cmdbuf_ptr > cmdbuf_base) { + /* sneak one in */ + cmdbuf_ptr--; + *cmdbuf_ptr = str[count]; + } + + return (0); +} +#endif /* MENUBAR_MAX */ + +#ifdef BACKGROUND_CYCLING_SUPPORT +# if RETSIGTYPE != void +# define CPC_RETURN(x) return ((RETSIGTYPE) x) +# else +# define CPC_RETURN(x) return +# endif + +RETSIGTYPE +check_pixmap_change(int sig) +{ + + static time_t last_update = 0; + time_t now; + static unsigned long image_idx = 0; + void (*old_handler) (int); + static unsigned char in_cpc = 0; + + if (in_cpc) + CPC_RETURN(0); + in_cpc = 1; + D_PIXMAP(("check_pixmap_change(): rs_anim_delay == %lu seconds, last_update == %lu\n", + rs_anim_delay, last_update)); + if (!rs_anim_delay) + CPC_RETURN(0); + if (last_update == 0) { + last_update = time(NULL); + old_handler = signal(SIGALRM, check_pixmap_change); + alarm(rs_anim_delay); + in_cpc = 0; + CPC_RETURN(0); + } + now = time(NULL); + D_PIXMAP(("now %lu >= %lu (last_update %lu + rs_anim_delay %lu) ?\n", now, last_update + rs_anim_delay, last_update, rs_anim_delay)); + if (now >= last_update + rs_anim_delay || 1) { + D_PIXMAP(("Time to update pixmap. now == %lu\n", now)); + Imlib_destroy_image(imlib_id, imlib_bg.im); + imlib_bg.im = NULL; + xterm_seq(XTerm_Pixmap, rs_anim_pixmaps[image_idx++]); + last_update = now; + old_handler = signal(SIGALRM, check_pixmap_change); + alarm(rs_anim_delay); + if (rs_anim_pixmaps[image_idx] == NULL) { + image_idx = 0; + } + } + in_cpc = 0; + if (old_handler) { + CPC_RETURN((*old_handler) (sig)); + } else { + CPC_RETURN(sig); + } +} +#endif /* BACKGROUND_CYCLING_SUPPORT */ + +/* cmd_getc() - Return next input character */ +/* + * Return the next input character after first passing any keyboard input + * to the command. + */ +#define CHARS_READ() (cmdbuf_ptr < cmdbuf_endp) +#define CHARS_BUFFERED() (count != CMD_BUF_SIZE) +#define RETURN_CHAR() do { refreshed = 0; return (*cmdbuf_ptr++); } while (0) + +#ifdef REFRESH_DELAY +# define REFRESH_DELAY_USEC 1000000/25 +#endif + +unsigned char +cmd_getc(void) +{ + +#define TIMEOUT_USEC 2500 + static short refreshed = 0; + fd_set readfds; + int retval; + struct timeval value, *delay; + + /* If there has been a lot of new lines, then update the screen + * What the heck I'll cheat and only refresh less than every page-full. + * the number of pages between refreshes is refresh_limit, which + * is incremented here because we must be doing flat-out scrolling. + * + * refreshing should be correct for small scrolls, because of the + * time-out + */ + if (refresh_count >= (refresh_limit * (TermWin.nrow - 1))) { + if (refresh_limit < REFRESH_PERIOD) + refresh_limit++; + refresh_count = 0; + refreshed = 1; + D_CMD(("cmd_getc(): scr_refresh() #1\n")); +#ifdef PROFILE + P_CALL(scr_refresh(refresh_type), "cmd_getc()->scr_refresh()"); +#else + scr_refresh(refresh_type); +#endif + } + /* characters already read in */ + if (CHARS_READ()) { + RETURN_CHAR(); + } + for (;;) { + + v_doPending(); + while (XPending(Xdisplay)) { /* process pending X events */ + + XEvent ev; + + refreshed = 0; + XNextEvent(Xdisplay, &ev); + +#ifndef NO_XLOCALE + if (!XFilterEvent(&ev, ev.xkey.window)) { + D_X11(("cmd_getc(): process_x_event();\n")); + process_x_event(&ev); + } +#else + D_X11(("cmd_getc(): process_x_event();\n")); + process_x_event(&ev); +#endif + + /* in case button actions pushed chars to cmdbuf */ + if (CHARS_READ()) { + RETURN_CHAR(); + } + } + +#ifdef SCROLLBAR_BUTTON_CONTINUAL_SCROLLING + if (scrollbar_isUp()) { + if (!scroll_arrow_delay-- && scr_page(UP, 1)) { + scroll_arrow_delay = SCROLLBAR_CONTINUOUS_DELAY; + refreshed = 0; +/* refresh_type |= SMOOTH_REFRESH; */ + } + } else if (scrollbar_isDn()) { + if (!scroll_arrow_delay-- && scr_page(DN, 1)) { + scroll_arrow_delay = SCROLLBAR_CONTINUOUS_DELAY; + refreshed = 0; +/* refresh_type |= SMOOTH_REFRESH; */ + } + } +#endif /* SCROLLBAR_BUTTON_CONTINUAL_SCROLLING */ + + /* Nothing to do! */ + FD_ZERO(&readfds); + FD_SET(cmd_fd, &readfds); + FD_SET(Xfd, &readfds); + value.tv_usec = TIMEOUT_USEC; + value.tv_sec = 0; + + if (refreshed +#ifdef SCROLLBAR_BUTTON_CONTINUAL_SCROLLING + && !(scrollbar_isUpDn()) +#endif + ) { + delay = NULL; + } else { + delay = &value; + } + retval = select(num_fds, &readfds, NULL, NULL, delay); + + /* See if we can read from the application */ + if (FD_ISSET(cmd_fd, &readfds)) { + + /* unsigned int count = BUFSIZ; */ + register unsigned int count = CMD_BUF_SIZE; + + cmdbuf_ptr = cmdbuf_endp = cmdbuf_base; + + /* while (count > sizeof(cmdbuf_base) / 2) */ + while (count) { + + /* int n = read(cmd_fd, cmdbuf_endp, count); */ + register int n = read(cmd_fd, cmdbuf_endp, count); + + if (n <= 0) + break; + cmdbuf_endp += n; + count -= n; + } + /* some characters read in */ + if (CHARS_BUFFERED()) { + RETURN_CHAR(); + } + } + /* select statement timed out - better update the screen */ + + if (retval == 0) { + refresh_count = 0; + refresh_limit = 1; + if (!refreshed) { + refreshed = 1; + D_CMD(("cmd_getc(): scr_refresh() #2\n")); + scr_refresh(refresh_type); + if (scrollbar_visible()) + scrollbar_show(1); + } + } + } + + D_CMD(("cmd_getc() returning\n")); + return (0); +} + +#if MENUBAR_MAX +# define XEVENT_IS_MYWIN(ev) (((ev)->xany.window == TermWin.parent) \ + || ((ev)->xany.window == TermWin.vt) \ + || ((ev)->xany.window == menuBar.win) \ + || ((ev)->xany.window == scrollBar.win)) +#else +# define XEVENT_IS_MYWIN(ev) (((ev)->xany.window == TermWin.parent) \ + || ((ev)->xany.window == TermWin.vt) \ + || ((ev)->xany.window == scrollBar.win)) +#endif +#define XEVENT_IS_PARENT(ev) (((ev)->xany.window == TermWin.wm_parent) \ + || ((ev)->xany.window == TermWin.wm_grandparent)) +#define XEVENT_REQUIRE(bool_test) do { if (!(bool_test)) return; } while (0) + +void +process_x_event(XEvent * ev) +{ + static Time buttonpress_time, lastbutton_press; + static int clicks = 0; + +#define clickOnce() (clicks <= 1) + static int bypass_keystate = 0; + int reportmode; + static int mouseoffset = 0; /* Mouse pointer offset info scrollbar anchor */ + +#ifdef COUNT_X_EVENTS + static long long event_cnt = 0; + static long long keypress_cnt = 0; + static long long motion_cnt = 0; + static long long expose_cnt = 0; + +#endif +#ifdef PIXMAP_OFFSET + Atom type; + int format; + unsigned long length, after; + unsigned char *data; + +#endif +#ifdef USE_ACTIVE_TAGS + static Time activate_time; + +#endif +#ifdef PROFILE_X_EVENTS + struct timeval expose_start, expose_stop, motion_start, motion_stop, keypress_start, keypress_stop; + static long expose_total = 0; + +#endif +#ifdef WATCH_DESKTOP_OPTION + Window new_desktop_window, last_desktop_window = desktop_window; + +#endif + +#ifdef COUNT_X_EVENTS + event_cnt++; + D_EVENTS(("total number of events: %ld\n", event_cnt)); +#endif + + D_EVENTS(("process_x_event(0x%02x): %s, for window 0x%08x\n", + ev->type, event_type_to_name(ev->type), ev->xany.window)); + + switch (ev->type) { + case KeyPress: + if (keypress_exit) + exit(EXIT_SUCCESS); + D_EVENTS(("process_x_event(%s)\n", "KeyPress")); +#ifdef COUNT_X_EVENTS + keypress_cnt++; + D_EVENTS(("total number of KeyPress events: %ld\n", keypress_cnt)); +#endif +#ifdef PROFILE_X_EVENTS + P_SETTIMEVAL(keypress_start); +#endif + XEVENT_REQUIRE(XEVENT_IS_MYWIN(ev)); + lookup_key(ev); +#ifdef PROFILE_X_EVENTS + P_SETTIMEVAL(keypress_stop); + fprintf(stderr, "KeyPress: %ld microseconds\n", + P_CMPTIMEVALS_USEC(keypress_start, keypress_stop)); +#endif + break; + +#ifdef WATCH_DESKTOP_OPTION + case PropertyNotify: + D_EVENTS(("process_x_event(%s)\n", "PropertyNotify")); + if (Options & Opt_pixmapTrans && Options & Opt_watchDesktop) { + if (desktop_window != None) { + XSelectInput(Xdisplay, desktop_window, 0); + } else { + XSelectInput(Xdisplay, Xroot, 0); + } + XGetWindowProperty(Xdisplay, Xroot, ev->xproperty.atom, 0L, 1L, False, + AnyPropertyType, &type, &format, &length, &after, &data); + if (type == XA_PIXMAP) { + if (desktop_pixmap != None) { + XFreePixmap(Xdisplay, desktop_pixmap); + desktop_pixmap = None; /* Force the re-read */ + } + render_pixmap(TermWin.vt, imlib_bg, bgPixmap, 0, 1); + scr_expose(0, 0, TermWin_TotalWidth(), TermWin_TotalHeight()); + } + if (desktop_window != None) { + XSelectInput(Xdisplay, desktop_window, PropertyChangeMask); + } else { + XSelectInput(Xdisplay, Xroot, PropertyChangeMask); + } + } + break; + + case ReparentNotify: + D_EVENTS(("ReparentNotify: window == 0x%08x, parent == 0x%08x, TermWin.parent == 0x%08x, TermWin.wm_parent == 0x%08x\n", + ev->xreparent.window, ev->xreparent.parent, TermWin.parent, TermWin.wm_parent)); + if (Options & Opt_watchDesktop) { + if (ev->xreparent.window == TermWin.parent) { + D_EVENTS(("It's TermWin.parent. Assigning TermWin.wm_parent to 0x%08x\n", ev->xreparent.parent)); + if (TermWin.wm_parent != None) { + XSelectInput(Xdisplay, TermWin.wm_parent, None); + } + TermWin.wm_parent = ev->xreparent.parent; + XSelectInput(Xdisplay, TermWin.wm_parent, (StructureNotifyMask | SubstructureNotifyMask)); + } else if (ev->xreparent.window == TermWin.wm_parent || ev->xreparent.window == TermWin.wm_grandparent) { + D_EVENTS(("It's my parent! last_desktop_window == 0x%08x, desktop_window == 0x%08x\n", + last_desktop_window, get_desktop_window())); + if (Options & Opt_pixmapTrans && Options & Opt_watchDesktop && get_desktop_window() != last_desktop_window) { + D_EVENTS(("Desktop changed!\n")); + if (desktop_pixmap != None) { + XFreePixmap(Xdisplay, desktop_pixmap); + desktop_pixmap = None; /* Force the re-read */ + } + render_pixmap(TermWin.vt, imlib_bg, bgPixmap, 0, 1); + scr_expose(0, 0, TermWin_TotalWidth(), TermWin_TotalHeight()); + } + } + } + break; +#endif + + case ClientMessage: + XEVENT_REQUIRE(XEVENT_IS_MYWIN(ev)); + D_EVENTS(("process_x_event(%s)\n", "ClientMessage")); + if (ev->xclient.format == 32 && ev->xclient.data.l[0] == wmDeleteWindow) + exit(EXIT_SUCCESS); +#ifdef OFFIX_DND + /* OffiX Dnd (drag 'n' drop) protocol */ + if (ev->xclient.message_type == DndProtocol && + ((ev->xclient.data.l[0] == DndFile) || + (ev->xclient.data.l[0] == DndDir) || + (ev->xclient.data.l[0] == DndLink))) { + /* Get Dnd data */ + Atom ActualType; + int ActualFormat; + unsigned char *data; + unsigned long Size, RemainingBytes; + + XGetWindowProperty(Xdisplay, Xroot, + DndSelection, + 0L, 1000000L, + False, AnyPropertyType, + &ActualType, &ActualFormat, + &Size, &RemainingBytes, + &data); + XChangeProperty(Xdisplay, Xroot, + XA_CUT_BUFFER0, XA_STRING, + 8, PropModeReplace, + data, strlen(data)); + selection_paste(Xroot, XA_CUT_BUFFER0, True); + XSetInputFocus(Xdisplay, Xroot, RevertToNone, CurrentTime); + } +#endif /* OFFIX_DND */ + break; + + case MappingNotify: + D_EVENTS(("process_x_event(%s)\n", "MappingNotify")); + XRefreshKeyboardMapping(&(ev->xmapping)); + break; + +#ifdef USE_ACTIVE_TAGS + case LeaveNotify: + XEVENT_REQUIRE(XEVENT_IS_MYWIN(ev)); + tag_hide(); + break; +#endif + + /* Here's my conclusion: + * If the window is completely unobscured, use bitblt's + * to scroll. Even then, they're only used when doing partial + * screen scrolling. When partially obscured, we have to fill + * in the GraphicsExpose parts, which means that after each refresh, + * we need to wait for the graphics expose or Noexpose events, + * which ought to make things real slow! + */ + case VisibilityNotify: + D_EVENTS(("process_x_event(%s)\n", "VisibilityNotify")); + XEVENT_REQUIRE(XEVENT_IS_MYWIN(ev)); + switch (ev->xvisibility.state) { + case VisibilityUnobscured: +#ifdef USE_SMOOTH_REFRESH + refresh_type = SMOOTH_REFRESH; +#else + refresh_type = FAST_REFRESH; +#endif + break; + + case VisibilityPartiallyObscured: + refresh_type = SLOW_REFRESH; + break; + + default: + refresh_type = NO_REFRESH; + break; + } + break; + + case FocusIn: + D_EVENTS(("process_x_event(%s)\n", "FocusIn")); + XEVENT_REQUIRE(XEVENT_IS_MYWIN(ev)); + if (!TermWin.focus) { + TermWin.focus = 1; +#ifdef CHANGE_SCROLLCOLOR_ON_FOCUS + menubar_expose(); +#endif + if (Options & Opt_scrollbar_popup) { + map_scrollBar(Options & Opt_scrollBar); + } +#ifndef NO_XLOCALE + if (Input_Context != NULL) + XSetICFocus(Input_Context); +#endif + } + break; + + case FocusOut: + D_EVENTS(("process_x_event(%s)\n", "FocusOut")); + XEVENT_REQUIRE(XEVENT_IS_MYWIN(ev)); + if (TermWin.focus) { + TermWin.focus = 0; +#ifdef CHANGE_SCROLLCOLOR_ON_FOCUS + menubar_expose(); +#endif + if (Options & Opt_scrollbar_popup) { + map_scrollBar(0); + } +#ifndef NO_XLOCALE + if (Input_Context != NULL) + XUnsetICFocus(Input_Context); +#endif + } + break; + + case ConfigureNotify: + D_EVENTS(("process_x_event(%s)\n", "ConfigureNotify")); + XEVENT_REQUIRE(XEVENT_IS_MYWIN(ev)); +#ifdef PIXMAP_OFFSET + if (Options & Opt_pixmapTrans || Options & Opt_viewport_mode) { + render_pixmap(TermWin.vt, imlib_bg, bgPixmap, 0, 2); + scr_expose(0, 0, TermWin_TotalWidth(), TermWin_TotalHeight()); + } +#endif + resize_window(); + menubar_expose(); + break; + + case SelectionClear: + D_EVENTS(("process_x_event(%s)\n", "SelectionClear")); + selection_clear(); + break; + + case SelectionNotify: + D_EVENTS(("process_x_event(%s)\n", "SelectionNotify")); + selection_paste(ev->xselection.requestor, ev->xselection.property, True); + break; + + case SelectionRequest: + D_EVENTS(("process_x_event(%s)\n", "SelectionRequest")); + selection_send(&(ev->xselectionrequest)); + break; + + case GraphicsExpose: + D_EVENTS(("process_x_event(%s)\n", "GraphicsExpose")); + case Expose: + D_EVENTS(("process_x_event(%s)\n", "Expose")); +#ifdef PROFILE_X_EVENTS + P_SETTIMEVAL(expose_start); +#endif + XEVENT_REQUIRE(XEVENT_IS_MYWIN(ev)); + if (ev->xany.window == TermWin.vt) { + scr_expose(ev->xexpose.x, ev->xexpose.y, ev->xexpose.width, ev->xexpose.height); + } else { + + XEvent unused_xevent; + + while (XCheckTypedWindowEvent(Xdisplay, ev->xany.window, Expose, &unused_xevent)); + while (XCheckTypedWindowEvent(Xdisplay, ev->xany.window, GraphicsExpose, &unused_xevent)); + if (isScrollbarWindow(ev->xany.window)) { + scrollbar_setNone(); + scrollbar_show(0); + } +#if (MENUBAR_MAX) + if (menubar_visible() && isMenuBarWindow(ev->xany.window)) { + menubar_expose(); + } +#endif /* MENUBAR_MAX */ + Gr_expose(ev->xany.window); + } +#ifdef WATCH_DESKTOP_OPTION + if (Options & Opt_pixmapTrans && Options & Opt_watchDesktop) { + if (desktop_window != None) { + XSelectInput(Xdisplay, desktop_window, PropertyChangeMask); + } else { + XSelectInput(Xdisplay, Xroot, PropertyChangeMask); + } + } +#endif +#ifdef PROFILE_X_EVENTS + P_SETTIMEVAL(expose_stop); + expose_total += P_CMPTIMEVALS_USEC(expose_start, expose_stop); + fprintf(stderr, "Expose: %ld(%ld) microseconds\n", + P_CMPTIMEVALS_USEC(expose_start, expose_stop), + expose_total); +#endif + break; + + case ButtonPress: + D_EVENTS(("process_x_event(%s)\n", "ButtonPress")); + XEVENT_REQUIRE(XEVENT_IS_MYWIN(ev)); + if (Options & Opt_borderless) { + XSetInputFocus(Xdisplay, Xroot, RevertToNone, CurrentTime); + } +#if defined(CTRL_CLICK_RAISE) || defined(CTRL_CLICK_SCROLLBAR) || defined(CTRL_CLICK_MENU) + if ((ev->xbutton.state & ControlMask) && (ev->xany.window == TermWin.vt)) { + D_EVENTS(("Checking for Ctrl+Button\n")); + switch (ev->xbutton.button) { + case Button1: + D_EVENTS(("Ctrl+Button1\n")); +# ifdef CTRL_CLICK_RAISE + XSetInputFocus(Xdisplay, TermWin.parent, RevertToParent, CurrentTime); + XRaiseWindow(Xdisplay, TermWin.parent); + /*XWarpPointer(Xdisplay, None, TermWin.vt, 0, 0, 0, 0, TermWin.width/2, TermWin.height/2); */ +# endif + break; + case Button2: + D_EVENTS(("Ctrl+Button2\n")); +# ifdef CTRL_CLICK_SCROLLBAR + map_scrollBar(scrollbar_visible()? 0 : 1); +# endif + break; + case Button3: + D_EVENTS(("Ctrl+Button3\n")); +# if defined(CTRL_CLICK_MENU) && (MENUBAR_MAX) + map_menuBar(menubar_visible()? 0 : 1); +# endif + break; + default: + break; + } + break; + } +#endif /* CTRL_CLICK_RAISE || CTRL_CLICK_MENU */ + + bypass_keystate = (ev->xbutton.state & (Mod1Mask | ShiftMask)); + reportmode = (bypass_keystate ? 0 : (PrivateModes & PrivMode_mouse_report)); + + if (ev->xany.window == TermWin.vt) { + if (ev->xbutton.subwindow != None) { + Gr_ButtonPress(ev->xbutton.x, ev->xbutton.y); + } else { + if (reportmode) { + if (reportmode & PrivMode_MouseX10) { + /* no state info allowed */ + ev->xbutton.state = 0; + } +#ifdef MOUSE_REPORT_DOUBLECLICK + if (ev->xbutton.button == Button1) { + if (ev->xbutton.time - buttonpress_time < MULTICLICK_TIME) + clicks++; + else + clicks = 1; + } +#else + clicks = 1; +#endif /* MOUSE_REPORT_DOUBLECLICK */ + mouse_report(&(ev->xbutton)); + } else { +#ifdef USE_ACTIVE_TAGS + if (tag_click(ev->xbutton.x, ev->xbutton.y, ev->xbutton.button, ev->xkey.state)) + activate_time = ev->xbutton.time; + else +#endif + switch (ev->xbutton.button) { + case Button1: + if (lastbutton_press == 1 + && (ev->xbutton.time - buttonpress_time < MULTICLICK_TIME)) + clicks++; + else + clicks = 1; + selection_click(clicks, ev->xbutton.x, ev->xbutton.y); + lastbutton_press = 1; + break; + + case Button3: + if (lastbutton_press == 3 + && (ev->xbutton.time - buttonpress_time < MULTICLICK_TIME)) + selection_rotate(ev->xbutton.x, ev->xbutton.y); + else + selection_extend(ev->xbutton.x, ev->xbutton.y, 1); + lastbutton_press = 3; + break; + } + } + buttonpress_time = ev->xbutton.time; + return; + } + } +#ifdef PIXMAP_SCROLLBAR + if ((isScrollbarWindow(ev->xany.window)) + || (scrollbar_upButtonWin(ev->xany.window)) + || (scrollbar_dnButtonWin(ev->xany.window))) +#else + if (isScrollbarWindow(ev->xany.window)) +#endif + { + scrollbar_setNone(); + /* + * Eterm-style scrollbar: + * move up if mouse is above slider + * move dn if mouse is below slider + * + * XTerm-style scrollbar: + * Move display proportional to pointer location + * pointer near top -> scroll one line + * pointer near bot -> scroll full page + */ +#ifndef NO_SCROLLBAR_REPORT + if (reportmode) { + /* + * Mouse report disabled scrollbar: + * arrow buttons - send up/down + * click on scrollbar - send pageup/down + */ +#ifdef PIXMAP_SCROLLBAR + if ((scrollbar_upButtonWin(ev->xany.window)) + || (!(scrollbar_is_pixmapped()) && + (scrollbar_upButton(ev->xbutton.y)))) +#else + if (scrollbar_upButton(ev->xbutton.y)) +#endif + tt_printf("\033[A"); +#ifdef PIXMAP_SCROLLBAR + else if ((scrollbar_dnButtonWin(ev->xany.window)) + || (!(scrollbar_is_pixmapped()) && + (scrollbar_upButton(ev->xbutton.y)))) +#else + else if (scrollbar_dnButton(ev->xbutton.y)) +#endif + tt_printf("\033[B"); + else + switch (ev->xbutton.button) { + case Button2: + tt_printf("\014"); + break; + case Button1: + tt_printf("\033[6~"); + break; + case Button3: + tt_printf("\033[5~"); + break; + } + } else +#endif /* NO_SCROLLBAR_REPORT */ + { +#ifdef PIXMAP_SCROLLBAR + if ((scrollbar_upButtonWin(ev->xany.window)) + || (!(scrollbar_is_pixmapped()) && + (scrollbar_upButton(ev->xbutton.y)))) +#else + if (scrollbar_upButton(ev->xbutton.y)) +#endif + { +#ifdef SCROLLBAR_BUTTON_CONTINUAL_SCROLLING + scroll_arrow_delay = SCROLLBAR_INITIAL_DELAY; +#endif + if (scr_page(UP, 1)) { + scrollbar_setUp(); + } + } else if +#ifdef PIXMAP_SCROLLBAR + ((scrollbar_dnButtonWin(ev->xany.window)) + || (!(scrollbar_is_pixmapped()) + && (scrollbar_dnButton(ev->xbutton.y)))) +#else + (scrollbar_dnButton(ev->xbutton.y)) +#endif + { +#ifdef SCROLLBAR_BUTTON_CONTINUAL_SCROLLING + scroll_arrow_delay = SCROLLBAR_INITIAL_DELAY; +#endif + if (scr_page(DN, 1)) { + scrollbar_setDn(); + } + } + else + switch (ev->xbutton.button) { + case Button2: + mouseoffset = (scrollBar.bot - scrollBar.top) / 2; /* Align to center */ + if (scrollbar_above_slider(ev->xbutton.y) || scrollbar_below_slider(ev->xbutton.y) + || scrollBar.type == SCROLLBAR_XTERM) { + scr_move_to(scrollbar_position(ev->xbutton.y) - mouseoffset, + scrollbar_size()); + } + scrollbar_setMotion(); + break; + + case Button1: + mouseoffset = ev->xbutton.y - scrollBar.top; + MAX_IT(mouseoffset, 1); + /* drop */ + case Button3: +#if defined(MOTIF_SCROLLBAR) || defined(NEXT_SCROLLBAR) + if (scrollBar.type == SCROLLBAR_MOTIF || scrollBar.type == SCROLLBAR_NEXT) { +# ifdef PIXMAP_SCROLLBAR + if (!(ev->xany.window == scrollBar.sa_win) + && (scrollbar_above_slider(ev->xbutton.y))) +# else + if (scrollbar_above_slider(ev->xbutton.y)) +# endif + scr_page(UP, TermWin.nrow - 1); +# ifdef PIXMAP_SCROLLBAR + else if (!(ev->xany.window == scrollBar.sa_win) + && (scrollbar_below_slider(ev->xbutton.y))) +# else + else + if (scrollbar_below_slider(ev->xbutton.y)) +# endif + scr_page(DN, TermWin.nrow - 1); + else + scrollbar_setMotion(); + } +#endif /* MOTIF_SCROLLBAR || NEXT_SCROLLBAR */ + +#ifdef XTERM_SCROLLBAR + if (scrollBar.type == SCROLLBAR_XTERM) { + scr_page((ev->xbutton.button == Button1 ? DN : UP), + (TermWin.nrow * + scrollbar_position(ev->xbutton.y) / + scrollbar_size()) + ); + } +#endif /* XTERM_SCROLLBAR */ + break; + } + } + return; + } +#if (MENUBAR_MAX) + if (isMenuBarWindow(ev->xany.window)) { + menubar_control(&(ev->xbutton)); + return; + } +#endif /* MENUBAR_MAX */ + break; + + case ButtonRelease: + D_EVENTS(("process_x_event(%s)\n", "ButtonRelease")); + XEVENT_REQUIRE(XEVENT_IS_MYWIN(ev)); + mouseoffset = 0; + reportmode = (bypass_keystate ? + 0 : (PrivateModes & PrivMode_mouse_report)); + + if (scrollbar_isUpDn()) { + scrollbar_setNone(); + scrollbar_show(0); +#ifdef SCROLLBAR_BUTTON_CONTINUAL_SCROLLING +/* refresh_type &= ~SMOOTH_REFRESH; */ +#endif + } + if (ev->xany.window == TermWin.vt) { + if (ev->xbutton.subwindow != None) + Gr_ButtonRelease(ev->xbutton.x, ev->xbutton.y); + else { + if (reportmode) { + switch (reportmode & PrivMode_mouse_report) { + case PrivMode_MouseX10: + break; + + case PrivMode_MouseX11: + ev->xbutton.state = bypass_keystate; + ev->xbutton.button = AnyButton; + mouse_report(&(ev->xbutton)); + break; + } + return; + } + /* + * dumb hack to compensate for the failure of click-and-drag + * when overriding mouse reporting + */ + if ((PrivateModes & PrivMode_mouse_report) && + (bypass_keystate) && + (ev->xbutton.button == Button1) && + (clickOnce())) + selection_extend(ev->xbutton.x, ev->xbutton.y, 0); + + switch (ev->xbutton.button) { + case Button1: + case Button3: +#if defined(CTRL_CLICK_RAISE) || defined(CTRL_CLICK_MENU) + if (!(ev->xbutton.state & ControlMask)) +#endif + selection_make(ev->xbutton.time); + break; + + case Button2: +#ifdef CTRL_CLICK_SCROLLBAR + if (!(ev->xbutton.state & ControlMask)) +#endif + selection_request(ev->xbutton.time, ev->xbutton.x, ev->xbutton.y); + break; + case Button4: + scr_page(UP, (ev->xbutton.state & ShiftMask) ? 1 : 5); + break; + case Button5: + scr_page(DN, (ev->xbutton.state & ShiftMask) ? 1 : 5); + break; + } + } + } +#if (MENUBAR_MAX) + else if (isMenuBarWindow(ev->xany.window)) { + menubar_control(&(ev->xbutton)); + } +#endif /* MENUBAR_MAX */ + break; + + case MotionNotify: + D_EVENTS(("process_x_event(%s)\n", "MotionNotify")); +#ifdef COUNT_X_EVENTS + motion_cnt++; + D_EVENTS(("total number of MotionNotify events: %ld\n", motion_cnt)); +#endif +#ifdef PROFILE_X_EVENTS + P_SETTIMEVAL(motion_start); +#endif + XEVENT_REQUIRE(XEVENT_IS_MYWIN(ev)); +#if (MENUBAR_MAX) + if (isMenuBarWindow(ev->xany.window)) { + menubar_control(&(ev->xbutton)); + break; + } +#endif /* MENUBAR_MAX */ + if ((PrivateModes & PrivMode_mouse_report) && !(bypass_keystate)) + break; + + if (ev->xany.window == TermWin.vt) { + if ((ev->xbutton.state & (Button1Mask | Button3Mask)) +#ifdef USE_ACTIVE_TAGS + && ((ev->xmotion.time - activate_time) > TAG_DRAG_THRESHHOLD) +#endif + ) { + Window unused_root, unused_child; + int unused_root_x, unused_root_y; + unsigned int unused_mask; + + while (XCheckTypedWindowEvent(Xdisplay, TermWin.vt, + MotionNotify, ev)); + XQueryPointer(Xdisplay, TermWin.vt, + &unused_root, &unused_child, + &unused_root_x, &unused_root_y, + &(ev->xbutton.x), &(ev->xbutton.y), + &unused_mask); +#ifdef MOUSE_THRESHOLD + /* deal with a `jumpy' mouse */ + if ((ev->xmotion.time - buttonpress_time) > MOUSE_THRESHOLD) +#endif + selection_extend((ev->xbutton.x), (ev->xbutton.y), + (ev->xbutton.state & Button3Mask)); + } +#ifdef USE_ACTIVE_TAGS + else + tag_pointer_new_position(ev->xbutton.x, ev->xbutton.y); +#endif +#ifdef PIXMAP_SCROLLBAR + } else if ((scrollbar_is_pixmapped()) && (ev->xany.window == scrollBar.sa_win) && scrollbar_isMotion()) { + + Window unused_root, unused_child; + int unused_root_x, unused_root_y; + unsigned int unused_mask; + + /* FIXME: I guess pointer or server should be grabbed here + * or something like that :) -vendu + */ + + while (XCheckTypedWindowEvent(Xdisplay, scrollBar.sa_win, + MotionNotify, ev)); + + XQueryPointer(Xdisplay, scrollBar.sa_win, + &unused_root, &unused_child, + &unused_root_x, &unused_root_y, + &(ev->xbutton.x), &(ev->xbutton.y), + &unused_mask); + + scr_move_to(scrollbar_position(ev->xbutton.y) - mouseoffset, + scrollbar_size()); + refresh_count = refresh_limit = 0; + scr_refresh(refresh_type); + scrollbar_show(mouseoffset); +#endif + } else if ((ev->xany.window == scrollBar.win) && scrollbar_isMotion()) { + Window unused_root, unused_child; + int unused_root_x, unused_root_y; + unsigned int unused_mask; + + while (XCheckTypedWindowEvent(Xdisplay, scrollBar.win, MotionNotify, ev)); + XQueryPointer(Xdisplay, scrollBar.win, + &unused_root, &unused_child, + &unused_root_x, &unused_root_y, + &(ev->xbutton.x), &(ev->xbutton.y), + &unused_mask); + scr_move_to(scrollbar_position(ev->xbutton.y) - mouseoffset, + scrollbar_size()); + refresh_count = refresh_limit = 0; + scr_refresh(refresh_type); + scrollbar_show(mouseoffset); + } +#ifdef PROFILE_X_EVENTS + P_SETTIMEVAL(motion_stop); + fprintf(stderr, "MotionNotify: %ld microseconds\n", + P_CMPTIMEVALS_USEC(motion_start, motion_stop)); +#endif + break; + } +} + +/* tt_write(), tt_printf() - output to command */ +/* + * Send count characters directly to the command + */ +void +tt_write(const unsigned char *buf, unsigned int count) +{ + + v_writeBig(cmd_fd, (char *) buf, count); + +#if 0 /* Fixes the bug that hung Eterm when pasting a lot of stuff */ + while (count > 0) { + int n = write(cmd_fd, buf, count); + + if (n > 0) { + count -= n; + buf += n; + } + } +#endif +} + +/* + * Send printf() formatted output to the command. + * Only use for small ammounts of data. + */ +void +tt_printf(const unsigned char *fmt,...) +{ + static unsigned char buf[256]; + va_list arg_ptr; + + va_start(arg_ptr, fmt); + vsprintf(buf, fmt, arg_ptr); + va_end(arg_ptr); + tt_write(buf, strlen(buf)); +} + + +/* print pipe */ +/*----------------------------------------------------------------------*/ +#ifdef PRINTPIPE +/* PROTO */ +FILE * +popen_printer(void) +{ + FILE *stream = popen(rs_print_pipe, "w"); + + if (stream == NULL) + print_error("can't open printer pipe \"%s\" -- %s", rs_print_pipe, strerror(errno)); + return stream; +} + +/* PROTO */ +int +pclose_printer(FILE * stream) +{ + fflush(stream); + /* pclose() reported not to work on SunOS 4.1.3 */ +# if defined (__sun__) + /* pclose works provided SIGCHLD handler uses waitpid */ + return pclose(stream); /* return fclose (stream); */ +# else + return pclose(stream); +# endif +} + +/* + * simulate attached vt100 printer + */ +/* PROTO */ +void +process_print_pipe(void) +{ + const char *const escape_seq = "\033[4i"; + const char *const rev_escape_seq = "i4[\033"; + int index; + FILE *fd; + + if ((fd = popen_printer()) != NULL) { + for (index = 0; index < 4; /* nil */ ) { + unsigned char ch = cmd_getc(); + + if (ch == escape_seq[index]) + index++; + else if (index) + for ( /*nil */ ; index > 0; index--) + fputc(rev_escape_seq[index - 1], fd); + + if (index == 0) + fputc(ch, fd); + } + pclose_printer(fd); + } +} +#endif /* PRINTPIPE */ + +/* process escape sequences */ +/* PROTO */ +void +process_escape_seq(void) +{ + unsigned char ch = cmd_getc(); + + switch (ch) { + /* case 1: do_tek_mode (); break; */ + case '#': + if (cmd_getc() == '8') + scr_E(); + break; + case '(': + scr_charset_set(0, cmd_getc()); + break; + case ')': + scr_charset_set(1, cmd_getc()); + break; + case '*': + scr_charset_set(2, cmd_getc()); + break; + case '+': + scr_charset_set(3, cmd_getc()); + break; +#ifdef KANJI + case '$': + scr_charset_set(-2, cmd_getc()); + break; +#endif + case '7': + scr_cursor(SAVE); + break; + case '8': + scr_cursor(RESTORE); + break; + case '=': + case '>': + PrivMode((ch == '='), PrivMode_aplKP); + break; + case '@': + (void) cmd_getc(); + break; + case 'D': + scr_index(UP); + break; + case 'E': + scr_add_lines("\n\r", 1, 2); + break; + case 'G': + process_graphics(); + break; + case 'H': + scr_set_tab(1); + break; + case 'M': + scr_index(DN); + break; + /*case 'N': scr_single_shift (2); break; */ + /*case 'O': scr_single_shift (3); break; */ + case 'Z': + tt_printf(ESCZ_ANSWER); + break; /* steal obsolete ESC [ c */ + case '[': + process_csi_seq(); + break; + case ']': + process_xterm_seq(); + break; + case 'c': + scr_poweron(); + break; + case 'n': + scr_charset_choose(2); + break; + case 'o': + scr_charset_choose(3); + break; + } +} + +/* process CSI (code sequence introducer) sequences `ESC[' */ +/* PROTO */ +void +process_csi_seq(void) +{ + + unsigned char ch, priv; + unsigned int nargs; + int arg[ESC_ARGS]; + + nargs = 0; + arg[0] = 0; + arg[1] = 0; + + priv = 0; + ch = cmd_getc(); + if (ch >= '<' && ch <= '?') { + priv = ch; + ch = cmd_getc(); + } + /* read any numerical arguments */ + do { + int n; + + for (n = 0; isdigit(ch); ch = cmd_getc()) + n = n * 10 + (ch - '0'); + + if (nargs < ESC_ARGS) + arg[nargs++] = n; + if (ch == '\b') { + scr_backspace(); + } else if (ch == 033) { + process_escape_seq(); + return; + } else if (ch < ' ') { + scr_add_lines(&ch, 0, 1); + return; + } + if (ch < '@') + ch = cmd_getc(); + } + while (ch >= ' ' && ch < '@'); + if (ch == 033) { + process_escape_seq(); + return; + } else if (ch < ' ') + return; + + switch (ch) { +#ifdef PRINTPIPE + case 'i': /* printing */ + switch (arg[0]) { + case 0: + scr_printscreen(0); + break; + case 5: + process_print_pipe(); + break; + } + break; +#endif + case 'A': + case 'e': /* up */ + scr_gotorc((arg[0] ? -arg[0] : -1), 0, RELATIVE); + break; + case 'B': /* down */ + scr_gotorc((arg[0] ? +arg[0] : +1), 0, RELATIVE); + break; + case 'C': + case 'a': /* right */ + scr_gotorc(0, (arg[0] ? +arg[0] : +1), RELATIVE); + break; + case 'D': /* left */ + scr_gotorc(0, (arg[0] ? -arg[0] : -1), RELATIVE); + break; + case 'E': /* down & to first column */ + scr_gotorc((arg[0] ? +arg[0] : +1), 0, R_RELATIVE); + break; + case 'F': /* up & to first column */ + scr_gotorc((arg[0] ? -arg[0] : -1), 0, R_RELATIVE); + break; + case 'G': + case '`': /* move to col */ + scr_gotorc(0, (arg[0] ? arg[0] - 1 : +1), R_RELATIVE); + break; + case 'd': /* move to row */ + scr_gotorc((arg[0] ? arg[0] - 1 : +1), 0, C_RELATIVE); + break; + case 'H': + case 'f': /* position cursor */ + switch (nargs) { + case 0: + scr_gotorc(0, 0, 0); + break; + case 1: + scr_gotorc((arg[0] ? arg[0] - 1 : 0), 0, 0); + break; + default: + scr_gotorc(arg[0] - 1, arg[1] - 1, 0); + break; + } + break; + case 'I': + scr_tab(arg[0] ? +arg[0] : +1); + break; + case 'Z': + scr_tab(arg[0] ? -arg[0] : -1); + break; + case 'J': + scr_erase_screen(arg[0]); + break; + case 'K': + scr_erase_line(arg[0]); + break; + case '@': + scr_insdel_chars((arg[0] ? arg[0] : 1), INSERT); + break; + case 'L': + scr_insdel_lines((arg[0] ? arg[0] : 1), INSERT); + break; + case 'M': + scr_insdel_lines((arg[0] ? arg[0] : 1), DELETE); + break; + case 'X': + scr_insdel_chars((arg[0] ? arg[0] : 1), ERASE); + break; + case 'P': + scr_insdel_chars((arg[0] ? arg[0] : 1), DELETE); + break; + + case 'c': +#ifndef NO_VT100_ANS + tt_printf(VT100_ANS); +#endif + break; + case 'm': + process_sgr_mode(nargs, arg); + break; + case 'n': /* request for information */ + switch (arg[0]) { + case 5: + tt_printf("\033[0n"); + break; /* ready */ + case 6: + scr_report_position(); + break; +#if defined (ENABLE_DISPLAY_ANSWER) + case 7: + tt_printf("%s\n", display_name); + break; +#endif + case 8: + xterm_seq(XTerm_title, APL_NAME "-" VERSION); + break; + case 9: +#ifdef PIXMAP_OFFSET + if (Options & Opt_pixmapTrans) { + char tbuff[70]; + + snprintf(tbuff, sizeof(tbuff), APL_NAME "-" VERSION ": Transparent - %d%% shading - 0x%06x tint mask", + rs_shadePct, rs_tintMask); + xterm_seq(XTerm_title, tbuff); + } else +#endif +#ifdef PIXMAP_SUPPORT + { + char *tbuff; + unsigned short len; + + if (imlib_bg.im) { + len = strlen(imlib_bg.im->filename) + sizeof(APL_NAME) + sizeof(VERSION) + 5; + tbuff = MALLOC(len); + snprintf(tbuff, len, APL_NAME "-" VERSION ": %s", imlib_bg.im->filename); + xterm_seq(XTerm_title, tbuff); + FREE(tbuff); + } else { + xterm_seq(XTerm_title, APL_NAME "-" VERSION ": No Pixmap"); + } + } +#endif /* PIXMAP_SUPPORT */ + break; + } + break; + case 'r': /* set top and bottom margins */ + if (priv != '?') { + if (nargs < 2 || arg[0] >= arg[1]) + scr_scroll_region(0, 10000); + else + scr_scroll_region(arg[0] - 1, arg[1] - 1); + break; + } + /* drop */ + case 't': + if (priv != '?') { + process_window_mode(nargs, arg); + break; + } + /* drop */ + case 's': + case 'h': + case 'l': + process_terminal_mode(ch, priv, nargs, arg); + break; + case 'g': + switch (arg[0]) { + case 0: + scr_set_tab(0); + break; /* delete tab */ + case 3: + scr_set_tab(-1); + break; /* clear all tabs */ + } + break; + case 'W': + switch (arg[0]) { + case 0: + scr_set_tab(1); + break; /* = ESC H */ + case 2: + scr_set_tab(0); + break; /* = ESC [ 0 g */ + case 5: + scr_set_tab(-1); + break; /* = ESC [ 3 g */ + } + break; + } +} + +/* process xterm text parameters sequences `ESC ] Ps ; Pt BEL' */ +/* PROTO */ +void +process_xterm_seq(void) +{ + unsigned char ch, string[STRING_MAX]; + int arg; + + ch = cmd_getc(); + if (isdigit(ch)) { + for (arg = 0; isdigit(ch); ch = cmd_getc()) { + arg = arg * 10 + (ch - '0'); + } + } else if (ch == ';') { + arg = 0; + } else { + arg = ch; + ch = cmd_getc(); + } + if (ch == ';') { + int n = 0; + + while ((ch = cmd_getc()) != 007) { + if (ch) { + if (ch == '\t') + ch = ' '; /* translate '\t' to space */ + else if (ch < ' ') + return; /* control character - exit */ + + if (n < sizeof(string) - 1) + string[n++] = ch; + } + } + string[n] = '\0'; + + /* + * menubar_dispatch() violates the constness of the string, + * so do it here + */ + if (arg == XTerm_Menu) + menubar_dispatch(string); + else + xterm_seq(arg, string); + } else { + int n = 0; + + for (; ch != '\e'; ch = cmd_getc()) { + if (ch) { + if (ch == '\t') + ch = ' '; /* translate '\t' to space */ + else if (ch < ' ') + return; /* control character - exit */ + + if (n < sizeof(string) - 1) + string[n++] = ch; + } + } + string[n] = '\0'; + + if ((ch = cmd_getc()) != '\\') { + return; + } + switch (arg) { + case 'l': + xterm_seq(XTerm_title, string); + break; + case 'L': + xterm_seq(XTerm_iconName, string); + break; + case 'I': + set_icon_pixmap(string, NULL); + break; + default: + break; + } + } +} + +/* Process window manipulations */ +void +process_window_mode(unsigned int nargs, int args[]) +{ + + register unsigned int i; + unsigned int x, y; + Screen *scr; + Window dummy_child; + char buff[128], *name; + + if (!nargs) + return; + scr = ScreenOfDisplay(Xdisplay, Xscreen); + if (!scr) + return; + + for (i = 0; i < nargs; i++) { + if (args[i] == 14) { + int dummy_x, dummy_y; + unsigned int dummy_border, dummy_depth; + + /* Store current width and height in x and y */ + XGetGeometry(Xdisplay, TermWin.parent, &dummy_child, &dummy_x, &dummy_y, &x, &y, &dummy_border, &dummy_depth); + } + switch (args[i]) { + case 1: + XRaiseWindow(Xdisplay, TermWin.parent); + break; + case 2: + XIconifyWindow(Xdisplay, TermWin.parent, Xscreen); + break; + case 3: + if (i + 2 >= nargs) + return; /* Make sure there are 2 args left */ + x = args[++i]; + y = args[++i]; + if (x > scr->width || y > scr->height) + return; /* Don't move off-screen */ + XMoveWindow(Xdisplay, TermWin.parent, x, y); + break; + case 4: + if (i + 2 >= nargs) + return; /* Make sure there are 2 args left */ + y = args[++i]; + x = args[++i]; + XResizeWindow(Xdisplay, TermWin.parent, x, y); + break; + case 5: + XRaiseWindow(Xdisplay, TermWin.parent); + break; + case 6: + XLowerWindow(Xdisplay, TermWin.parent); + break; + case 7: + XClearWindow(Xdisplay, TermWin.vt); + XSync(Xdisplay, False); + scr_touch(); + scr_refresh(SMOOTH_REFRESH); + break; + case 8: + if (i + 2 >= nargs) + return; /* Make sure there are 2 args left */ + y = args[++i]; + x = args[++i]; + XResizeWindow(Xdisplay, TermWin.parent, + Width2Pixel(x) + 2 * TermWin.internalBorder + (scrollbar_visible()? scrollbar_total_width() : 0), + Height2Pixel(y) + 2 * TermWin.internalBorder + (menubar_visible()? menuBar_TotalHeight() : 0)); + break; + case 11: + break; + case 13: + XTranslateCoordinates(Xdisplay, TermWin.parent, Xroot, 0, 0, &x, &y, &dummy_child); + snprintf(buff, sizeof(buff), "\e[3;%d;%dt", x, y); + tt_write(buff, strlen(buff)); + break; + case 14: + snprintf(buff, sizeof(buff), "\e[4;%d;%dt", y, x); + tt_write(buff, strlen(buff)); + break; + case 18: + snprintf(buff, sizeof(buff), "\e[8;%d;%dt", TermWin.nrow, TermWin.ncol); + tt_write(buff, strlen(buff)); + break; + case 20: + XGetIconName(Xdisplay, TermWin.parent, &name); + snprintf(buff, sizeof(buff), "\e]L%s\e\\", name); + tt_write(buff, strlen(buff)); + XFree(name); + break; + case 21: + XFetchName(Xdisplay, TermWin.parent, &name); + snprintf(buff, sizeof(buff), "\e]l%s\e\\", name); + tt_write(buff, strlen(buff)); + XFree(name); + break; + default: + break; + } + } +} + +/* process DEC private mode sequences `ESC [ ? Ps mode' */ +/* + * mode can only have the following values: + * 'l' = low + * 'h' = high + * 's' = save + * 'r' = restore + * 't' = toggle + * so no need for fancy checking + */ +/* PROTO */ +void +process_terminal_mode(int mode, int priv, unsigned int nargs, int arg[]) +{ + unsigned int i; + int state; + + if (nargs == 0) + return; + + /* make lo/hi boolean */ + switch (mode) { + case 'l': + mode = 0; + break; + case 'h': + mode = 1; + break; + } + + switch (priv) { + case 0: + if (mode && mode != 1) + return; /* only do high/low */ + for (i = 0; i < nargs; i++) + switch (arg[i]) { + case 4: + scr_insert_mode(mode); + break; + /* case 38: TEK mode */ + } + break; + +#define PrivCases(bit) \ +if (mode == 't') state = !(PrivateModes & bit); else state = mode;\ +switch (state) {\ +case 's': SavedModes |= (PrivateModes & bit); continue; break;\ +case 'r': state = (SavedModes & bit) ? 1 : 0;/*drop*/\ +default: PrivMode (state, bit); } + + case '?': + for (i = 0; i < nargs; i++) + switch (arg[i]) { + case 1: /* application cursor keys */ + PrivCases(PrivMode_aplCUR); + break; + + /* case 2: - reset charsets to USASCII */ + + case 3: /* 80/132 */ + PrivCases(PrivMode_132); + if (PrivateModes & PrivMode_132OK) + set_width(state ? 132 : 80); + break; + + /* case 4: - smooth scrolling */ + + case 5: /* reverse video */ + PrivCases(PrivMode_rVideo); + scr_rvideo_mode(state); + break; + + case 6: /* relative/absolute origins */ + PrivCases(PrivMode_relOrigin); + scr_relative_origin(state); + break; + + case 7: /* autowrap */ + PrivCases(PrivMode_Autowrap); + scr_autowrap(state); + break; + + /* case 8: - auto repeat, can't do on a per window basis */ + + case 9: /* X10 mouse reporting */ + PrivCases(PrivMode_MouseX10); + /* orthogonal */ + if (PrivateModes & PrivMode_MouseX10) + PrivateModes &= ~(PrivMode_MouseX11); + break; + +#if (MENUBAR_MAX) +# ifdef menuBar_esc + case menuBar_esc: + PrivCases(PrivMode_menuBar); + map_menuBar(state); + break; +# endif +#endif /* MENUBAR_MAX */ + +#ifdef scrollBar_esc + case scrollBar_esc: + PrivCases(PrivMode_scrollBar); + map_scrollBar(state); + break; +#endif + case 25: /* visible/invisible cursor */ + PrivCases(PrivMode_VisibleCursor); + scr_cursor_visible(state); + break; + + case 35: + PrivCases(PrivMode_ShiftKeys); + break; + + case 40: /* 80 <--> 132 mode */ + PrivCases(PrivMode_132OK); + break; + + case 47: /* secondary screen */ + PrivCases(PrivMode_Screen); + scr_change_screen(state); + break; + + case 66: /* application key pad */ + PrivCases(PrivMode_aplKP); + break; + + case 67: + PrivCases(PrivMode_BackSpace); + break; + + case 1000: /* X11 mouse reporting */ + PrivCases(PrivMode_MouseX11); + /* orthogonal */ + if (PrivateModes & PrivMode_MouseX11) + PrivateModes &= ~(PrivMode_MouseX10); + break; + +#if 0 + case 1001: + break; /* X11 mouse highlighting */ +#endif + case 1010: /* Scroll to bottom on TTY output */ + if (Options & Opt_homeOnEcho) + Options &= ~Opt_homeOnEcho; + else + Options |= Opt_homeOnEcho; + break; + case 1011: /* scroll to bottom on refresh */ + if (Options & Opt_homeOnRefresh) + Options &= ~Opt_homeOnRefresh; + else + Options |= Opt_homeOnRefresh; + break; + case 1012: /* Scroll to bottom on TTY input */ + if (Options & Opt_homeOnInput) + Options &= ~Opt_homeOnInput; + else + Options |= Opt_homeOnInput; + break; + } +#undef PrivCases + break; + } +} + +/* process sgr sequences */ +/* PROTO */ +void +process_sgr_mode(unsigned int nargs, int arg[]) +{ + unsigned int i; + + if (nargs == 0) { + scr_rendition(0, ~RS_None); + return; + } + for (i = 0; i < nargs; i++) + switch (arg[i]) { + case 0: + scr_rendition(0, ~RS_None); + break; + case 1: + scr_rendition(1, RS_Bold); + break; + case 4: + scr_rendition(1, RS_Uline); + break; + case 5: + scr_rendition(1, RS_Blink); + break; + case 7: + scr_rendition(1, RS_RVid); + break; + case 22: + scr_rendition(0, RS_Bold); + break; + case 24: + scr_rendition(0, RS_Uline); + break; + case 25: + scr_rendition(0, RS_Blink); + break; + case 27: + scr_rendition(0, RS_RVid); + break; + + case 30: + case 31: /* set fg color */ + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + scr_color(minColor + (arg[i] - 30), RS_Bold); + break; + case 39: /* default fg */ + scr_color(restoreFG, RS_Bold); + break; + + case 40: + case 41: /* set bg color */ + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + scr_color(minColor + (arg[i] - 40), RS_Blink); + break; + case 49: /* default bg */ + scr_color(restoreBG, RS_Blink); + break; + } +} + +/* process Rob Nation's own graphics mode sequences */ +/* PROTO */ +void +process_graphics(void) +{ + unsigned char ch, cmd = cmd_getc(); + +#ifndef RXVT_GRAPHICS + if (cmd == 'Q') { /* query graphics */ + tt_printf("\033G0\n"); /* no graphics */ + return; + } + /* swallow other graphics sequences until terminating ':' */ + do + ch = cmd_getc(); + while (ch != ':'); +#else + int nargs; + int args[NGRX_PTS]; + unsigned char *text = NULL; + + if (cmd == 'Q') { /* query graphics */ + tt_printf("\033G1\n"); /* yes, graphics (color) */ + return; + } + for (nargs = 0; nargs < (sizeof(args) / sizeof(args[0])) - 1; /*nil */ ) { + int neg; + + ch = cmd_getc(); + neg = (ch == '-'); + if (neg || ch == '+') + ch = cmd_getc(); + + for (args[nargs] = 0; isdigit(ch); ch = cmd_getc()) + args[nargs] = args[nargs] * 10 + (ch - '0'); + if (neg) + args[nargs] = -args[nargs]; + + nargs++; + args[nargs] = 0; + if (ch != ';') + break; + } + + if ((cmd == 'T') && (nargs >= 5)) { + int i, len = args[4]; + + text = MALLOC((len + 1) * sizeof(char)); + + if (text != NULL) { + for (i = 0; i < len; i++) + text[i] = cmd_getc(); + text[len] = '\0'; + } + } + Gr_do_graphics(cmd, nargs, args, text); +#endif +} + +#ifndef USE_POSIX_THREADS +/* Read and process output from the application */ + +void +main_loop(void) +{ + /* int ch; */ + register int ch; + + D_CMD(("[%d] main_loop() called\n", getpid())); + +#ifdef BACKGROUND_CYCLING_SUPPORT + if (rs_anim_delay) { + check_pixmap_change(0); + } +#endif + do { + while ((ch = cmd_getc()) == 0); /* wait for something */ + if (ch >= ' ' || ch == '\t' || ch == '\n' || ch == '\r') { + /* Read a text string from the input buffer */ + int nlines = 0; + + /* unsigned char * str; */ + register unsigned char *str; + + /* + * point to the start of the string, + * decrement first since already did get_com_char () + */ + str = --cmdbuf_ptr; + while (cmdbuf_ptr < cmdbuf_endp) { + + ch = *cmdbuf_ptr++; + if (ch >= ' ' || ch == '\t' || ch == '\r') { + /* nothing */ + } else if (ch == '\n') { + nlines++; + if (++refresh_count >= (refresh_limit * (TermWin.nrow - 1))) + break; + } else { /* unprintable */ + cmdbuf_ptr--; + break; + } + } + D_SCREEN(("Adding lines, str == 0x%08x, cmdbuf_ptr == 0x%08x, cmdbuf_endp == 0x%08x\n", str, cmdbuf_ptr, + cmdbuf_endp)); + D_SCREEN(("Command buffer base == 0x%08x, length %lu, end at 0x%08x\n", cmdbuf_base, CMD_BUF_SIZE, + cmdbuf_base + CMD_BUF_SIZE - 1)); + scr_add_lines(str, nlines, (cmdbuf_ptr - str)); + } else { + switch (ch) { +# ifdef NO_VT100_ANS + case 005: + break; +# else + case 005: + tt_printf(VT100_ANS); + break; /* terminal Status */ +# endif + case 007: + scr_bell(); + break; /* bell */ + case '\b': + scr_backspace(); + break; /* backspace */ + case 013: + case 014: + scr_index(UP); + break; /* vertical tab, form feed */ + case 016: + scr_charset_choose(1); + break; /* shift out - acs */ + case 017: + scr_charset_choose(0); + break; /* shift in - acs */ + case 033: + process_escape_seq(); + break; + } + } + } while (ch != EOF); +} +#endif + +/* Addresses pasting large amounts of data + * code pinched from xterm + */ + +static char *v_buffer; /* pointer to physical buffer */ +static char *v_bufstr = NULL; /* beginning of area to write */ +static char *v_bufptr; /* end of area to write */ +static char *v_bufend; /* end of physical buffer */ + +/* output a burst of any pending data from a paste... */ +static int +v_doPending() +{ + + if (v_bufstr >= v_bufptr) + return (0); + v_writeBig(cmd_fd, NULL, 0); + return (1); +} + +/* Write data to the pty as typed by the user, pasted with the mouse, + * or generated by us in response to a query ESC sequence. + * Code stolen from xterm + */ +static void +v_writeBig(int f, char *d, int len) +{ + + int written; + int c = len; + + if (v_bufstr == NULL && len > 0) { + + v_buffer = malloc(len); + v_bufstr = v_buffer; + v_bufptr = v_buffer; + v_bufend = v_buffer + len; + } + /* + * Append to the block we already have. + * Always doing this simplifies the code, and + * isn't too bad, either. If this is a short + * block, it isn't too expensive, and if this is + * a long block, we won't be able to write it all + * anyway. + */ + + if (len > 0) { + if (v_bufend < v_bufptr + len) { /* we've run out of room */ + if (v_bufstr != v_buffer) { + /* there is unused space, move everything down */ + /* possibly overlapping bcopy here */ + + /* bcopy(v_bufstr, v_buffer, v_bufptr - v_bufstr); */ + memcpy(v_buffer, v_bufstr, v_bufptr - v_bufstr); + v_bufptr -= v_bufstr - v_buffer; + v_bufstr = v_buffer; + } + if (v_bufend < v_bufptr + len) { + /* still won't fit: get more space */ + /* Don't use XtRealloc because an error is not fatal. */ + int size = v_bufptr - v_buffer; /* save across realloc */ + + v_buffer = realloc(v_buffer, size + len); + if (v_buffer) { + v_bufstr = v_buffer; + v_bufptr = v_buffer + size; + v_bufend = v_bufptr + len; + } else { + /* no memory: ignore entire write request */ + print_error("cannot allocate buffer space\n"); + v_buffer = v_bufstr; /* restore clobbered pointer */ + c = 0; + } + } + } + if (v_bufend >= v_bufptr + len) { /* new stuff will fit */ + memcpy(v_bufptr, d, len); /* bcopy(d, v_bufptr, len); */ + v_bufptr += len; + } + } + /* + * Write out as much of the buffer as we can. + * Be careful not to overflow the pty's input silo. + * We are conservative here and only write + * a small amount at a time. + * + * If we can't push all the data into the pty yet, we expect write + * to return a non-negative number less than the length requested + * (if some data written) or -1 and set errno to EAGAIN, + * EWOULDBLOCK, or EINTR (if no data written). + * + * (Not all systems do this, sigh, so the code is actually + * a little more forgiving.) + */ + +#if defined(linux) +# ifdef PTY_BUF_SIZE /* From */ +# define MAX_PTY_WRITE PTY_BUF_SIZE +# endif +#endif + +/* NOTE: _POSIX_MAX_INPUT is defined _through_ at least for + * the following systems: HP-UX 10.20, AIX (no idea about the version), + * OSF1/alpha 4.0, Linux (probably any Linux system). + */ +#ifndef MAX_PTY_WRITE +# ifdef _POSIX_VERSION +# ifdef _POSIX_MAX_INPUT +# define MAX_PTY_WRITE _POSIX_MAX_INPUT +# else +# define MAX_PTY_WRITE 255 /* POSIX minimum MAX_INPUT */ +# endif +# endif +#endif + +#ifndef MAX_PTY_WRITE +# define MAX_PTY_WRITE 128 /* 1/2 POSIX minimum MAX_INPUT */ +#endif + + if (v_bufptr > v_bufstr) { + written = write(f, v_bufstr, v_bufptr - v_bufstr <= MAX_PTY_WRITE ? + v_bufptr - v_bufstr : MAX_PTY_WRITE); + if (written < 0) { + written = 0; + } + D_TTY(("v_writeBig(): Wrote %d characters\n", written)); + v_bufstr += written; + if (v_bufstr >= v_bufptr) /* we wrote it all */ + v_bufstr = v_bufptr = v_buffer; + } + /* + * If we have lots of unused memory allocated, return it + */ + if (v_bufend - v_bufptr > 1024) { /* arbitrary hysteresis */ + /* save pointers across realloc */ + int start = v_bufstr - v_buffer; + int size = v_bufptr - v_buffer; + int allocsize = size ? size : 1; + + v_buffer = realloc(v_buffer, allocsize); + if (v_buffer) { + v_bufstr = v_buffer + start; + v_bufptr = v_buffer + size; + v_bufend = v_buffer + allocsize; + } else { + /* should we print a warning if couldn't return memory? */ + v_buffer = v_bufstr - start; /* restore clobbered pointer */ + } + } +} + +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +XErrorHandler +xerror_handler(Display * display, XErrorEvent * event) +{ + + char err_string[2048]; + extern char *XRequest, *XlibMessage; + + strcpy(err_string, ""); + XGetErrorText(Xdisplay, event->error_code, err_string, sizeof(err_string)); + print_error("XError in function %s (request %d.%d): %s (error %d)", request_code_to_name(event->request_code), + event->request_code, event->minor_code, err_string, event->error_code); +#if DEBUG > DEBUG_X11 + if (debug_level >= DEBUG_X11) { + dump_stack_trace(); + } +#endif + print_error("Attempting to continue..."); + return 0; +} + +/* color aliases, fg/bg bright-bold */ +/*static inline void */ +/* inline void */ +void +color_aliases(int idx) +{ + + if (rs_color[idx] && isdigit(*rs_color[idx])) { + + int i = atoi(rs_color[idx]); + + if (i >= 8 && i <= 15) { /* bright colors */ + i -= 8; +#ifndef NO_BRIGHTCOLOR + rs_color[idx] = rs_color[minBright + i]; + return; +#endif + } + if (i >= 0 && i <= 7) /* normal colors */ + rs_color[idx] = rs_color[minColor + i]; + } +} + +/* + * find if fg/bg matches any of the normal (low-intensity) colors + */ +#ifndef NO_BRIGHTCOLOR +static inline void +set_colorfgbg(void) +{ + unsigned int i; + static char *colorfgbg_env = NULL; + char *p; + int fg = -1, bg = -1; + + if (!colorfgbg_env) { + colorfgbg_env = (char *) malloc(30); + strcpy(colorfgbg_env, "COLORFGBG=default;default;bg"); + } + for (i = BlackColor; i <= WhiteColor; i++) { + if (PixColors[fgColor] == PixColors[i]) { + fg = (i - BlackColor); + break; + } + } + for (i = BlackColor; i <= WhiteColor; i++) { + if (PixColors[bgColor] == PixColors[i]) { + bg = (i - BlackColor); + break; + } + } + + p = strchr(colorfgbg_env, '='); + p++; + if (fg >= 0) + sprintf(p, "%d;", fg); + else + strcpy(p, "default;"); + p = strchr(p, '\0'); + if (bg >= 0) + sprintf(p, +# ifdef PIXMAP_SUPPORT + "default;" +# endif + "%d", bg); + else + strcpy(p, "default"); + putenv(colorfgbg_env); + + colorfgbg = DEFAULT_RSTYLE; + for (i = minColor; i <= maxColor; i++) { + if (PixColors[fgColor] == PixColors[i] +# ifndef NO_BOLDUNDERLINE + && PixColors[fgColor] == PixColors[colorBD] +# endif /* NO_BOLDUNDERLINE */ + /* if we wanted boldFont to have precedence */ +# if 0 /* ifndef NO_BOLDFONT */ + && TermWin.boldFont == NULL +# endif /* NO_BOLDFONT */ + ) + colorfgbg = SET_FGCOLOR(colorfgbg, i); + if (PixColors[bgColor] == PixColors[i]) + colorfgbg = SET_BGCOLOR(colorfgbg, i); + } +} +#else /* NO_BRIGHTCOLOR */ +# define set_colorfgbg() ((void)0) +#endif /* NO_BRIGHTCOLOR */ + +/* Create_Windows() - Open and map the window */ +void +Create_Windows(int argc, char *argv[]) +{ + + Cursor cursor; + XClassHint classHint; + XWMHints wmHint; + Atom prop; + CARD32 val; + int i, x, y, flags; + unsigned int width, height; + unsigned int r, g, b; + MWMHints mwmhints; + +/* char *tmp; */ + + if (Options & Opt_borderless) { + prop = XInternAtom(Xdisplay, "_MOTIF_WM_HINTS", True); + if (prop == None) { + print_warning("Window Manager does not support MWM hints. Bypassing window manager control for borderless window."); + Attributes.override_redirect = TRUE; + mwmhints.flags = 0; + } else { + mwmhints.flags = MWM_HINTS_DECORATIONS; + mwmhints.decorations = 0; + } + } + Attributes.save_under = TRUE; + Attributes.backing_store = WhenMapped; + + /* + * grab colors before netscape does + */ + for (i = 0; i < (Xdepth <= 2 ? 2 : NRS_COLORS); i++) { + + XColor xcol; + unsigned char found_color; + + if (!rs_color[i]) + continue; + + if (!XParseColor(Xdisplay, Xcmap, rs_color[i], &xcol)) { + print_warning("Unable to resolve \"%s\" as a color name. Falling back on \"%s\".", + rs_color[i], def_colorName[i] ? def_colorName[i] : "(nil)"); + rs_color[i] = def_colorName[i]; + if (!rs_color[i]) + continue; + if (!XParseColor(Xdisplay, Xcmap, rs_color[i], &xcol)) { + print_warning("Unable to resolve \"%s\" as a color name. This should never fail. Please repair/restore your RGB database.", rs_color[i]); + found_color = 0; + } else { + found_color = 1; + } + } else { + found_color = 1; + } + if (found_color) { + r = xcol.red; + g = xcol.green; + b = xcol.blue; + xcol.pixel = Imlib_best_color_match(imlib_id, &r, &g, &b); + if (!XAllocColor(Xdisplay, Xcmap, &xcol)) { + print_warning("Unable to allocate \"%s\" (0x%08x: 0x%04x, 0x%04x, 0x%04x) in the color map. " + "Falling back on \"%s\".", + rs_color[i], xcol.pixel, r, g, b, def_colorName[i] ? def_colorName[i] : "(nil)"); + rs_color[i] = def_colorName[i]; + if (!rs_color[i]) + continue; + if (!XAllocColor(Xdisplay, Xcmap, &xcol)) { + print_warning("Unable to allocate \"%s\" (0x%08x: 0x%04x, 0x%04x, 0x%04x) in the color map.", + rs_color[i], xcol.pixel, r, g, b); + found_color = 0; + } else { + found_color = 1; + } + } else { + found_color = 1; + } + } + if (!found_color) { + switch (i) { + case fgColor: + case bgColor: + /* fatal: need bg/fg color */ + fatal_error("Unable to get foreground/background colors!"); + break; +#ifndef NO_CURSORCOLOR + case cursorColor: + xcol.pixel = PixColors[bgColor]; + break; + case cursorColor2: + xcol.pixel = PixColors[fgColor]; + break; +#endif /* NO_CURSORCOLOR */ + default: + xcol.pixel = PixColors[bgColor]; /* None */ + break; + } + } + PixColors[i] = xcol.pixel; + } + +#ifndef NO_CURSORCOLOR + if (Xdepth <= 2 || !rs_color[cursorColor]) + PixColors[cursorColor] = PixColors[bgColor]; + if (Xdepth <= 2 || !rs_color[cursorColor2]) + PixColors[cursorColor2] = PixColors[fgColor]; +#endif /* NO_CURSORCOLOR */ + if (Xdepth <= 2 || !rs_color[pointerColor]) + PixColors[pointerColor] = PixColors[fgColor]; + if (Xdepth <= 2 || !rs_color[borderColor]) + PixColors[borderColor] = PixColors[bgColor]; + +#ifndef NO_BOLDUNDERLINE + if (Xdepth <= 2 || !rs_color[colorBD]) + PixColors[colorBD] = PixColors[fgColor]; + if (Xdepth <= 2 || !rs_color[colorUL]) + PixColors[colorUL] = PixColors[fgColor]; +#endif /* NO_BOLDUNDERLINE */ + + /* + * get scrollBar/menuBar shadow colors + * + * The calculations of topShadow/bottomShadow values are adapted + * from the fvwm window manager. + */ +#ifdef KEEP_SCROLLCOLOR + if (Xdepth <= 2) { /* Monochrome */ + PixColors[scrollColor] = PixColors[bgColor]; + PixColors[topShadowColor] = PixColors[fgColor]; + PixColors[bottomShadowColor] = PixColors[fgColor]; + +# ifdef CHANGE_SCROLLCOLOR_ON_FOCUS + PixColors[unfocusedScrollColor] = PixColors[bgColor]; + PixColors[unfocusedTopShadowColor] = PixColors[fgColor]; + PixColors[unfocusedBottomShadowColor] = PixColors[fgColor]; +# endif + + } else { + + XColor xcol, white; + + /* bottomShadowColor */ + xcol.pixel = PixColors[scrollColor]; + XQueryColor(Xdisplay, Xcmap, &xcol); + + xcol.red /= 2; + xcol.green /= 2; + xcol.blue /= 2; + r = xcol.red; + g = xcol.green; + b = xcol.blue; + xcol.pixel = Imlib_best_color_match(imlib_id, &r, &g, &b); + + if (!XAllocColor(Xdisplay, Xcmap, &xcol)) { + print_error("Unable to allocate \"bottomShadowColor\" (0x%08x: 0x%04x, 0x%04x, 0x%04x) in the color map.", + xcol.pixel, r, g, b); + xcol.pixel = PixColors[minColor]; + } + PixColors[bottomShadowColor] = xcol.pixel; + +#ifdef CHANGE_SCROLLCOLOR_ON_FOCUS + /* unfocusedBottomShadowColor */ + xcol.pixel = PixColors[unfocusedScrollColor]; + XQueryColor(Xdisplay, Xcmap, &xcol); + + xcol.red /= 2; + xcol.green /= 2; + xcol.blue /= 2; + r = xcol.red; + g = xcol.green; + b = xcol.blue; + xcol.pixel = Imlib_best_color_match(imlib_id, &r, &g, &b); + + if (!XAllocColor(Xdisplay, Xcmap, &xcol)) { + print_error("Unable to allocate \"unfocusedbottomShadowColor\" (0x%08x: 0x%04x, 0x%04x, 0x%04x) in the color map.", + xcol.pixel, r, g, b); + xcol.pixel = PixColors[minColor]; + } + PixColors[unfocusedBottomShadowColor] = xcol.pixel; +#endif + + /* topShadowColor */ +# ifdef PREFER_24BIT + white.red = white.green = white.blue = r = g = b = ~0; + white.pixel = Imlib_best_color_match(imlib_id, &r, &g, &b); + XAllocColor(Xdisplay, Xcmap, &white); +# else + white.pixel = WhitePixel(Xdisplay, Xscreen); + XQueryColor(Xdisplay, Xcmap, &white); +# endif + + xcol.pixel = PixColors[scrollColor]; + XQueryColor(Xdisplay, Xcmap, &xcol); + + xcol.red = max((white.red / 5), xcol.red); + xcol.green = max((white.green / 5), xcol.green); + xcol.blue = max((white.blue / 5), xcol.blue); + + xcol.red = min(white.red, (xcol.red * 7) / 5); + xcol.green = min(white.green, (xcol.green * 7) / 5); + xcol.blue = min(white.blue, (xcol.blue * 7) / 5); + r = xcol.red; + g = xcol.green; + b = xcol.blue; + xcol.pixel = Imlib_best_color_match(imlib_id, &r, &g, &b); + + if (!XAllocColor(Xdisplay, Xcmap, &xcol)) { + print_error("Unable to allocate \"topShadowColor\" (0x%08x: 0x%04x, 0x%04x, 0x%04x) in the color map.", + xcol.pixel, r, g, b); + xcol.pixel = PixColors[WhiteColor]; + } + PixColors[topShadowColor] = xcol.pixel; + +#ifdef CHANGE_SCROLLCOLOR_ON_FOCUS + /* Do same for unfocusedTopShadowColor */ + xcol.pixel = PixColors[unfocusedScrollColor]; + XQueryColor(Xdisplay, Xcmap, &xcol); + + xcol.red = max((white.red / 5), xcol.red); + xcol.green = max((white.green / 5), xcol.green); + xcol.blue = max((white.blue / 5), xcol.blue); + + xcol.red = min(white.red, (xcol.red * 7) / 5); + xcol.green = min(white.green, (xcol.green * 7) / 5); + xcol.blue = min(white.blue, (xcol.blue * 7) / 5); + r = xcol.red; + g = xcol.green; + b = xcol.blue; + xcol.pixel = Imlib_best_color_match(imlib_id, &r, &g, &b); + + if (!XAllocColor(Xdisplay, Xcmap, &xcol)) { + print_error("Unable to allocate \"unfocusedtopShadowColor\" (0x%08x: 0x%04x, 0x%04x, 0x%04x) in the color map.", + xcol.pixel, r, g, b); + xcol.pixel = PixColors[WhiteColor]; + } + PixColors[unfocusedTopShadowColor] = xcol.pixel; +#endif + + } +#endif /* KEEP_SCROLLCOLOR */ + + szHint.base_width = (2 * TermWin.internalBorder + + (Options & Opt_scrollBar ? scrollbar_total_width() + : 0)); + szHint.base_height = (2 * TermWin.internalBorder); + + flags = (rs_geometry ? XParseGeometry(rs_geometry, &x, &y, &width, &height) : 0); + D_X11(("XParseGeometry(geom, %d, %d, %d, %d)\n", x, y, width, height)); + + if (flags & WidthValue) { + szHint.width = width; + szHint.flags |= USSize; + } + if (flags & HeightValue) { + szHint.height = height; + szHint.flags |= USSize; + } + TermWin.ncol = szHint.width; + TermWin.nrow = szHint.height; + + change_font(1, NULL); +#if (MENUBAR_MAX) + szHint.base_height += (delay_menu_drawing ? menuBar_TotalHeight() : 0); +#endif + if (flags & XValue) { + if (flags & XNegative) { + if (check_for_enlightenment()) { + x += (DisplayWidth(Xdisplay, Xscreen)); + } else { + x += (DisplayWidth(Xdisplay, Xscreen) - (szHint.width + TermWin.internalBorder)); + } + szHint.win_gravity = NorthEastGravity; + } + szHint.x = x; + szHint.flags |= USPosition; + } + if (flags & YValue) { + if (flags & YNegative) { + if (check_for_enlightenment()) { + y += (DisplayHeight(Xdisplay, Xscreen) - (2 * TermWin.internalBorder)); + } else { + y += (DisplayHeight(Xdisplay, Xscreen) - (szHint.height + TermWin.internalBorder)); + } + szHint.win_gravity = (szHint.win_gravity == NorthEastGravity ? + SouthEastGravity : SouthWestGravity); + } + szHint.y = y; + szHint.flags |= USPosition; + } + D_X11(("Geometry values after parsing: %dx%d%+d%+d\n", width, height, x, y)); + + /* parent window - reverse video so we can see placement errors + * sub-window placement & size in resize_subwindows() + */ + + Attributes.background_pixel = PixColors[bgColor]; + Attributes.border_pixel = PixColors[bgColor]; +#ifdef PREFER_24BIT + Attributes.colormap = Xcmap; + TermWin.parent = XCreateWindow(Xdisplay, Xroot, + szHint.x, szHint.y, + szHint.width, szHint.height, + 0, + Xdepth, InputOutput, + Xvisual, + CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect, + &Attributes); +#else + TermWin.parent = XCreateWindow(Xdisplay, Xroot, + szHint.x, szHint.y, + szHint.width, szHint.height, + 0, + Xdepth, + InputOutput, + CopyFromParent, + CWBackPixel | CWBorderPixel | CWOverrideRedirect, + &Attributes); +#endif + + xterm_seq(XTerm_title, rs_title); + xterm_seq(XTerm_iconName, rs_iconName); + classHint.res_name = (char *) rs_name; + classHint.res_class = APL_NAME; + wmHint.window_group = TermWin.parent; + wmHint.input = True; + wmHint.initial_state = (Options & Opt_iconic ? IconicState : NormalState); + wmHint.window_group = TermWin.parent; + wmHint.flags = (InputHint | StateHint | WindowGroupHint); +#ifdef PIXMAP_SUPPORT + set_icon_pixmap(rs_icon, &wmHint); +#endif + + XSetWMProperties(Xdisplay, TermWin.parent, NULL, NULL, argv, argc, &szHint, &wmHint, &classHint); + XSelectInput(Xdisplay, TermWin.parent, (KeyPressMask | FocusChangeMask | StructureNotifyMask | VisibilityChangeMask)); + if (mwmhints.flags) { + XChangeProperty(Xdisplay, TermWin.parent, prop, prop, 32, PropModeReplace, (unsigned char *) &mwmhints, PROP_MWM_HINTS_ELEMENTS); + } + /* vt cursor: Black-on-White is standard, but this is more popular */ + TermWin_cursor = XCreateFontCursor(Xdisplay, XC_xterm); + { + + XColor fg, bg; + + fg.pixel = PixColors[pointerColor]; + XQueryColor(Xdisplay, Xcmap, &fg); + bg.pixel = PixColors[bgColor]; + XQueryColor(Xdisplay, Xcmap, &bg); + XRecolorCursor(Xdisplay, TermWin_cursor, &fg, &bg); + } + + /* cursor (menuBar/scrollBar): Black-on-White */ + cursor = XCreateFontCursor(Xdisplay, XC_left_ptr); + + /* the vt window */ + +#ifdef BACKING_STORE + if ((!(Options & Opt_borderless)) + && (Options & Opt_saveUnder)) { + D_X11(("Creating term window with save_under = TRUE\n")); + TermWin.vt = XCreateWindow(Xdisplay, TermWin.parent, + 0, 0, + szHint.width, szHint.height, + 0, + Xdepth, + InputOutput, + CopyFromParent, + CWBackPixel | CWBorderPixel | CWOverrideRedirect | CWSaveUnder | CWBackingStore, + &Attributes); + if (!(background_is_pixmap()) && !(Options & Opt_borderless)) { + XSetWindowBackground(Xdisplay, TermWin.vt, PixColors[bgColor]); + XClearWindow(Xdisplay, TermWin.vt); + } + } else +#endif + { + D_X11(("Creating term window with no backing store\n")); + TermWin.vt = XCreateWindow(Xdisplay, TermWin.parent, + 0, 0, + szHint.width, szHint.height, + 0, + Xdepth, + InputOutput, + CopyFromParent, + CWBackPixel | CWBorderPixel | CWOverrideRedirect, + &Attributes); + if (!(background_is_pixmap()) && !(Options & Opt_borderless)) { + XSetWindowBackground(Xdisplay, TermWin.vt, PixColors[bgColor]); + XClearWindow(Xdisplay, TermWin.vt); + } + } + + XDefineCursor(Xdisplay, TermWin.vt, TermWin_cursor); +#ifdef USE_ACTIVE_TAGS + XSelectInput(Xdisplay, TermWin.vt, + (ExposureMask | ButtonPressMask | ButtonReleaseMask | + Button1MotionMask | Button3MotionMask | + PointerMotionMask | LeaveWindowMask)); +#else + XSelectInput(Xdisplay, TermWin.vt, + (ExposureMask | ButtonPressMask | ButtonReleaseMask | + Button1MotionMask | Button3MotionMask)); +#endif + + /* If the user wants a specific desktop, tell the WM that */ + if (rs_desktop != -1) { + prop = XInternAtom(Xdisplay, "_WIN_WORKSPACE", False); + val = rs_desktop; + XChangeProperty(Xdisplay, TermWin.parent, prop, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &val, 1); + } + XMapWindow(Xdisplay, TermWin.vt); + XMapWindow(Xdisplay, TermWin.parent); + + /* scrollBar: size doesn't matter */ +#ifdef KEEP_SCROLLCOLOR + Attributes.background_pixel = PixColors[scrollColor]; +#else + Attributes.background_pixel = PixColors[fgColor]; +#endif + Attributes.border_pixel = PixColors[bgColor]; + + scrollBar.win = XCreateWindow(Xdisplay, TermWin.parent, + 0, 0, + 1, 1, + 0, + Xdepth, + InputOutput, + CopyFromParent, + CWOverrideRedirect | CWSaveUnder | CWBackPixel | CWBorderPixel, + &Attributes); + + XDefineCursor(Xdisplay, scrollBar.win, cursor); + XSelectInput(Xdisplay, scrollBar.win, + (ExposureMask | ButtonPressMask | ButtonReleaseMask | + Button1MotionMask | Button2MotionMask | Button3MotionMask) + ); + +#ifdef PIXMAP_SCROLLBAR + if (scrollbar_is_pixmapped()) { + scrollBar.up_win = XCreateWindow(Xdisplay, scrollBar.win, + 0, 0, + scrollbar_total_width(), + scrollbar_arrow_height(), + 0, + Xdepth, + InputOutput, + CopyFromParent, + CWOverrideRedirect | CWSaveUnder, + &Attributes); + + XDefineCursor(Xdisplay, scrollBar.up_win, cursor); + XSelectInput(Xdisplay, scrollBar.up_win, + (ExposureMask | ButtonPressMask | ButtonReleaseMask | + Button1MotionMask | Button2MotionMask | Button3MotionMask) + ); + + scrollBar.dn_win = XCreateWindow(Xdisplay, scrollBar.win, + 0, + scrollbar_arrow_height() + + scrollbar_anchor_max_height(), + scrollbar_total_width(), + scrollbar_arrow_height(), + 0, + Xdepth, + InputOutput, + CopyFromParent, + CWOverrideRedirect | CWSaveUnder, + &Attributes); + + XDefineCursor(Xdisplay, scrollBar.dn_win, cursor); + XSelectInput(Xdisplay, scrollBar.dn_win, + (ExposureMask | ButtonPressMask | ButtonReleaseMask | + Button1MotionMask | Button2MotionMask | Button3MotionMask) + ); + scrollBar.sa_win = XCreateWindow(Xdisplay, scrollBar.win, + 0, + scrollbar_arrow_height(), + scrollbar_total_width(), + scrollbar_anchor_max_height(), + 0, + Xdepth, + InputOutput, + CopyFromParent, + CWOverrideRedirect | CWSaveUnder | CWBackingStore, + &Attributes); + + XDefineCursor(Xdisplay, scrollBar.sa_win, cursor); + XSelectInput(Xdisplay, scrollBar.sa_win, + (ExposureMask | ButtonPressMask | ButtonReleaseMask | + Button1MotionMask | Button2MotionMask | Button3MotionMask) + ); + } +#endif + +#if (MENUBAR_MAX) + /* menuBar: size doesn't matter */ +# ifdef KEEP_SCROLLCOLOR + Attributes.background_pixel = PixColors[scrollColor]; +# else + Attributes.background_pixel = PixColors[fgColor]; +# endif + Attributes.border_pixel = PixColors[bgColor]; + menuBar.win = XCreateWindow(Xdisplay, TermWin.parent, + 0, 0, + 1, 1, + 0, + Xdepth, + InputOutput, + CopyFromParent, + CWOverrideRedirect | CWSaveUnder | CWBackingStore | CWBackPixel | CWBorderPixel, + &Attributes); + + +# ifdef PIXMAP_MENUBAR + if (menubar_is_pixmapped()) { + set_Pixmap(rs_pixmaps[pixmap_mb], mbPixmap.pixmap, pixmap_mb); + XSetWindowBackgroundPixmap(Xdisplay, menuBar.win, + mbPixmap.pixmap); + } else +# endif + { +# ifdef KEEP_SCROLLCOLOR + XSetWindowBackground(Xdisplay, menuBar.win, PixColors[scrollColor]); +# else + XSetWindowBackground(Xdisplay, menuBar.win, PixColors[fgColor]); +# endif + } + + XClearWindow(Xdisplay, menuBar.win); + + XDefineCursor(Xdisplay, menuBar.win, cursor); + XSelectInput(Xdisplay, menuBar.win, + (ExposureMask | ButtonPressMask | ButtonReleaseMask | + Button1MotionMask) + ); +#endif /* MENUBAR_MAX */ + + XSetWindowBackground(Xdisplay, TermWin.vt, PixColors[bgColor]); + XClearWindow(Xdisplay, TermWin.vt); + +#ifdef PIXMAP_SUPPORT + if (rs_pixmaps[pixmap_bg] != NULL) { + + char *p = rs_pixmaps[pixmap_bg]; + + if ((p = strchr(p, '@')) != NULL) { + p++; + scale_pixmap(p, &bgPixmap); + } + D_PIXMAP(("set_bgPixmap() call #1\n")); + set_bgPixmap(rs_pixmaps[pixmap_bg]); + } +# ifdef PIXMAP_SCROLLBAR + if (scrollbar_is_pixmapped()) { + if (rs_pixmaps[pixmap_sb] != NULL) { + + char *p = rs_pixmaps[pixmap_sb]; + + if ((p = strchr(p, '@')) != NULL) { + p++; + scale_pixmap(p, &sbPixmap); + } + fprintf(stderr, "scrollbar sb: %s\n", p); + D_PIXMAP(("set_Pixmap(rs_pixmaps[pixmap_sb], pixmap_sb)\n")); + set_Pixmap(rs_pixmaps[pixmap_sb], sbPixmap.pixmap, pixmap_sb); + } + if (rs_pixmaps[pixmap_up] != NULL) { + + char *p = rs_pixmaps[pixmap_up]; + + if ((p = strchr(p, '@')) != NULL) { + p++; + scale_pixmap(p, &upPixmap); + } + fprintf(stderr, "scrollbar up: %s\n", p); + D_PIXMAP(("set_Pixmap(rs_pixmaps[pixmap_up], pixmap_up)\n")); + set_Pixmap(rs_pixmaps[pixmap_up], upPixmap.pixmap, pixmap_up); + } + if (rs_pixmaps[pixmap_upclk] != NULL) { + + char *p = rs_pixmaps[pixmap_upclk]; + + if ((p = strchr(p, '@')) != NULL) { + p++; + scale_pixmap(p, &up_clkPixmap); + } + fprintf(stderr, "scrollbar upclk: %s\n", p); + D_PIXMAP(("set_Pixmap(rs_pixmaps[pixmap_upclk], pixmap_upclk)\n")); + set_Pixmap(rs_pixmaps[pixmap_upclk], up_clkPixmap.pixmap, pixmap_upclk); + } + if (rs_pixmaps[pixmap_dn] != NULL) { + + char *p = rs_pixmaps[pixmap_dn]; + + if ((p = strchr(p, '@')) != NULL) { + p++; + scale_pixmap(p, &dnPixmap); + } + fprintf(stderr, "scrollbar dn: %s\n", p); + D_PIXMAP(("set_Pixmap(rs_pixmaps[pixmap_dn], pixmap_dn)\n")); + set_Pixmap(rs_pixmaps[pixmap_dn], dnPixmap.pixmap, pixmap_dn); + } + if (rs_pixmaps[pixmap_dnclk] != NULL) { + + char *p = rs_pixmaps[pixmap_dnclk]; + + if ((p = strchr(p, '@')) != NULL) { + p++; + scale_pixmap(p, &dn_clkPixmap); + } + fprintf(stderr, "scrollbar dnclk: %s\n", p); + D_PIXMAP(("set_Pixmap(rs_pixmaps[pixmap_dnclk], pixmap_dnclk)\n")); + set_Pixmap(rs_pixmaps[pixmap_dnclk], dn_clkPixmap.pixmap, pixmap_dnclk); + } + if (rs_pixmaps[pixmap_sa] != NULL) { + + char *p = rs_pixmaps[pixmap_sa]; + + if ((p = strchr(p, '@')) != NULL) { + p++; + scale_pixmap(p, &saPixmap); + } + fprintf(stderr, "scrollbar sa: %s\n", p); + D_PIXMAP(("set_Pixmap(rs_pixmaps[pixmap_sa], pixmap_sa)\n")); + set_Pixmap(rs_pixmaps[pixmap_sa], saPixmap.pixmap, pixmap_sa); + } + if (rs_pixmaps[pixmap_saclk] != NULL) { + + char *p = rs_pixmaps[pixmap_saclk]; + + if ((p = strchr(p, '@')) != NULL) { + p++; + scale_pixmap(p, &sa_clkPixmap); + } + fprintf(stderr, "scrollbar saclk: %s\n", p); + D_PIXMAP(("set_Pixmap(rs_pixmaps[pixmap_saclk], pixmap_saclk)\n")); + set_Pixmap(rs_pixmaps[pixmap_saclk], sa_clkPixmap.pixmap, pixmap_saclk); + } + } +# endif /* PIXMAP_SCROLLBAR */ + +# ifdef PIXMAP_MENUBAR + if (menubar_is_pixmapped()) { + if (rs_pixmaps[pixmap_mb] != NULL) { + + char *p = rs_pixmaps[pixmap_mb]; + + if ((p = strchr(p, '@')) != NULL) { + p++; + scale_pixmap(p, &mbPixmap); + } + fprintf(stderr, "menubar mb: %s\n", p); + set_Pixmap(rs_pixmaps[pixmap_mb], mbPixmap.pixmap, pixmap_mb); + } + if (rs_pixmaps[pixmap_ms] != NULL) { + + char *p = rs_pixmaps[pixmap_ms]; + + if ((p = strchr(p, '@')) != NULL) { + p++; + scale_pixmap(p, &mb_selPixmap); + } + fprintf(stderr, "menubar ms: %s\n", p); + D_PIXMAP(("set_Pixmap(rs_pixmaps[pixmap_ms], pixmap_ms)\n")); + set_Pixmap(rs_pixmaps[pixmap_ms], mb_selPixmap.pixmap, pixmap_ms); + } + } +# endif /* PIXMAP_MENUBAR */ +#else /* PIXMAP_SUPPORT */ + XSetWindowBackground(Xdisplay, TermWin.vt, PixColors[bgColor]); + XClearWindow(Xdisplay, TermWin.vt); +#endif /* PIXMAP_SUPPORT */ + + /* graphics context for the vt window */ + { + + XGCValues gcvalue; + + gcvalue.font = TermWin.font->fid; + gcvalue.foreground = PixColors[fgColor]; + gcvalue.background = PixColors[bgColor]; + gcvalue.graphics_exposures = 0; + TermWin.gc = XCreateGC(Xdisplay, TermWin.vt, + GCForeground | GCBackground | GCFont | GCGraphicsExposures, + &gcvalue); + } + + if (Options & Opt_noCursor) + scr_cursor_visible(0); +} + +/* window resizing - assuming the parent window is the correct size */ +void +resize_subwindows(int width, int height) +{ + + int x = 0, y = 0; + +#ifdef RXVT_GRAPHICS + int old_width = TermWin.width; + int old_height = TermWin.height; + +#endif + + D_SCREEN(("resize_subwindows(%d, %d)\n", width, height)); + TermWin.width = TermWin.ncol * TermWin.fwidth; + TermWin.height = TermWin.nrow * TermWin.fheight; + + /* size and placement */ + if (scrollbar_visible()) { + scrollBar.beg = 0; + scrollBar.end = height; +#ifdef MOTIF_SCROLLBAR + if (scrollBar.type == SCROLLBAR_MOTIF) { + /* arrows are as high as wide - leave 1 pixel gap */ + scrollBar.beg += scrollbar_arrow_height(); + scrollBar.end -= scrollbar_arrow_height(); + } +#endif +#ifdef NEXT_SCROLLBAR + if (scrollBar.type == SCROLLBAR_NEXT) { + scrollBar.beg = sb_shadow; + scrollBar.end -= (scrollBar.width * 2 + (sb_shadow ? sb_shadow : 1) + 2); + } +#endif + width -= scrollbar_total_width(); + XMoveResizeWindow(Xdisplay, scrollBar.win, + ((Options & Opt_scrollBar_right) ? (width) : (x)), + 0, scrollbar_total_width(), height); + + if (!(Options & Opt_scrollBar_right)) { + x = scrollbar_total_width(); + } + } +#if (MENUBAR_MAX) + if (menubar_visible()) { + y = menuBar_TotalHeight(); /* for placement of vt window */ + XMoveResizeWindow(Xdisplay, menuBar.win, x, 0, width, y); + if ((!(menubar_is_pixmapped())) + && ((Options & Opt_borderless) || (Options & Opt_saveUnder))) + XSetWindowBackground(Xdisplay, menuBar.win, PixColors[scrollColor]); + } +#endif /* NO_MENUBAR */ + + XMoveResizeWindow(Xdisplay, TermWin.vt, x, y, width, height + 1); + +#ifdef RXVT_GRAPHICS + if (old_width) + Gr_Resize(old_width, old_height); +#endif + XClearWindow(Xdisplay, TermWin.vt); + if (!(background_is_pixmap())) + XSetWindowBackground(Xdisplay, TermWin.vt, PixColors[bgColor]); + +#ifdef PIXMAP_SUPPORT +# ifdef USE_POSIX_THREADS + + D_PIXMAP(("resize_subwindows(): start_bg_thread()\n")); + pthread_attr_init(&resize_sub_thr_attr); + +# ifdef MUTEX_SYNCH + if (pthread_mutex_trylock(&mutex) == EBUSY) { + D_THREADS(("resize_subwindows(): mutex locked, bbl\n")); + } else { + D_THREADS(("pthread_mutex_trylock(&mutex): ")); + pthread_mutex_unlock(&mutex); + D_THREADS(("pthread_mutex_unlock(&mutex)\n")); + } +# endif + + if (!(pthread_create(&resize_sub_thr, &resize_sub_thr_attr, + (void *) &render_bg_thread, NULL))) { + /* bg_set = 0; */ + D_THREADS(("thread created\n")); + } else { + D_THREADS(("pthread_create() failed!\n")); + } + +# else + D_PIXMAP(("resize_subwindows(): render_pixmap(TermWin.vt)\n")); + render_pixmap(TermWin.vt, imlib_bg, bgPixmap, 0, 1); + XSync(Xdisplay, 0); +# endif +#endif +} + +static void +resize(void) +{ + szHint.base_width = (2 * TermWin.internalBorder); + szHint.base_height = (2 * TermWin.internalBorder); + + szHint.base_width += (scrollbar_visible()? scrollbar_total_width() : 0); +#if (MENUBAR_MAX) + szHint.base_height += (menubar_visible()? menuBar_TotalHeight() : 0); +#endif + + szHint.min_width = szHint.base_width + szHint.width_inc; + szHint.min_height = szHint.base_height + szHint.height_inc; + + szHint.width = szHint.base_width + TermWin.width; + szHint.height = szHint.base_height + TermWin.height; + + szHint.flags = PMinSize | PResizeInc | PBaseSize | PWinGravity; + + XSetWMNormalHints(Xdisplay, TermWin.parent, &szHint); + XResizeWindow(Xdisplay, TermWin.parent, szHint.width, szHint.height); + + resize_subwindows(szHint.width, szHint.height); +} + +/* + * Redraw window after exposure or size change + */ +static void +resize_window1(unsigned int width, unsigned int height) +{ + static short first_time = 1; + int new_ncol = (width - szHint.base_width) / TermWin.fwidth; + int new_nrow = (height - szHint.base_height) / TermWin.fheight; + + if (first_time || + (new_ncol != TermWin.ncol) || + (new_nrow != TermWin.nrow)) { + int curr_screen = -1; + + /* scr_reset only works on the primary screen */ + if (!first_time) { /* this is not the first time thru */ + selection_clear(); + curr_screen = scr_change_screen(PRIMARY); + } + TermWin.ncol = new_ncol; + TermWin.nrow = new_nrow; + + resize_subwindows(width, height); + scr_reset(); + + if (curr_screen >= 0) /* this is not the first time thru */ + scr_change_screen(curr_screen); + first_time = 0; + } else if (Options & Opt_pixmapTrans) { + resize_subwindows(width, height); + scrollbar_show(0); + scr_expose(0, 0, width, height); + } +} + +/* + * good for toggling 80/132 columns + */ +void +set_width(unsigned short width) +{ + unsigned short height = TermWin.nrow; + + if (width != TermWin.ncol) { + width = szHint.base_width + width * TermWin.fwidth; + height = szHint.base_height + height * TermWin.fheight; + + XResizeWindow(Xdisplay, TermWin.parent, width, height); + resize_window1(width, height); + } +} + +/* + * Redraw window after exposure or size change + */ +void +resize_window(void) +{ + Window root; + XEvent dummy; + int x, y; + unsigned int border, depth, width, height; + + while (XCheckTypedWindowEvent(Xdisplay, TermWin.parent, + ConfigureNotify, &dummy)); + + /* do we come from an fontchange? */ + if (font_change_count > 0) { + font_change_count--; + return; + } + XGetGeometry(Xdisplay, TermWin.parent, + &root, &x, &y, &width, &height, &border, &depth); +#if 0 + XGetGeometry(Xdisplay, TermWin.vt, + &root, &x, &y, &width, &height, &border, &depth); +#endif + + /* parent already resized */ + + resize_window1(width, height); +} + +/* xterm sequences - title, iconName, color (exptl) */ +#ifdef SMART_WINDOW_TITLE +static void +set_title(const char *str) +{ + + char *name; + + if (XFetchName(Xdisplay, TermWin.parent, &name)) + name = NULL; + if (name == NULL || strcmp(name, str)) + XStoreName(Xdisplay, TermWin.parent, str); + if (name) + XFree(name); +} +#else +# define set_title(str) XStoreName(Xdisplay, TermWin.parent, str) +#endif + +#ifdef SMART_WINDOW_TITLE +static void +set_iconName(const char *str) +{ + + char *name; + + if (XGetIconName(Xdisplay, TermWin.parent, &name)) + name = NULL; + if (name == NULL || strcmp(name, str)) + XSetIconName(Xdisplay, TermWin.parent, str); + if (name) + XFree(name); +} +#else +# define set_iconName(str) XSetIconName (Xdisplay, TermWin.parent, str) +#endif + +#ifdef XTERM_COLOR_CHANGE +static void +set_window_color(int idx, const char *color) +{ + + XColor xcol; + int i; + unsigned int pixel, r, g, b; + + if (color == NULL || *color == '\0') + return; + + /* handle color aliases */ + if (isdigit(*color)) { + i = atoi(color); + if (i >= 8 && i <= 15) { /* bright colors */ + i -= 8; +# ifndef NO_BRIGHTCOLOR + PixColors[idx] = PixColors[minBright + i]; + goto Done; +# endif + } + if (i >= 0 && i <= 7) { /* normal colors */ + PixColors[idx] = PixColors[minColor + i]; + goto Done; + } + } + if (XParseColor(Xdisplay, Xcmap, color, &xcol)) { + r = xcol.red; + g = xcol.green; + b = xcol.blue; + pixel = Imlib_best_color_match(imlib_id, &r, &g, &b); + xcol.pixel = pixel; + if (!XAllocColor(Xdisplay, Xcmap, &xcol)) { + print_warning("Unable to allocate \"%s\" in the color map.\n", color); + return; + } + } else { + print_warning("Unable to resolve \"%s\" as a color name.\n", color); + return; + } + + /* XStoreColor(Xdisplay, Xcmap, XColor*); */ + + /* + * FIXME: should free colors here, but no idea how to do it so instead, + * so just keep gobbling up the colormap + */ +# if 0 + for (i = BlackColor; i <= WhiteColor; i++) + if (PixColors[idx] == PixColors[i]) + break; + if (i > WhiteColor) { + /* fprintf (stderr, "XFreeColors: PixColors[%d] = %lu\n", idx, PixColors[idx]); */ + XFreeColors(Xdisplay, Xcmap, (PixColors + idx), 1, + DisplayPlanes(Xdisplay, Xscreen)); + } +# endif + + PixColors[idx] = xcol.pixel; + + /* XSetWindowAttributes attr; */ + /* Cursor cursor; */ +Done: + if (idx == bgColor) + XSetWindowBackground(Xdisplay, TermWin.vt, PixColors[bgColor]); + + /* handle colorBD, scrollbar background, etc. */ + + set_colorfgbg(); + { + + XColor fg, bg; + + fg.pixel = PixColors[fgColor]; + XQueryColor(Xdisplay, Xcmap, &fg); + bg.pixel = PixColors[bgColor]; + XQueryColor(Xdisplay, Xcmap, &bg); + + XRecolorCursor(Xdisplay, TermWin_cursor, &fg, &bg); + } + /* the only reasonable way to enforce a clean update */ + scr_poweron(); +} +#else +# define set_window_color(idx,color) ((void)0) +#endif /* XTERM_COLOR_CHANGE */ + +/* Macros to make parsing escape sequences slightly more readable.... */ +#define OPT_SET_OR_TOGGLE(s, mask, bit) do { \ + if (!(s) || !(*(s))) { \ + if ((mask) & (bit)) { \ + (mask) &= ~(bit); \ + } else { \ + (mask) |= (bit); \ + } \ + } else if (BOOL_OPT_ISTRUE(s)) { \ + if ((mask) & (bit)) return; \ + (mask) |= (bit); \ + } else if (BOOL_OPT_ISFALSE(s)) { \ + if (!((mask) & (bit))) return; \ + (mask) &= ~(bit); \ + } \ + } while (0) +/* The macro below forces bit to the opposite state from what we want, so that the + code that follows will set it right. Hackish, but saves space. :) Use this + if you need to do some processing other than just setting the flag right. */ +#define OPT_SET_OR_TOGGLE_NEG(s, mask, bit) do { if (s) { \ + if (BOOL_OPT_ISTRUE(s)) { \ + if ((mask) & (bit)) return; \ + (mask) &= ~(bit); \ + } else if (BOOL_OPT_ISFALSE(s)) { \ + if (!((mask) & (bit))) return; \ + (mask) |= (bit); \ + } \ + } } while (0) + +/* + * XTerm escape sequences: ESC ] Ps;Pt BEL + * 0 = change iconName/title + * 1 = change iconName + * 2 = change title + * 46 = change logfile (not implemented) + * 50 = change font + * + * rxvt/Eterm extensions: + * 5 = Hostile takeover (grab focus and raise) + * 6 = Transparency mode stuff + * 10 = menu + * 20 = bg pixmap + * 39 = change default fg color + * 49 = change default bg color + */ +void +xterm_seq(int op, const char *str) +{ + + XColor xcol; + char *nstr, *tnstr, *orig_tnstr; + unsigned char eterm_seq_op; + +#if MENUBAR_MAX + char *menu_str; + +#endif +#ifdef PIXMAP_SUPPORT + int changed = 0, scaled = 0; + +#endif + + if (!str) + return; + +#if MENUBAR_MAX + menu_str = strdup(str); +#endif +#ifdef PIXMAP_SUPPORT + orig_tnstr = tnstr = strdup(str); +#endif + + switch (op) { + case XTerm_title: + set_title(str); + break; + case XTerm_name: + set_title(str); /* drop */ + case XTerm_iconName: + set_iconName(str); + break; + case XTerm_Takeover: + XSetInputFocus(Xdisplay, TermWin.parent, RevertToParent, CurrentTime); + XRaiseWindow(Xdisplay, TermWin.parent); + break; +#if MENUBAR_MAX + case XTerm_Menu: + menubar_dispatch(menu_str); + free(menu_str); + break; +#endif + + case XTerm_EtermSeq: + + /* Eterm proprietary escape sequences + + Syntax: ESC ] 6 ; ; BEL + + where is: 0 Set/toggle transparency + 1 Set shade percentage + 2 Set tint mask + 3 Force update of pseudo-transparent background + 4 Set/toggle desktop watching + 10 Set scrollbar type/width + 11 Set/toggle right-side scrollbar + 12 Set/toggle floating scrollbar + 13 Set/toggle popup scrollbar + 15 Set/toggle menubar move + 20 Set/toggle visual bell + 21 Set/toggle map alert + 22 Set/toggle xterm selection behavior + 23 Set/toggle triple-click line selection + 24 Set/toggle viewport mode + 25 Set/toggle selection of trailing spaces + 30 Do not use + 40 Do not use + 50 Move window to another desktop + 70 Exit Eterm + 71 Save current configuration to a file + and is an optional argument, depending + on the particular sequence being used. It + (along with its preceeding semicolon) may or + may not be needed. + */ + + D_EVENTS(("Got XTerm_EtermSeq sequence\n")); + nstr = strsep(&tnstr, ";"); + eterm_seq_op = (unsigned char) strtol(nstr, (char **) NULL, 10); + D_EVENTS((" XTerm_EtermSeq operation is %d\n", eterm_seq_op)); + /* Yes, there is order to the numbers for this stuff. And here it is: + 0-9 Transparency Configuration + 10-14 Scrollbar Configuration + 15-19 Menubar Configuration + 20-29 Miscellaneous Toggles + 30-39 Foreground/Text Color Configuration + 40-49 Background Color Configuration + 50-69 Window/Window Manager Configuration/Interaction + 70-79 Internal Eterm Operations + */ + switch (eterm_seq_op) { +#ifdef PIXMAP_OFFSET + case 0: + nstr = strsep(&tnstr, ";"); + OPT_SET_OR_TOGGLE_NEG(nstr, Options, Opt_pixmapTrans); + if (Options & Opt_pixmapTrans) { + Options &= ~(Opt_pixmapTrans); +# ifdef IMLIB_TRANS + if (imlib_id) { + if (imlib_bg.im != NULL) { + Imlib_kill_image(imlib_id, imlib_bg.im); + imlib_bg.im = NULL; + } + } +#endif + set_bgPixmap(rs_pixmaps[pixmap_bg]); + } else { + Options |= Opt_pixmapTrans; + if (imlib_id) { + ImlibFreePixmap(imlib_id, bgPixmap.pixmap); + if (imlib_bg.im != NULL) { + D_IMLIB(("ImlibDestroyImage()\n")); + ImlibDestroyImage(imlib_id, imlib_bg.im); + imlib_bg.im = NULL; + } + bgPixmap.pixmap = None; + } + TermWin.pixmap = None; + } + render_pixmap(TermWin.vt, imlib_bg, bgPixmap, 0, 1); + scr_touch(); + break; + case 1: + nstr = strsep(&tnstr, ";"); + if (!nstr) { + break; + } + rs_shadePct = strtoul(nstr, (char **) NULL, 0); + D_EVENTS((" XTerm_EtermSeq shade percentage is %d%%\n", rs_shadePct)); + if (Options & Opt_pixmapTrans && desktop_pixmap != None) { + XFreePixmap(Xdisplay, desktop_pixmap); + desktop_pixmap = None; /* Force the re-read */ + } + if (Options & Opt_viewport_mode && viewport_pixmap != None) { + XFreePixmap(Xdisplay, viewport_pixmap); + viewport_pixmap = None; /* Force the re-read */ + } + render_pixmap(TermWin.vt, imlib_bg, bgPixmap, 0, 1); + scr_touch(); + break; + case 2: + nstr = strsep(&tnstr, ";"); + if (!nstr) { + break; + } + if (!BEG_STRCASECMP(nstr, "none")) { + rs_tintMask = 0xffffff; + } else if (!BEG_STRCASECMP(nstr, "red")) { + rs_tintMask = 0xff8080; + } else if (!BEG_STRCASECMP(nstr, "green")) { + rs_tintMask = 0x80ff80; + } else if (!BEG_STRCASECMP(nstr, "blue")) { + rs_tintMask = 0x8080ff; + } else if (!BEG_STRCASECMP(nstr, "cyan")) { + rs_tintMask = 0x80ffff; + } else if (!BEG_STRCASECMP(nstr, "magenta")) { + rs_tintMask = 0xff80ff; + } else if (!BEG_STRCASECMP(nstr, "yellow")) { + rs_tintMask = 0xffff80; + } else { + rs_tintMask = strtoul(nstr, (char **) NULL, 0); + } + D_EVENTS((" XTerm_EtermSeq tint mask is 0x%06x\n", rs_tintMask)); + if (Options & Opt_pixmapTrans && desktop_pixmap != None) { + XFreePixmap(Xdisplay, desktop_pixmap); + desktop_pixmap = None; /* Force the re-read */ + } + if (Options & Opt_viewport_mode && viewport_pixmap != None) { + XFreePixmap(Xdisplay, viewport_pixmap); + viewport_pixmap = None; /* Force the re-read */ + } + render_pixmap(TermWin.vt, imlib_bg, bgPixmap, 0, 1); + scr_touch(); + break; + case 3: + if (Options & Opt_pixmapTrans) { + get_desktop_window(); + if (desktop_pixmap != None) { + XFreePixmap(Xdisplay, desktop_pixmap); + desktop_pixmap = None; /* Force the re-read */ + } + render_pixmap(TermWin.vt, imlib_bg, bgPixmap, 0, 1); + scr_expose(0, 0, TermWin_TotalWidth(), TermWin_TotalHeight()); + } + break; + case 4: + nstr = strsep(&tnstr, ";"); + OPT_SET_OR_TOGGLE(nstr, Options, Opt_watchDesktop); + if (Options & Opt_pixmapTrans) { + get_desktop_window(); + } + break; +#endif + case 10: + nstr = strsep(&tnstr, ";"); + if (nstr && *nstr) { + if (!strcasecmp(nstr, "xterm")) { +#ifdef XTERM_SCROLLBAR + scrollBar.type = SCROLLBAR_XTERM; +#else + print_error("Support for xterm scrollbars was not compiled in. Sorry."); +#endif + } else if (!strcasecmp(nstr, "next")) { +#ifdef NEXT_SCROLLBAR + scrollBar.type = SCROLLBAR_NEXT; +#else + print_error("Support for NeXT scrollbars was not compiled in. Sorry."); +#endif + } else if (!strcasecmp(nstr, "motif")) { +#ifdef MOTIF_SCROLLBAR + scrollBar.type = SCROLLBAR_MOTIF; +#else + print_error("Support for motif scrollbars was not compiled in. Sorry."); +#endif + } else { + print_error("Unrecognized scrollbar type \"%s\".", nstr); + } + scrollbar_reset(); + map_scrollBar(0); + map_scrollBar(1); + scrollbar_show(0); + } + nstr = strsep(&tnstr, ";"); + if (nstr && *nstr) { + scrollBar.width = strtoul(nstr, (char **) NULL, 0); + if (scrollBar.width == 0) { + print_error("Invalid scrollbar length \"%s\".", nstr); + scrollBar.width = SB_WIDTH; + } + scrollbar_reset(); + map_scrollBar(0); + map_scrollBar(1); + scrollbar_show(0); + } + break; + case 11: + nstr = strsep(&tnstr, ";"); + OPT_SET_OR_TOGGLE(nstr, Options, Opt_scrollBar_right); + scrollbar_reset(); + map_scrollBar(0); + map_scrollBar(1); + scrollbar_show(0); + break; + case 12: + nstr = strsep(&tnstr, ";"); + OPT_SET_OR_TOGGLE(nstr, Options, Opt_scrollBar_floating); + scrollbar_reset(); + map_scrollBar(0); + map_scrollBar(1); + scrollbar_show(0); + break; + case 13: + nstr = strsep(&tnstr, ";"); + OPT_SET_OR_TOGGLE(nstr, Options, Opt_scrollbar_popup); + break; + case 15: + nstr = strsep(&tnstr, ";"); + OPT_SET_OR_TOGGLE(nstr, Options, Opt_menubar_move); + break; + case 20: + nstr = strsep(&tnstr, ";"); + OPT_SET_OR_TOGGLE(nstr, Options, Opt_visualBell); + break; +#ifdef MAPALERT_OPTION + case 21: + nstr = strsep(&tnstr, ";"); + OPT_SET_OR_TOGGLE(nstr, Options, Opt_mapAlert); + break; +#endif + case 22: + nstr = strsep(&tnstr, ";"); + OPT_SET_OR_TOGGLE(nstr, Options, Opt_xterm_select); + break; + case 23: + nstr = strsep(&tnstr, ";"); + OPT_SET_OR_TOGGLE(nstr, Options, Opt_select_whole_line); + break; + case 24: + nstr = strsep(&tnstr, ";"); + OPT_SET_OR_TOGGLE(nstr, Options, Opt_viewport_mode); + render_pixmap(TermWin.vt, imlib_bg, bgPixmap, 0, 1); + scr_touch(); + break; + case 25: + nstr = strsep(&tnstr, ";"); + OPT_SET_OR_TOGGLE(nstr, Options, Opt_select_trailing_spaces); + break; + case 30: + nstr = strsep(&tnstr, ";"); + if (nstr) { + if (XParseColor(Xdisplay, Xcmap, nstr, &xcol) && XAllocColor(Xdisplay, Xcmap, &xcol)) { + PixColors[fgColor] = xcol.pixel; + scr_refresh(SMOOTH_REFRESH); + } + } + break; + case 40: + nstr = strsep(&tnstr, ";"); + if (nstr) { + if (XParseColor(Xdisplay, Xcmap, nstr, &xcol) && XAllocColor(Xdisplay, Xcmap, &xcol)) { + PixColors[bgColor] = xcol.pixel; + scr_refresh(SMOOTH_REFRESH); + } + } + break; + case 50: + /* Change desktops */ + nstr = strsep(&tnstr, ";"); + if (nstr && *nstr) { + XClientMessageEvent xev; + + rs_desktop = (int) strtol(nstr, (char **) NULL, 0); + xev.type = ClientMessage; + xev.window = TermWin.parent; + xev.message_type = XInternAtom(Xdisplay, "_WIN_WORKSPACE", False); + xev.format = 32; + xev.data.l[0] = rs_desktop; + XChangeProperty(Xdisplay, TermWin.parent, xev.message_type, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &rs_desktop, 1); + XSendEvent(Xdisplay, Xroot, False, SubstructureNotifyMask, (XEvent *) & xev); + } + break; + case 70: + /* Exit Eterm */ + exit(0); + break; + case 71: + /* Save current config */ + nstr = strsep(&tnstr, ";"); + if (nstr && *nstr) { + save_config(nstr); + } else { + save_config(NULL); + } + break; + + default: + break; + } + break; + + case XTerm_Pixmap: +#ifdef PIXMAP_SUPPORT +# ifdef PIXMAP_OFFSET + if (Options & Opt_pixmapTrans) { + Options &= ~(Opt_pixmapTrans); + } +# endif + rs_shadePct = 0; + rs_tintMask = 0xffffff; + if (!strcmp(str, ";")) { + rs_pixmaps[pixmap_bg] = ""; + set_bgPixmap(""); + return; + } + nstr = strsep(&tnstr, ";"); + if (nstr) { + if (*nstr) { + scale_pixmap("", &bgPixmap); + D_PIXMAP(("set_bgPixmap() call #2\n")); + bg_needs_update = 1; + set_bgPixmap(nstr); + } + while ((nstr = strsep(&tnstr, ";")) && *nstr) { + changed += scale_pixmap(nstr, &bgPixmap); + scaled = 1; + } + /* FIXME: This used to be && instead of || to avoid unnecessary + * rendering under some circumstances... I'll try to look + * deeper :) -vendu + */ + if ((changed) || (bg_needs_update)) { + D_PIXMAP(("XTerm_Pixmap sequence: render_pixmap(TermWin.vt)\n")); + render_pixmap(TermWin.vt, imlib_bg, bgPixmap, 0, 1); + scr_touch(); + } + } else { + D_PIXMAP(("set_bgPixmap() call #3\n")); + set_bgPixmap(""); + } +#endif /* PIXMAP_SUPPORT */ + break; + + case XTerm_restoreFG: + set_window_color(fgColor, str); + break; + case XTerm_restoreBG: + set_window_color(bgColor, str); + break; + case XTerm_logfile: + break; + case XTerm_font: + change_font(0, str); + break; +#ifdef ETERM_COMMAND_MODE + case ETerm_command_mode: + fprintf(stderr, "ETerm_command_mode\n"); + break; +#endif + default: + D_CMD(("Unsupported xterm escape sequence operator: 0x%02x\n", op)); + break; + } +#ifdef PIXMAP_SUPPORT + free(orig_tnstr); +#endif +} + +/* change_font() - Switch to a new font */ +/* + * init = 1 - initialize + * + * fontname == FONT_UP - switch to bigger font + * fontname == FONT_DN - switch to smaller font + */ +#define ABORT() do { print_error("aborting"); exit(EXIT_FAILURE); } while (0) +void +change_font(int init, const char *fontname) +{ + const char *const msg = "can't load font \"%s\""; + XFontStruct *xfont; + static char *newfont[NFONTS]; + +#ifndef NO_BOLDFONT + static XFontStruct *boldFont = NULL; + +#endif + static int fnum = FONT0_IDX; /* logical font number */ + int idx = 0; /* index into rs_font[] */ + +#if (FONT0_IDX == 0) +# define IDX2FNUM(i) (i) +# define FNUM2IDX(f) (f) +#else +# define IDX2FNUM(i) (i == 0? FONT0_IDX : (i <= FONT0_IDX? (i-1) : i)) +# define FNUM2IDX(f) (f == FONT0_IDX ? 0 : (f < FONT0_IDX ? (f+1) : f)) +#endif +#define FNUM_RANGE(i) (i <= 0 ? 0 : (i >= NFONTS ? (NFONTS-1) : i)) + + if (!init) { + switch (fontname[0]) { + case '\0': + fnum = FONT0_IDX; + fontname = NULL; + break; + + /* special (internal) prefix for font commands */ + case FONT_CMD: + idx = atoi(fontname + 1); + switch (fontname[1]) { + case '+': /* corresponds to FONT_UP */ + fnum += (idx ? idx : 1); + fnum = FNUM_RANGE(fnum); + break; + + case '-': /* corresponds to FONT_DN */ + fnum += (idx ? idx : -1); + fnum = FNUM_RANGE(fnum); + break; + + default: + if (fontname[1] != '\0' && !isdigit(fontname[1])) + return; + if (idx < 0 || idx >= (NFONTS)) + return; + fnum = IDX2FNUM(idx); + break; + } + fontname = NULL; + break; + + default: + if (fontname != NULL) { + /* search for existing fontname */ + for (idx = 0; idx < NFONTS; idx++) { + if (!strcmp(rs_font[idx], fontname)) { + fnum = IDX2FNUM(idx); + fontname = NULL; + break; + } + } + } else + return; + break; + } + /* re-position around the normal font */ + idx = FNUM2IDX(fnum); + + if (fontname != NULL) { + char *name; + + xfont = XLoadQueryFont(Xdisplay, fontname); + if (!xfont) + return; + + name = MALLOC(strlen(fontname + 1) * sizeof(char)); + + if (name == NULL) { + XFreeFont(Xdisplay, xfont); + return; + } + strcpy(name, fontname); + if (newfont[idx] != NULL) + FREE(newfont[idx]); + newfont[idx] = name; + rs_font[idx] = newfont[idx]; + } + } + if (TermWin.font) + XFreeFont(Xdisplay, TermWin.font); + + /* load font or substitute */ + xfont = XLoadQueryFont(Xdisplay, rs_font[idx]); + if (!xfont) { + print_error(msg, rs_font[idx]); + rs_font[idx] = "fixed"; + xfont = XLoadQueryFont(Xdisplay, rs_font[idx]); + if (!xfont) { + print_error(msg, rs_font[idx]); + ABORT(); + } + } + TermWin.font = xfont; + +#ifndef NO_BOLDFONT + /* fail silently */ + if (init && rs_boldFont != NULL) + boldFont = XLoadQueryFont(Xdisplay, rs_boldFont); +#endif + +#ifdef KANJI + if (TermWin.kanji) + XFreeFont(Xdisplay, TermWin.kanji); + + /* load font or substitute */ + xfont = XLoadQueryFont(Xdisplay, rs_kfont[idx]); + if (!xfont) { + print_error(msg, rs_kfont[idx]); + rs_kfont[idx] = "k14"; + xfont = XLoadQueryFont(Xdisplay, rs_kfont[idx]); + if (!xfont) { + print_error(msg, rs_kfont[idx]); + ABORT(); + } + } + TermWin.kanji = xfont; +#endif /* KANJI */ + + /* alter existing GC */ + if (!init) { + XSetFont(Xdisplay, TermWin.gc, TermWin.font->fid); +#if (MENUBAR_MAX) + menubar_expose(); +#endif /* MENUBAR_MAX */ + } + /* set the sizes */ + { + + int i, cw, fh, fw = 0; + + fw = TermWin.font->min_bounds.width; + fh = TermWin.font->ascent + TermWin.font->descent; + + D_X11(("Font information: Ascent == %hd, Descent == %hd\n", TermWin.font->ascent, TermWin.font->descent)); + if (TermWin.font->min_bounds.width == TermWin.font->max_bounds.width) + TermWin.fprop = 0; /* Mono-spaced (fixed width) font */ + else + TermWin.fprop = 1; /* Proportional font */ + if (TermWin.fprop == 1) + for (i = TermWin.font->min_char_or_byte2; + i <= TermWin.font->max_char_or_byte2; i++) { + cw = TermWin.font->per_char[i].width; + MAX_IT(fw, cw); + } + /* not the first time thru and sizes haven't changed */ + if (fw == TermWin.fwidth && fh == TermWin.fheight) + return; /* TODO: not return; check KANJI if needed */ + + TermWin.fwidth = fw; + TermWin.fheight = fh; + } + + /* check that size of boldFont is okay */ +#ifndef NO_BOLDFONT + TermWin.boldFont = NULL; + if (boldFont != NULL) { + int i, cw, fh, fw = 0; + + fw = boldFont->min_bounds.width; + fh = boldFont->ascent + boldFont->descent; + if (TermWin.fprop == 0) { /* bold font must also be monospaced */ + if (fw != boldFont->max_bounds.width) + fw = -1; + } else { + for (i = 0; i < 256; i++) { + if (!isprint(i)) + continue; + cw = boldFont->per_char[i].width; + MAX_IT(fw, cw); + } + } + + if (fw == TermWin.fwidth && fh == TermWin.fheight) + TermWin.boldFont = boldFont; + } +#endif /* NO_BOLDFONT */ + + set_colorfgbg(); + + TermWin.width = TermWin.ncol * TermWin.fwidth; + TermWin.height = TermWin.nrow * TermWin.fheight; + + szHint.width_inc = TermWin.fwidth; + szHint.height_inc = TermWin.fheight; + + szHint.min_width = szHint.base_width + szHint.width_inc; + szHint.min_height = szHint.base_height + szHint.height_inc; + + szHint.width = szHint.base_width + TermWin.width; + szHint.height = szHint.base_height + TermWin.height; +#if (MENUBAR_MAX) + szHint.height += (delay_menu_drawing ? menuBar_TotalHeight() : 0); +#endif + + szHint.flags = PMinSize | PResizeInc | PBaseSize | PWinGravity; + + if (!init) { + font_change_count++; + resize(); + } + return; +#undef IDX2FNUM +#undef FNUM2IDX +#undef FNUM_RANGE +} diff --git a/src/command.h b/src/command.h new file mode 100644 index 0000000..bd5567f --- /dev/null +++ b/src/command.h @@ -0,0 +1,122 @@ +/*--------------------------------*-C-*---------------------------------* + * File: command.h + * + * Copyright 1992 John Bovey, University of Kent at Canterbury. + * + * You can do what you like with this source code as long as you don't try + * to make money out of it and you include an unaltered copy of this + * message (including the copyright). + * + * This module has been heavily modified by R. Nation + * + * No additional restrictions are applied. + * + * Additional modifications by mj olesen + * No additional restrictions are applied. + * + * As usual, the author accepts no responsibility for anything, nor does + * he guarantee anything whatsoever. + *----------------------------------------------------------------------*/ +#ifndef _COMMAND_H_ +# define _COMMAND_H_ +# include +# include +# include +# include +# include + +# ifdef USE_ACTIVE_TAGS +# include "activetags.h" +# endif + +# define menuBar_esc 10 +# define scrollBar_esc 30 + +/* Motif window hints */ +#define MWM_HINTS_FUNCTIONS (1L << 0) +#define MWM_HINTS_DECORATIONS (1L << 1) +#define MWM_HINTS_INPUT_MODE (1L << 2) +#define MWM_HINTS_STATUS (1L << 3) + +/* bit definitions for MwmHints.functions */ +#define MWM_FUNC_ALL (1L << 0) +#define MWM_FUNC_RESIZE (1L << 1) +#define MWM_FUNC_MOVE (1L << 2) +#define MWM_FUNC_MINIMIZE (1L << 3) +#define MWM_FUNC_MAXIMIZE (1L << 4) +#define MWM_FUNC_CLOSE (1L << 5) + +/* bit definitions for MwmHints.decorations */ +#define MWM_DECOR_ALL (1L << 0) +#define MWM_DECOR_BORDER (1L << 1) +#define MWM_DECOR_RESIZEH (1L << 2) +#define MWM_DECOR_TITLE (1L << 3) +#define MWM_DECOR_MENU (1L << 4) +#define MWM_DECOR_MINIMIZE (1L << 5) +#define MWM_DECOR_MAXIMIZE (1L << 6) + +/* bit definitions for MwmHints.inputMode */ +#define MWM_INPUT_MODELESS 0 +#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1 +#define MWM_INPUT_SYSTEM_MODAL 2 +#define MWM_INPUT_FULL_APPLICATION_MODAL 3 + +#define PROP_MWM_HINTS_ELEMENTS 5 + +/* Motif window hints */ +typedef struct _mwmhints { + CARD32 flags; + CARD32 functions; + CARD32 decorations; + INT32 input_mode; + CARD32 status; +} MWMHints; + +/* DEC private modes */ +# define PrivMode_132 (1LU<<0) +# define PrivMode_132OK (1LU<<1) +# define PrivMode_rVideo (1LU<<2) +# define PrivMode_relOrigin (1LU<<3) +# define PrivMode_Screen (1LU<<4) +# define PrivMode_Autowrap (1LU<<5) +# define PrivMode_aplCUR (1LU<<6) +# define PrivMode_aplKP (1LU<<7) +# define PrivMode_BackSpace (1LU<<8) +# define PrivMode_ShiftKeys (1LU<<9) +# define PrivMode_VisibleCursor (1LU<<10) +# define PrivMode_MouseX10 (1LU<<11) +# define PrivMode_MouseX11 (1LU<<12) +/* too annoying to implement X11 highlight tracking */ +/* #define PrivMode_MouseX11Track (1LU<<13) */ +# define PrivMode_scrollBar (1LU<<14) +# define PrivMode_menuBar (1LU<<15) + +#define PrivMode_mouse_report (PrivMode_MouseX10|PrivMode_MouseX11) +#define PrivMode(test,bit) do {\ +if (test) PrivateModes |= (bit); else PrivateModes &= ~(bit);} while (0) + +#define PrivMode_Default (PrivMode_Autowrap|PrivMode_ShiftKeys|PrivMode_VisibleCursor) + +extern char initial_dir[PATH_MAX+1]; +extern unsigned long PrivateModes; + +_XFUNCPROTOBEGIN + +# ifdef USE_ACTIVE_TAGS +pid_t cmd_pid; +int cmd_fd; +# endif +extern void init_command(char **); +extern void tt_resize(void); +extern void tt_write(const unsigned char *, unsigned int); +extern void tt_printf(const unsigned char *, ...); +extern unsigned int cmd_write(const unsigned char *, unsigned int); +extern void main_loop(void); +extern FILE *popen_printer(void); +extern int pclose_printer(FILE *); +extern void color_aliases (int idx); + +_XFUNCPROTOEND + +#endif /* _COMMAND_H_ */ +/*----------------------- end-of-file (C header) -----------------------*/ diff --git a/src/debug.h b/src/debug.h new file mode 100644 index 0000000..bc576c3 --- /dev/null +++ b/src/debug.h @@ -0,0 +1,105 @@ +/* debug.h for Eterm. + * 21 Feb 1998, vendu. + */ + +#ifndef _DEBUG_H +# define _DEBUG_H + +extern unsigned int debug_level; + +/* Assert macros stolen from my work on Ebar. If these macros break with your cpp, let me know -- mej@eterm.org */ +# define NOP ((void)0) + +#if defined(__FILE__) && defined(__LINE__) +# define ASSERT(x) do {if (!(x)) {if (debug_level>=1) {fatal_error("ASSERT failed at %s:%d: %s", __FILE__, __LINE__, #x);} \ + else {print_warning("ASSERT failed at %s:%d: %s", __FILE__, __LINE__, #x);}}} while (0); +#else +# define ASSERT(x) do {if (!(x)) {if (debug_level>=1) {fatal_error("ASSERT failed: %s", #x);} \ + else {print_warning("ASSERT failed: %s", #x);}}} while (0); +#endif + +#ifdef __FILE__ +#ifdef __LINE__ +#define __DEBUG() fprintf(stderr, "%s, line %d: ", __FILE__, __LINE__); +#endif +#endif + +#ifndef __DEBUG +#define __DEBUG() NOP +#endif + +/* Macros for printing debugging messages */ +# if DEBUG >= 1 +# ifndef DPRINTF +# define DPRINTF(x) do { if (debug_level >= 1) {__DEBUG(); real_dprintf x;} } while (0) +# endif +# define DPRINTF1(x) do { if (debug_level >= 1) {__DEBUG(); real_dprintf x;} } while (0) +# define DPRINTF2(x) do { if (debug_level >= 2) {__DEBUG(); real_dprintf x;} } while (0) +# define DPRINTF3(x) do { if (debug_level >= 3) {__DEBUG(); real_dprintf x;} } while (0) +# define DPRINTF4(x) do { if (debug_level >= 4) {__DEBUG(); real_dprintf x;} } while (0) +# define DPRINTF5(x) do { if (debug_level >= 5) {__DEBUG(); real_dprintf x;} } while (0) +# else +# ifndef DPRINTF +# define DPRINTF(x) NOP +# endif +# define DPRINTF1(x) NOP +# define DPRINTF2(x) NOP +# define DPRINTF3(x) NOP +# define DPRINTF4(x) NOP +# define DPRINTF5(x) NOP +# endif + +/* Debugging macros/defines which set the debugging levels for each output type. + To change the debugging level at which something appears, change the number in + both the DEBUG_ definition and the D_ macro (if there is one). -- mej */ + +# define DEBUG_SCREEN 1 +# define D_SCREEN(x) DPRINTF1(x) +# define DEBUG_CMD 1 +# define D_CMD(x) DPRINTF1(x) +# define DEBUG_TTY 1 +# define D_TTY(x) DPRINTF1(x) +# define DEBUG_SELECTION 1 +# define D_SELECT(x) DPRINTF1(x) +# define DEBUG_UTMP 1 +# define D_UTMP(x) DPRINTF1(x) +# define DEBUG_OPTIONS 1 +# define D_OPTIONS(x) DPRINTF1(x) +# define DEBUG_IMLIB 1 +# define D_IMLIB(x) DPRINTF1(x) +# define DEBUG_PIXMAP 1 +# define D_PIXMAP(x) DPRINTF1(x) +# define DEBUG_EVENTS 1 +# define D_EVENTS(x) DPRINTF1(x) +# define DEBUG_STRINGS 1 +# define D_STRINGS(x) DPRINTF1(x) + +# define DEBUG_X11 2 +# define D_X11(x) DPRINTF2(x) +# define DEBUG_SCROLLBAR 2 +# define D_SCROLLBAR(x) DPRINTF2(x) +# define DEBUG_THREADS 2 +# define D_THREADS(x) DPRINTF2(x) +# define DEBUG_TAGS 2 +# define D_TAGS(x) DPRINTF2(x) + +# define DEBUG_MENU 3 +# define D_MENUBAR(x) DPRINTF3(x) +# define DEBUG_TTYMODE 3 +# define D_TTYMODE(x) DPRINTF3(x) +# define DEBUG_COLORS 3 +# define D_COLORS(x) DPRINTF3(x) + +# define DEBUG_MALLOC 4 +# define D_MALLOC(x) DPRINTF4(x) +# define DEBUG_MENUARROWS 4 +# define D_MENUARROWS(x) DPRINTF4(x) +# define DEBUG_MENU_LAYOUT 4 +# define D_MENU_LAYOUT(x) DPRINTF4(x) +# define DEBUG_MENUBAR_STACKING 4 +# define D_MENUBAR_STACKING(x) DPRINTF4(x) + +# define DEBUG_X 5 + + +#endif /* _DEBUG_H */ diff --git a/src/eterm_imlib.h b/src/eterm_imlib.h new file mode 100644 index 0000000..06637e4 --- /dev/null +++ b/src/eterm_imlib.h @@ -0,0 +1,26 @@ +/* eterm_imlib.h - An include file for porting Eterm to use Imlib 1.0 + * in addition to Imlib 0.x. + * Feb 15 1998, vendu + */ + +#ifndef _ETERM_IMLIB_H +# define _ETERM_IMLIB_H + +# ifdef NEW_IMLIB +# include +# else if defined(OLD_IMLIB) +# include +# endif + +# ifdef NEW_IMLIB +# define ImColor ImlibColor +# define Image ImlibImage +# define ImlibInit(d) Imlib_init(d) +# define ImlibLoadImage(id,f,c) Imlib_load_image(id,f) +# define ImlibFreePixmap(id,p) Imlib_free_pixmap(id,p) +# define ImlibRender(id,i,w,h) Imlib_render(id,i,w,h) +# define ImlibCopyImageToPixmap(id,i) Imlib_copy_image(id,i) +# define ImlibDestroyImage(id,i) Imlib_destroy_image(id,i) +# endif + +#endif /* _ETERM_IMLIB_H */ diff --git a/src/feature.h.in b/src/feature.h.in new file mode 100644 index 0000000..bfdbb40 --- /dev/null +++ b/src/feature.h.in @@ -0,0 +1,527 @@ +/* feature.h -- Eterm feature defines header + * -- 10 Sept 1997, mej + * + * This file is original work by Michael Jennings and + * Tuomo Venalainen . This file, and any other file + * bearing this same message or a similar one, is distributed under + * the GNU Public License (GPL) as outlined in the COPYING file. + * + * Copyright (C) 1997, Michael Jennings and Tuomo Venalainen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + * + */ + +#ifndef _FEATURE_H_ +# define _FEATURE_H_ + +# include +# include + +# include "config.h" +# include "debug.h" + +/********************* Miscellaneous OS fixings *********************/ + +# if defined(hpux) && !defined(_HPUX_SOURCE) +# define _HPUX_SOURCE +# endif + +/* +# if defined(_HPUX_SOURCE) && !defined(SVR4) +# define SVR4 +# endif + */ + +# if defined(SVR4) && !defined(__svr4__) +# define __svr4__ +# endif +# if !defined(SVR4) && defined(__svr4__) +# define SVR4 +# endif + +# if defined(sun) && !defined(__sun__) +# define __sun__ +# endif +# if !defined(sun) && defined(__sun__) +# define sun +# endif + +# if defined (sun) +# undef HAVE_SYS_IOCTL_H +# endif + +# ifdef _SCO_DS /* SCO Osr5 */ +# define ALL_NUMERIC_PTYS /* Scos pty naming is /dev/[pt]typ0 - /dev/[pt]ty256 */ +# endif + +/********************* Debugging stuff *********************/ +/* As Keith Bunge would say, don't crap with the debugging stuff below + * unless you develop this mess. :^) -- mej + */ + +# ifndef DEBUG +# define DEBUG 0 +# endif + +/********************* Random development stuff ***************************/ +/* #define PROFILE */ +#ifdef PROFILE +/* #define PROFILE_SCREEN */ +/* #define PROFILE_X_EVENTS */ +/* #define COUNT_X_EVENTS */ +#endif +/* Active tags are disabled by default until we find a bug that crashes Eterm + * on window resize :( + */ +/* #define USE_ACTIVE_TAGS */ +#define OPTIMIZE_HACKS + +/********************* Color, screen, and image stuff *********************/ + +/* Allow pixmaps in the background of the window */ +# define PIXMAP_SUPPORT + +/* I'm having problems with this... The call to XInitThreads() in main.c seems + * to mess threads up on my system... They run "OK" for a while without that, + * but will make Eterm hang eventually. + */ +/* #define USE_POSIX_THREADS */ +/* Use mutexes for thread synchronization. */ +/* #define MUTEX_SYNCH */ + +/* Support for pseudo-transparency and viewport mode */ +# define PIXMAP_OFFSET + +/* Use Imlib for pseudo-transparency, shading, etc. Still experimental at + this point. -- mej */ +/* # define IMLIB_TRANS */ + +/* Support for background pixmap cycling */ +#define BACKGROUND_CYCLING_SUPPORT + +/* Pixmapped scrollbar. + */ +# define PIXMAP_SCROLLBAR + +/* Pixmapped menubar. + */ +# define PIXMAP_MENUBAR + +/* Enable use of backing store for the terminal window. */ +# define BACKING_STORE + +/* Use Rasterman's Imlib image library for image manipulation + * If you don't use Imlib, you won't be able to have background pixmaps */ +# define USE_IMLIB + +/* Define this to use Eterm with Imlib 0.x. Otherwise, it will use Imlib 1.0's + * API. + */ +/* #define OLD_IMLIB */ + +/* Define this to use Eterm with Imlib 1.x. This certainly is the Imlib you + * want to use. + */ + +# if defined(USE_IMLIB) && !defined(OLD_IMLIB) +# define NEW_IMLIB +# endif + +/* The environment variable in which Eterm looks for a search path for + config files and pixmaps */ +# define PATH_ENV "ETERMPATH" + +/* Enable support for themes. */ +# define USE_THEMES + +/* These are for future use. Defining them won't help anything, and it may + break stuff. */ +#define USE_EFFECTS + +/* Option to watch the desktop pixmap for changes. If the desktop background changes + a pseudo-transparent Eterm will find out about it and update to the new image */ +#define WATCH_DESKTOP_OPTION + +/* Disable support for changing the cursor color (-c and -t options) */ +/* #define NO_CURSORCOLOR */ + +/* Disable use of high-intensity colors 8-15. They will be simulated using + the "bold" font, colorBD, or overstrike */ +/* #define NO_BRIGHTCOLOR */ + +/* Disable separate colors for the bold and underline attributes */ +/* #define NO_BOLDUNDERLINE */ + +/* Disable simulation of bold font using an "overstrike" technique. This technique + has been known to cause pixel droppings, and its use is not advised. See + also FORCE_CLEAR_CHARS. */ +/* #define NO_BOLDOVERSTRIKE */ + +/* Disable the use of a separate "bold" font */ +/* #define NO_BOLDFONT */ + +/* Disable the secondary screen ("\E[?47h" / "\E[?47l") */ +/* #define NO_SECONDARY_SCREEN */ + +/* The number of screenfuls between refreshes. + * If you define this, it will be set to 3. + */ +/*#define REFRESH_PERIOD 3 */ +# define REFRESH_PERIOD 5 + +/* This will force clearing of characters before writing new ones on top of + * them. This is experimental - added in order to try and fix pixel dropping + * problems some people have had. See also NO_BOLDOVERSTRIKE. */ +# define FORCE_CLEAR_CHARS + +/* Rob Nation's graphics escape sequences */ +/* #define RXVT_GRAPHICS */ + +/* The command through which to pipe print-screen requests */ +#define PRINTPIPE "lp" + +/* If the screen can handle 24-bit graphics, force them */ +/* #define PREFER_24BIT */ + +/* Offer some support for the Offix DND (Drag 'n' Drop) protocol (untested) */ +/* #define OFFIX_DND */ + +/* Allows the -w and --border-width options for specifying the width of the + * border (in pixels) between the actual X client window and the program-useable + * terminal window. -- mej + */ +# define BORDER_WIDTH_OPTION + +/********************* Key and key-bindings options *********************/ + +/* Use the X server value for the Delete key, regardless */ +/* #define NO_DELETE_KEY */ + +/* Force the delete key to send ^? instead of ESC [ 3 ~ */ +/* #define KS_DELETE "\177" */ +#ifndef NO_DELETE_KEY +# define KS_DELETE "\177" +#endif + +/* Force the Backspace key to send ^H instead of checking the stty setting */ +#define FORCE_BACKSPACE +/* Force Backspace to send ^? */ +/* #define FORCE_DELETE */ + +/* Pick the hotkey for changing the font size */ +# define HOTKEY_CTRL +/* #define HOTKEY_META */ + +/* Use Home = "\E[1~" and End = "\E[4~" instead of Home = "\E[7~" and End = "\E[8~" */ +/* #define LINUX_KEYS */ +#ifdef linux +# define LINUX_KEYS +#endif + +/* Allow the "keysym" attribute in config files for remapping keysyms */ +#define KEYSYM_ATTRIBUTE + +/* Disable X11R6 support for European languages */ +/* #define NO_XLOCALE */ + +/* Allow unshifted Next and Prior keys to scroll, in addition to their shifted + * counterparts */ +/* #define UNSHIFTED_SCROLLKEYS */ + +/********************* Mouse, scrollbar, and menu bar options *********************/ + +/* Disable sending escape sequences from the scrollbar when mouse reporting + * is enabled */ +/* #define NO_SCROLLBAR_REPORT */ + +/* Set the default number of lines in the scrollback buffer */ +/* #define SAVELINES 256 */ + +/* Set the default separator characters for double-click word selection */ +#define CUTCHARS "\"&'()*,;<=>?@[\\]^`{|}~ \t" + +/* Make it an option */ +#define CUTCHAR_OPTION + +/* To activate double-click reporting for button 1 */ +/* #define MOUSE_REPORT_DOUBLECLICK */ + +/* The delay in milliseconds between multiple clicks */ +/* #define MULTICLICK_TIME 500 */ + +/* Support for the old xterm-style scrollbar */ +#define XTERM_SCROLLBAR + +/* Support for the traditional motif-style scrollbar */ +#define MOTIF_SCROLLBAR + +/* Support for a NeXT-style scrollbar */ +#define NEXT_SCROLLBAR + +/* Default scrollbar type */ +#define SCROLLBAR_DEFAULT_TYPE SCROLLBAR_MOTIF + +/* Scrollbar Colors */ +#define KEEP_SCROLLCOLOR + +/* The default width (in pixels) of the scrollbar. Should be an even number. */ +#define SB_WIDTH 10 + +/* Revert the scrollbar's color to the background color when the window loses focus */ +#define CHANGE_SCROLLCOLOR_ON_FOCUS + +/* Continuous scrolling by pressing the scrollbar arrow buttons */ +#define SCROLLBAR_BUTTON_CONTINUAL_SCROLLING + +/* To allow smooth refresh when the terminal window is fully unobscured. + * Didn't seem to cause a performance hit rolling a big amount of text + * on my Pentium-100 system (Linux) :)... Recommended :) + */ +#define USE_SMOOTH_REFRESH + +/* Delay periods for continuous scrolling */ +/* #define SCROLLBAR_INITIAL_DELAY 40 */ +/* #define SCROLLBAR_CONTINUOUS_DELAY 2 */ + +/* The maximum number of menubars that can be stacked. 1 disabled stacking, 0 + disables menubars altogether */ +#define MENUBAR_MAX 8 + +/* An alternative placement of the menubar shadow */ +/* #define MENUBAR_SHADOW_IN */ + +/* An alternative placement of the menu shadow */ +#define MENU_SHADOW_IN + +/* Allow Ctrl+Button1 in a window to raise and steal focus */ +#define CTRL_CLICK_RAISE + +/* Allow Ctrl+Button2 in a window to toggle the scrollbar */ +#define CTRL_CLICK_SCROLLBAR + +/* Allow Ctrl+Button3 in a window to toggle the menubar */ +#define CTRL_CLICK_MENU + +/********************* Multi-lingual support options *********************/ + +/* Allow option/attribute for Meta to set the 8th bit */ +#define META8_OPTION + +/* To include support for Greek Elot-928 and IBM-437 keyboard modes */ +/* #define GREEK_SUPPORT */ + +/* To compile as a Kanji terminal. Executable should be renamed "Kterm". */ +/* #define KANJI */ + +/********************* Miscellaneous options *********************/ + +/* To have $DISPLAY and the "\E[7n" response be IP addresses rather than FQDN's */ +/* #define DISPLAY_IS_IP */ + +/* To have "\E[7n" reply with the display name. This is a potential security risk, + * so its use is discouraged and unsupported. */ +/* #define ENABLE_DISPLAY_ANSWER */ + +/* To control what the Eterm detection sequence, ESC-Z, replies with */ +/* #define ESCZ_ANSWER "\033[?1;2C" */ + +/* Comment this out to allow printing of the VT100_ANS sequence. See + * command.c. I have no idea what this is supposed to do, but disabling + * it will prevent your terminal from getting garbage when ^E (ctrl-E) + * is printed on it. + */ +#define NO_VT100_ANS + +/* Checks the current value of the window title and icon name before setting them. + Can save unnecessary screen refreshes */ +#define SMART_WINDOW_TITLE + +/* Allow changing of the foreground and background colors with "\E]39;color^G" */ +/* #define XTERM_COLOR_CHANGE */ + +/* Exports TERM=xterm-color instead of just TERM=xterm */ +/* #define DEFINE_XTERM_COLOR */ + +/* Disable automatic de-iconify on bell altogether */ +/* #define NO_MAPALERT */ + +/* Make it an option */ +#define MAPALERT_OPTION + +/* Enable core dumps from Eterm. Not recommended for use by anyone but developers. */ +/* #define ENABLE_CORE_DUMPS */ + +/********************* utmp logging support *********************/ + +/* Enable utmp support. This has been tested and verified to work on Linux, + * FreeBSD, and HP-UX. Other operatings systems should work, but we have + * not been able to verify for sure that they do. Eterm *must* be setuid + * or setgid, usually setuid root, for this to work. Do it at your own risk. + */ +#define UTMP_SUPPORT + +/* Added security for systems with saved uids and gids. If you don't define + * this, and you're not on HP-UX with _HPUX_SOURCE defined, Eterm processes + * may seem to be owned by root. But if you define this and don't have them, + * the utmp and tty stuff could break. Do some testing. DO NOT get this one + * wrong! */ +/* #define HAVE_SAVED_UIDS */ + +/* Use getgrnam() to determine the group id of TTY_GRP_NAME, and chgrp tty + * device files to that group. This should be ok on SVR4 and Linux systems + * with group "tty" and on BSD systems with group "wheel" + */ +#define USE_GETGRNAME +#define TTY_GRP_NAME "tty" + +/********************* Config file parser options *********************/ + +/* Allow evaluation of expressions like `echo hello` in config files. The + * security-paranoid will not want to define this, but I have replaced the + * OS system() call with a secure one that I have tested and verified, so + * child processes run in this way will not run with any privileges, active + * or attainable. + */ +#define ALLOW_BACKQUOTE_EXEC + +/* This is the initial path that Eterm searches for its config file. + * By convention, this should be ".", then "~/.Eterm", then a global + * directory for all users like "/usr/local/lib/Eterm" */ +#define CONFIG_SEARCH_PATH "~/.Eterm/themes:~/.Eterm:@DATADIR@/Eterm/themes:@DATADIR@/Eterm" + +/* The name of the config file. "MAIN" by default. Don't change this + unless you have a darn good reason to. It's never been tested any other way. */ +#define CONFIG_FILE_NAME "MAIN" + +/* This causes Eterm to warn you if a config file it's about to parse was + * designed for an older version of Eterm. */ +/* #define WARN_OLDER */ + +/********************* Anti-cl00bie protection (sigh) *********************/ +/* EDITING THIS FILE BELOW THIS LINE IS UNSUPPORTED! YOU HAVE BEEN WARNED! */ + +#ifdef KANJI +# undef GREEK_SUPPORT +# undef XTERM_FONT_CHANGE +# undef DEFINE_XTERM_COLOR +# define KFONT0 "k14" +# define KFONT1 "jiskan16" +# define KFONT2 "jiskan18" +# define KFONT3 "jiskan24" +# define KFONT4 "jiskan26" +/* sizes matched to kanji fonts */ +# define FONT0 "7x14" +# define FONT1 "8x16" +# define FONT2 "9x18" +# define FONT3 "12x24" +# define FONT4 "13x26" +#else /* KANJI */ +# define FONT0 "7x14" +# define FONT1 "6x10" +# define FONT2 "6x13" +# define FONT3 "8x13" +# define FONT4 "9x15" +#endif /* KANJI */ +#define FONT0_IDX 2 + +#ifndef PIXMAP_SUPPORT +# undef USE_IMLIB +# undef OLD_IMLIB +# undef PIXMAP_SCROLLBAR +# undef PIXMAP_MENUBAR +# undef BACKING_STORE +# undef PIXMAP_OFFSET +# undef IMLIB_TRANS +# undef PIXMAP_BUFFERING +# undef BACKGROUND_CYCLING_SUPPORT +# undef WATCH_PIXMAP_OPTION +#endif + +#ifndef PIXMAP_OFFSET +# undef WATCH_DESKTOP_OPTION +#endif + +#if defined(XTERM_SCROLLBAR) && !defined(NO_MENUBAR) +# define NO_MENUBAR +#endif + +#ifndef TTY_GRP_NAME +# undef USE_GETGRNAME +#endif + +#ifndef HAVE_MEMMOVE +inline void *memmove(void *, const void *, size_t); +#endif + +#define APL_NAME "Eterm" /* The name of our beloved program */ + +/* COLORTERM, TERM environment variables */ +#ifdef KANJI +# define TERMENV "kterm" +# define COLORTERMENV "Kterm" +#else +# define TERMENV "xterm" +# define COLORTERMENV "Eterm" +#endif + +#ifdef NO_MOUSE_REPORT +# ifndef NO_MOUSE_REPORT_SCROLLBAR +# define NO_MOUSE_REPORT_SCROLLBAR +# endif +#endif + +#ifndef DEFAULT_BORDER_WIDTH +# define DEFAULT_BORDER_WIDTH 5 +#endif + +#ifndef SB_WIDTH +# define SB_WIDTH 10 +#endif + +#ifndef KEEP_SCROLLCOLOR +# undef CHANGE_SCROLLCOLOR_ON_FOCUS +#endif + +#ifndef MENUBAR_MAX +# define MENUBAR_MAX 0 +#endif + +#ifndef SAVELINES +# define SAVELINES 256 +#endif + +#ifdef NO_SECONDARY_SCREEN +# define NSCREENS 0 +#else +# define NSCREENS 1 +#endif + +#ifndef CUTCHARS +# define CUTCHARS "\"&'()*,;<=>?@[\\]^`{|}~" +#endif + +#if defined (__sun__) || defined (__svr4__) +# define NO_DELETE_KEY /* These systems seem to be anal this way*/ +#endif + +/* utmp doesn't work on CygWin32 */ +#ifdef __CYGWIN32__ +# undef UTMP_SUPPORT +#endif + +#endif /* _FEATURE_H_ */ diff --git a/src/graphics.c b/src/graphics.c new file mode 100644 index 0000000..916c1c9 --- /dev/null +++ b/src/graphics.c @@ -0,0 +1,556 @@ +/*--------------------------------*-C-*---------------------------------* + * File: graphics.c + * + * This module is all new by Rob Nation + * + * + * Modifications by mj olesen + * and Raul Garcia Garcia + *----------------------------------------------------------------------*/ + +static const char cvs_ident[] = "$Id$"; + +#include "main.h" + +#ifdef HAVE_UNISTD_H +# include +#endif +#include + +#include "command.h" /* for tt_printf() */ +#include "debug.h" +#include "graphics.h" +#include "screen.h" + +/* commands: + * 'C' = Clear + * 'F' = Fill + * 'G' = Geometry + * 'L' = Line + * 'P' = Points + * 'T' = Text + * 'W' = Window + */ + +#ifndef GRX_SCALE +# define GRX_SCALE 10000 +#endif + +/* extern functions referenced */ +/* extern variables referenced */ +/* extern variables declared here */ + +#ifdef RXVT_GRAPHICS +/* local variables */ +static int graphics_up = 0; + +typedef struct grcmd_t { + char cmd; + short color; + short ncoords; + int *coords; + unsigned char *text; + struct grcmd_t *next; +} grcmd_t; + +typedef struct grwin_t { + Window win; + int x, y; + unsigned int w, h; + short screen; + grcmd_t *graphics; + struct grwin_t *prev, *next; +} grwin_t; + +static grwin_t *gr_root = NULL; + +/*----------------------------------------------------------------------* + * local functions + */ +/* Gr_NewWindow() */ +static void +Gr_NewWindow(int nargs, int args[]) +{ + int x, y; + unsigned int w, h; + Window win; + grwin_t *grwin; + Cursor cursor; + + if (nargs != 4) { + print_error("NewWindow: 4 args needed, got %d\n", nargs); + return; + } + x = args[0] * TermWin.width / GRX_SCALE + TermWin.internalBorder; + y = args[1] * TermWin.height / GRX_SCALE + TermWin.internalBorder; + w = args[2] * TermWin.width / GRX_SCALE; + h = args[3] * TermWin.height / GRX_SCALE; + + win = XCreateSimpleWindow(Xdisplay, TermWin.vt, + x, y, w, h, + 0, + PixColors[fgColor], + PixColors[bgColor]); + + cursor = XCreateFontCursor(Xdisplay, XC_crosshair); + XDefineCursor(Xdisplay, win, cursor); + XMapWindow(Xdisplay, win); + XSelectInput(Xdisplay, win, ExposureMask); + + grwin = (grwin_t *) MALLOC(sizeof(grwin_t)); + grwin->win = win; + grwin->x = x; + grwin->y = y; + grwin->w = w; + grwin->h = h; + grwin->screen = 0; + grwin->prev = NULL; + grwin->next = gr_root; + if (grwin->next) + grwin->next->prev = grwin; + gr_root = grwin; + grwin->graphics = NULL; + graphics_up++; + + tt_printf("\033W%ld\n", (long) grwin->win); +} + +/* Gr_ClearWindow() */ +static void +Gr_ClearWindow(grwin_t * grwin) +{ + grcmd_t *cmd, *next; + + for (cmd = grwin->graphics; cmd != NULL; cmd = next) { + next = cmd->next; + free(cmd->coords); + if (cmd->text != NULL) + free(cmd->text); + free(cmd); + } + grwin->graphics = NULL; + XClearWindow(Xdisplay, grwin->win); +} + +/* Gr_Text() */ +/* + * arg [0] = x + * arg [1] = y + * arg [2] = alignment + * arg [3] = strlen (text) + */ +static void +Gr_Text(grwin_t * grwin, grcmd_t * data) +{ + int x, y, align; + + if (data->ncoords < 4 || data->text == NULL || *(data->text) == '\0') + return; + + x = data->coords[0] * grwin->w / GRX_SCALE; + y = data->coords[1] * grwin->h / GRX_SCALE; + align = data->coords[2]; + + if (align & RIGHT_TEXT) + x -= XTextWidth(TermWin.font, data->text, data->coords[3]); + else if (align & HCENTER_TEXT) + x -= (XTextWidth(TermWin.font, data->text, data->coords[3]) >> 1); + + if (align & TOP_TEXT) + y += TermWin.font->ascent; + else if (align & BOTTOM_TEXT) + y -= TermWin.font->descent; + + if (align & VCENTER_TEXT) + y -= TermWin.font->descent + ((TermWin.font->ascent + TermWin.font->descent) >> 1); + if (align & VCAPS_CENTER_TEXT) + y += (TermWin.font->ascent >> 1); + +# ifdef PIXMAP_SUPPORT + XClearArea(Xdisplay, grwin->win, + x, y, + Width2Pixel(data->coords[3]), + Height2Pixel(1), + 0); +# endif + XDrawString(Xdisplay, grwin->win, TermWin.gc, + x, y, + data->text, data->coords[3]); +} + +/* Gr_Geometry() */ +static void +Gr_Geometry(grwin_t * grwin, grcmd_t * data) +{ + if (grwin) + tt_printf("\033G%ld %d %d %u %u %d %d %ld %ld %d\n", + (long) grwin->win, + grwin->x, grwin->y, grwin->w, grwin->h, + TermWin.fwidth, + TermWin.fheight, + (long) GRX_SCALE * TermWin.fwidth / grwin->w, + (long) GRX_SCALE * TermWin.fheight / grwin->h, + Xdepth); + else /* rxvt terminal window size */ + tt_printf("\033G0 0 0 %d %d %d %d %ld %ld %d\n", + TermWin.width - 2 * TermWin.internalBorder, + TermWin.height - 2 * TermWin.internalBorder, + TermWin.fwidth, + TermWin.fheight, + (long) GRX_SCALE * TermWin.fwidth / (TermWin.width - 2 * TermWin.internalBorder), + (long) GRX_SCALE * TermWin.fheight / (TermWin.height - 2 * TermWin.internalBorder), + Xdepth); +} + +/* Gr_DestroyWindow() */ +static void +Gr_DestroyWindow(grwin_t * grwin) +{ + grcmd_t *cmd, *next; + + if (grwin == NULL) + return; + + for (cmd = grwin->graphics; cmd; cmd = next) { + next = cmd->next; + free(cmd->coords); + if (cmd->text != NULL) + free(cmd->text); + free(cmd); + } + + XDestroyWindow(Xdisplay, grwin->win); + if (grwin->next != NULL) + grwin->next->prev = grwin->prev; + if (grwin->prev != NULL) + grwin->prev->next = grwin->next; + else + gr_root = grwin->next; + free(grwin); + + graphics_up--; +} + +/* Gr_Dispatch() */ +static void +Gr_Dispatch(grwin_t * grwin, grcmd_t * data) +{ + int i, n; + union { + XPoint pt[NGRX_PTS / 2]; + XRectangle rect[NGRX_PTS / 4]; + } xdata; + + if (data->color != fgColor) { + XGCValues gcv; + + gcv.foreground = PixColors[data->color]; + XChangeGC(Xdisplay, TermWin.gc, GCForeground, &gcv); + } + if (grwin) + switch (data->cmd) { + case 'L': + if (data->ncoords > 3) { + for (n = i = 0; i < data->ncoords; i += 2, n++) { + xdata.pt[n].x = data->coords[i] * grwin->w / GRX_SCALE; + xdata.pt[n].y = data->coords[i + 1] * grwin->h / GRX_SCALE; + } + XDrawLines(Xdisplay, + grwin->win, TermWin.gc, xdata.pt, n, CoordModeOrigin); + } + break; + + case 'P': + if (data->ncoords > 3) { + for (n = i = 0; i < data->ncoords; i += 2, n++) { + xdata.pt[n].x = data->coords[i] * grwin->w / GRX_SCALE; + xdata.pt[n].y = data->coords[i + 1] * grwin->h / GRX_SCALE; + } + XDrawPoints(Xdisplay, + grwin->win, TermWin.gc, xdata.pt, n, CoordModeOrigin); + } + break; + + case 'F': + if (data->ncoords > 0) { + for (n = i = 0; i < data->ncoords; i += 4, n++) { + xdata.rect[n].x = data->coords[i] * grwin->w / GRX_SCALE; + xdata.rect[n].y = data->coords[i + 1] * grwin->h / GRX_SCALE; + xdata.rect[n].width = ((data->coords[i + 2] + - data->coords[i] + 1) * + grwin->w / GRX_SCALE); + xdata.rect[n].height = ((data->coords[i + 3] + - data->coords[i + 1] + 1) * + grwin->h / GRX_SCALE); + +# ifdef PIXMAP_SUPPORT + XClearArea(Xdisplay, grwin->win, + xdata.rect[n].x, + xdata.rect[n].y, + xdata.rect[n].width, + xdata.rect[n].height, + 0); +# endif + } + XFillRectangles(Xdisplay, grwin->win, TermWin.gc, xdata.rect, n); + } + break; + case 'T': + Gr_Text(grwin, data); + break; + case 'C': + Gr_ClearWindow(grwin); + break; + } + if (data->color != fgColor) { + XGCValues gcv; + + gcv.foreground = PixColors[fgColor]; + XChangeGC(Xdisplay, TermWin.gc, GCForeground, &gcv); + } +} + +/* Gr_Redraw() */ +static void +Gr_Redraw(grwin_t * grwin) +{ + grcmd_t *cmd; + + for (cmd = grwin->graphics; cmd != NULL; cmd = cmd->next) + Gr_Dispatch(grwin, cmd); +} + +#endif +/*----------------------------------------------------------------------* + * end of static functions + */ + +#ifdef RXVT_GRAPHICS +void +Gr_ButtonReport(int but, int x, int y) +{ + grwin_t *grwin; + + for (grwin = gr_root; grwin != NULL; grwin = grwin->next) + if ((x > grwin->x) && + (y > grwin->y) && + (x < grwin->x + grwin->w) && + (y < grwin->y + grwin->h)) + break; + + if (grwin == NULL) + return; + + x = GRX_SCALE * (x - grwin->x) / grwin->w; + y = GRX_SCALE * (y - grwin->y) / grwin->h; + tt_printf("\033%c%ld;%d;%d;\n", but, (long) grwin->win, x, y); +} + +/* Gr_do_graphics() */ +void +Gr_do_graphics(int cmd, int nargs, int args[], unsigned char *text) +{ + static Window last_id = None; + long win_id; + grwin_t *grwin; + grcmd_t *newcmd, *oldcmd; + int i; + + if (cmd == 'W') { + Gr_NewWindow(nargs, args); + return; + } + win_id = (nargs > 0) ? (Window) args[0] : None; + + if ((cmd == 'G') && (win_id == None)) { + Gr_Geometry(NULL, NULL); + return; + } + if ((win_id == None) && (last_id != None)) + win_id = last_id; + + if (win_id == None) + return; + + grwin = gr_root; + while ((grwin != NULL) && (grwin->win != win_id)) + grwin = grwin->next; + + if (grwin == NULL) + return; + + if (cmd == 'G') { + Gr_Geometry(grwin, NULL); + return; + } + nargs--; + args++; /* skip over window id */ + + /* record this new command */ + newcmd = (grcmd_t *) MALLOC(sizeof(grcmd_t)); + newcmd->ncoords = nargs; + newcmd->coords = (int *) MALLOC((newcmd->ncoords * sizeof(int))); + + newcmd->next = NULL; + newcmd->cmd = cmd; + newcmd->color = scr_get_fgcolor(); + newcmd->text = text; + + for (i = 0; i < newcmd->ncoords; i++) + newcmd->coords[i] = args[i]; + + /* + * If newcmd == fill, and rectangle is full window, drop all prior + * commands. + */ + if ((newcmd->cmd == 'F') && (grwin) && (grwin->graphics)) { + for (i = 0; i < newcmd->ncoords; i += 4) { + if ((newcmd->coords[i] == 0) && + (newcmd->coords[i + 1] == 0) && + (newcmd->coords[i + 2] == GRX_SCALE) && + (newcmd->coords[i + 3] == GRX_SCALE)) { + /* drop previous commands */ + oldcmd = grwin->graphics; + while (oldcmd->next != NULL) { + grcmd_t *tmp = oldcmd; + + oldcmd = oldcmd->next; + free(tmp); + } + grwin->graphics = NULL; + } + } + } + /* insert new command into command list */ + oldcmd = grwin->graphics; + if (oldcmd == NULL) + grwin->graphics = newcmd; + else { + while (oldcmd->next != NULL) + oldcmd = oldcmd->next; + oldcmd->next = newcmd; + } + Gr_Dispatch(grwin, newcmd); +} + +/* Gr_scroll() */ +void +Gr_scroll(int count) +{ + static short prev_start = 0; + grwin_t *grwin, *next; + + if ((count == 0) && (prev_start == TermWin.view_start)) + return; + + prev_start = TermWin.view_start; + + for (grwin = gr_root; grwin != NULL; grwin = next) { + next = grwin->next; + grwin->y -= (count * TermWin.fheight); +# ifdef USE_ACTIVE_TAGS + fprintf(stderr, "FUCK YOU!\n"); + if (grwin == TermWin.vt) + tag_hide(); +# endif + if ((grwin->y + grwin->h) < -(TermWin.saveLines * TermWin.fheight)) + Gr_DestroyWindow(grwin); + else + XMoveWindow(Xdisplay, grwin->win, + grwin->x, + grwin->y + (TermWin.view_start * TermWin.fheight)); + } +} + +/* Gr_ClearScreen() */ +void +Gr_ClearScreen(void) +{ + grwin_t *grwin, *next; + + for (grwin = gr_root; grwin != NULL; grwin = next) { + next = grwin->next; + if ((grwin->screen == 0) && (grwin->y + grwin->h > 0)) { + if (grwin->y >= 0) + Gr_DestroyWindow(grwin); + else + XResizeWindow(Xdisplay, grwin->win, + grwin->w, -grwin->y); + } + } +} + +/* Gr_ChangeScreen() */ +void +Gr_ChangeScreen(void) +{ + grwin_t *grwin, *next; + + for (grwin = gr_root; grwin != NULL; grwin = next) { + next = grwin->next; + if (grwin->y + grwin->h > 0) { + if (grwin->screen == 1) { + XMapWindow(Xdisplay, grwin->win); + grwin->screen = 0; + } else { + XUnmapWindow(Xdisplay, grwin->win); + grwin->screen = 1; + } + } + } +} + +/* Gr_expose() */ +void +Gr_expose(Window win) +{ + grwin_t *grwin; + + for (grwin = gr_root; grwin != NULL; grwin = grwin->next) { + if (grwin->win == win) { + Gr_Redraw(grwin); + break; + } + } +} + +/* Gr_Resize() */ +void +Gr_Resize(int w, int h) +{ + grwin_t *grwin; + + for (grwin = gr_root; grwin != NULL; grwin = grwin->next) { + if (TermWin.height != h) { + grwin->y += (TermWin.height - h); + XMoveWindow(Xdisplay, grwin->win, + grwin->x, + grwin->y + (TermWin.view_start * TermWin.fheight)); + } + Gr_Redraw(grwin); + } +} + +/* Gr_reset() */ +void +Gr_reset(void) +{ + grwin_t *grwin, *next; + + for (grwin = gr_root; grwin != NULL; grwin = next) { + next = grwin->next; + Gr_DestroyWindow(grwin); + } + + graphics_up = 0; +} + +/* Gr_Displayed() */ +int +Gr_Displayed(void) +{ + return graphics_up; +} + +#endif /* RXVT_GRAPHICS */ +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/graphics.h b/src/graphics.h new file mode 100644 index 0000000..594b24a --- /dev/null +++ b/src/graphics.h @@ -0,0 +1,63 @@ +/*--------------------------------*-C-*---------------------------------* + * File: graphics.h + * + *----------------------------------------------------------------------*/ + +#ifndef _GRAPHICS_H_ +# define _GRAPHICS_H_ +# include + +# include "grx.h" /* text alignment */ + +/* + * number of graphics points + * divisible by 2 (num lines) + * divisible by 4 (num rect) + */ +# define NGRX_PTS 1000 + +_XFUNCPROTOBEGIN + +extern void Gr_ButtonReport(int, int, int); + +extern void Gr_do_graphics (int /* cmd */, + int /* nargs */, + int /* args */[], + unsigned char * /* text */); + +extern void Gr_scroll (int /* count */); + +extern void Gr_ClearScreen (void); + +extern void Gr_ChangeScreen (void); + +extern void Gr_expose (Window /* win */); + +extern void Gr_Resize (int /* w */, + int /* h */); + +extern void Gr_reset (void); + +extern int Gr_Displayed (void); + +_XFUNCPROTOEND + +# ifdef RXVT_GRAPHICS +# define Gr_ButtonPress(x,y) Gr_ButtonReport ('P',(x),(y)) +# define Gr_ButtonRelease(x,y) Gr_ButtonReport ('R',(x),(y)) +# define GR_DISPLAY(x) if (Gr_Displayed()) (x) +# define GR_NO_DISPLAY(x) if (!Gr_Displayed()) (x) +# else +# define Gr_ButtonPress(x,y) ((void)0) +# define Gr_ButtonRelease(x,y) ((void)0) +# define Gr_scroll(count) ((void)0) +# define Gr_ClearScreen() ((void)0) +# define Gr_ChangeScreen() ((void)0) +# define Gr_expose(win) ((void)0) +# define Gr_Resize(w,h) ((void)0) +# define Gr_reset() ((void)0) +# define GR_DISPLAY(x) +# define GR_NO_DISPLAY(x) (x) +# endif +#endif /* whole file */ +/*----------------------- end-of-file (C header) -----------------------*/ diff --git a/src/graphics/.cvsignore b/src/graphics/.cvsignore new file mode 100644 index 0000000..282522d --- /dev/null +++ b/src/graphics/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/src/graphics/Makefile.am b/src/graphics/Makefile.am new file mode 100644 index 0000000..102e91d --- /dev/null +++ b/src/graphics/Makefile.am @@ -0,0 +1,11 @@ +# $Id$ + +bin_PROGRAMS = qplot + +qplot_SOURCES = grxlib.c qplot.c + +INCLUDES = -I. -I.. -I$(includedir) -I$(prefix)/include + +LDADD = -L. -L.. -L$(libdir) -L$(prefix)/lib + +install-exec-hook: diff --git a/src/graphics/README b/src/graphics/README new file mode 100644 index 0000000..463fba1 --- /dev/null +++ b/src/graphics/README @@ -0,0 +1 @@ +This is an example of rxvt graphics. diff --git a/src/graphics/data b/src/graphics/data new file mode 100644 index 0000000..fe864ac --- /dev/null +++ b/src/graphics/data @@ -0,0 +1,4000 @@ +6.37e+2 1.52e+2 +1.73e+2 5.13e+1 +1.77e+2 5.08e+1 +1.71e+2 1.83e+1 +1.82e+2 1.83e+1 +1.84e+2 1.83e+1 +1.86e+2 1.83e+1 +1.79e+2 5.07e+1 +7.07e+1 1.02e+2 +1.37e+1 1.14e+2 +1.76e+2 5.13e+1 +1.65e+2 5.23e+1 +1.80e+2 5.08e+1 +1.72e+2 5.18e+1 +6.33e+2 1.55e+2 +1.73e+2 5.13e+1 +2.94e+1 1.09e+2 +2.06e+1 1.12e+2 +6.32e+2 7.78e+1 +2.35e+1 1.11e+2 +1.81e+2 5.08e+1 +2.55e+1 1.11e+2 +6.31e+2 7.83e+1 +6.17e+2 6.20e+1 +2.16e+1 1.12e+2 +1.86e+1 1.12e+2 +3.04e+1 1.09e+2 +3.24e+1 1.09e+2 +6.30e+2 7.83e+1 +2.75e+1 1.10e+2 +3.34e+1 1.09e+2 +6.25e+2 1.59e+2 +6.29e+2 7.88e+1 +4.12e+1 1.07e+2 +4.42e+1 1.06e+2 +6.24e+2 1.60e+2 +6.23e+2 1.60e+2 +1.84e+2 5.08e+1 +1.89e+2 5.02e+1 +1.91e+2 4.99e+1 +3.44e+1 1.08e+2 +6.22e+2 1.81e+2 +6.24e+2 1.79e+2 +1.86e+2 5.08e+1 +1.85e+2 5.08e+1 +3.53e+1 1.08e+2 +4.62e+1 1.06e+2 +4.81e+1 1.05e+2 +6.21e+2 1.81e+2 +3.63e+1 1.08e+2 +3.83e+1 1.08e+2 +4.03e+1 1.08e+2 +6.19e+2 1.83e+2 +6.20e+2 1.62e+2 +6.22e+2 8.03e+1 +6.22e+2 1.20e+2 +6.24e+2 1.19e+2 +6.19e+2 1.63e+2 +6.21e+2 8.08e+1 +6.16e+2 1.85e+2 +6.20e+2 8.13e+1 +6.17e+2 1.64e+2 +6.19e+2 8.13e+1 +6.16e+2 1.65e+2 +6.15e+2 1.65e+2 +6.15e+2 8.29e+1 +1.63e+2 5.28e+1 +6.15e+2 1.24e+2 +6.13e+2 1.87e+2 +6.17e+2 8.23e+1 +6.11e+2 8.39e+1 +6.13e+2 8.34e+1 +5.30e+1 1.04e+2 +6.14e+2 1.24e+2 +6.12e+2 1.88e+2 +6.09e+2 8.44e+1 +5.60e+1 6.96e+1 +6.58e+1 1.02e+2 +6.13e+2 1.25e+2 +6.12e+2 1.25e+2 +6.10e+2 1.68e+2 +6.10e+2 1.26e+2 +6.09e+2 1.26e+2 +7.66e+1 7.12e+1 +6.58e+1 7.01e+1 +6.08e+2 1.90e+2 +6.10e+2 1.89e+2 +9.63e+1 9.85e+1 +5.99e+1 1.03e+2 +6.08e+2 1.69e+2 +9.43e+1 9.86e+1 +8.84e+1 7.06e+1 +6.05e+2 8.59e+1 +6.07e+2 1.91e+2 +9.83e+1 9.81e+1 +6.07e+2 1.69e+2 +6.05e+2 1.28e+2 +1.00e+2 9.80e+1 +8.55e+1 9.96e+1 +6.04e+2 1.29e+2 +6.02e+2 1.72e+2 +1.53e+2 7.01e+1 +6.06e+2 1.92e+2 +1.02e+2 9.76e+1 +1.04e+2 9.74e+1 +1.02e+2 7.06e+1 +9.24e+1 7.06e+1 +6.02e+2 1.29e+2 +8.65e+1 9.96e+1 +8.84e+1 9.96e+1 +1.12e+2 9.65e+1 +9.04e+1 9.91e+1 +9.24e+1 9.88e+1 +1.07e+2 9.70e+1 +1.51e+2 7.01e+1 +1.54e+2 7.01e+1 +1.56e+2 7.01e+1 +1.58e+2 7.01e+1 +1.09e+2 9.71e+1 +1.14e+2 9.66e+1 +1.15e+2 9.65e+1 +3.15e+2 1.99e+2 +1.04e+2 7.06e+1 +5.98e+2 1.96e+2 +6.03e+2 1.93e+2 +6.05e+2 1.92e+2 +5.99e+2 1.74e+2 +6.02e+2 1.94e+2 +1.47e+2 7.05e+1 +1.49e+2 7.10e+1 +1.25e+2 6.96e+1 +3.21e+2 7.06e+1 +1.28e+2 7.01e+1 +1.07e+2 7.12e+1 +1.24e+2 6.96e+1 +1.31e+2 6.96e+1 +1.05e+2 7.06e+1 +1.19e+2 7.06e+1 +1.21e+2 7.07e+1 +1.17e+2 9.66e+1 +1.19e+2 9.66e+1 +1.21e+2 9.66e+1 +5.99e+2 1.30e+2 +1.44e+2 6.96e+1 +1.41e+2 7.06e+1 +1.43e+2 7.06e+1 +1.37e+2 7.06e+1 +1.39e+2 7.12e+1 +5.97e+2 1.74e+2 +5.98e+2 1.74e+2 +5.97e+2 1.31e+2 +5.94e+2 1.31e+2 +1.33e+2 6.96e+1 +1.35e+2 6.95e+1 +5.96e+2 1.31e+2 +6.00e+2 1.95e+2 +1.17e+2 6.99e+1 +1.14e+2 7.12e+1 +1.15e+2 7.12e+1 +1.94e+2 7.01e+1 +5.96e+2 1.74e+2 +1.13e+2 7.12e+1 +2.07e+2 7.01e+1 +2.09e+2 7.01e+1 +1.10e+2 7.12e+1 +1.17e+2 1.92e+2 +5.95e+2 1.75e+2 +3.00e+2 7.06e+1 +5.92e+2 1.32e+2 +2.40e+2 9.46e+1 +2.23e+2 9.51e+1 +3.73e+1 7.06e+1 +5.91e+2 1.32e+2 +5.91e+2 1.98e+2 +2.13e+2 7.01e+1 +7.96e+1 7.12e+1 +5.90e+2 1.32e+2 +5.87e+2 1.33e+2 +5.89e+2 1.33e+2 +5.85e+2 1.99e+2 +5.86e+2 2.00e+2 +5.85e+2 1.33e+2 +5.84e+2 1.33e+2 +5.81e+2 1.34e+2 +6.09e+1 7.01e+1 +5.84e+2 2.00e+2 +5.80e+2 1.34e+2 +2.71e+2 5.18e+1 +5.79e+2 1.34e+2 +2.82e+2 5.34e+1 +3.08e+2 1.47e+2 +2.81e+2 5.34e+1 +5.79e+2 1.34e+2 +5.74e+2 1.81e+2 +5.76e+2 1.81e+2 +5.78e+2 1.81e+2 +2.85e+2 5.44e+1 +5.80e+2 2.01e+2 +2.86e+2 5.44e+1 +5.75e+2 1.36e+2 +5.77e+2 1.35e+2 +5.79e+2 2.01e+2 +6.68e+1 1.47e+2 +2.76e+2 5.28e+1 +2.78e+2 5.33e+1 +2.80e+2 5.34e+1 +5.73e+2 1.36e+2 +5.72e+2 1.36e+2 +5.71e+2 1.36e+2 +5.68e+2 1.38e+2 +2.89e+2 5.51e+1 +2.90e+2 5.54e+1 +5.69e+2 1.37e+2 +5.71e+2 9.14e+1 +5.73e+2 9.11e+1 +5.69e+2 9.15e+1 +5.68e+2 9.20e+1 +5.66e+2 9.20e+1 +3.99e+2 1.47e+2 +5.65e+2 9.19e+1 +2.86e+2 1.99e+2 +5.62e+2 9.25e+1 + +5.47e+2 9.40e+1 +5.49e+2 9.36e+1 +5.59e+2 9.25e+1 +5.61e+2 9.22e+1 +5.45e+2 9.46e+1 +5.41e+2 9.56e+1 +5.58e+2 9.25e+1 +5.50e+2 9.35e+1 +5.32e+2 9.61e+1 +5.55e+2 9.30e+1 +5.37e+2 9.61e+1 +5.39e+2 9.61e+1 +3.67e+2 2.28e+1 +3.87e+2 2.33e+1 +5.52e+2 9.35e+1 +5.54e+2 9.33e+1 +5.33e+2 9.61e+1 +3.55e+2 6.17e+1 +3.85e+2 2.33e+1 +5.34e+2 9.61e+1 +3.84e+2 2.33e+1 +3.40e+2 4.57e+1 +3.59e+2 6.30e+1 +3.61e+2 6.34e+1 +3.42e+2 4.57e+1 +3.51e+2 6.30e+1 +3.49e+2 4.52e+1 +3.50e+2 4.52e+1 +3.54e+2 4.47e+1 +3.47e+2 4.52e+1 +3.44e+2 4.57e+1 +3.46e+2 4.57e+1 +3.83e+2 2.33e+1 +3.51e+2 4.52e+1 +3.52e+2 4.47e+1 +3.43e+2 4.57e+1 +7.74e+2 2.33e+1 +3.88e+2 2.33e+1 +7.94e+2 2.28e+1 +3.89e+2 2.28e+1 +3.77e+2 6.45e+1 +3.63e+2 6.37e+1 +3.65e+2 6.40e+1 +3.90e+2 2.28e+1 +3.81e+2 6.51e+1 +3.82e+2 9.35e+1 +3.66e+2 6.40e+1 +3.82e+2 6.51e+1 +3.95e+2 2.28e+1 +3.57e+2 2.23e+1 +3.96e+2 2.23e+1 +7.92e+2 2.28e+1 +3.80e+2 1.30e+2 +3.59e+2 1.25e+2 +3.71e+2 4.62e+1 +3.83e+2 6.51e+1 +3.73e+2 6.45e+1 +3.71e+2 2.28e+1 +3.75e+2 4.62e+1 +3.76e+2 4.62e+1 +3.80e+2 2.33e+1 +3.90e+2 4.57e+1 +3.87e+2 6.45e+1 +3.85e+2 6.45e+1 +3.91e+2 2.28e+1 +3.85e+2 1.29e+2 +3.86e+2 1.29e+2 +3.84e+2 1.29e+2 +3.67e+2 6.40e+1 +3.87e+2 1.29e+2 +3.92e+2 2.28e+1 +3.70e+2 4.62e+1 +3.88e+2 1.29e+2 +3.70e+2 6.41e+1 +3.74e+2 6.96e+1 +3.80e+2 7.01e+1 +3.86e+2 4.62e+1 +3.82e+2 7.01e+1 +7.90e+2 2.28e+1 +3.76e+2 6.96e+1 +3.78e+2 6.96e+1 +3.77e+2 6.96e+1 +3.90e+2 1.27e+2 +3.77e+2 4.62e+1 +3.79e+2 2.33e+1 +3.82e+2 4.67e+1 +3.83e+2 7.01e+1 +7.75e+2 2.33e+1 +7.77e+2 2.33e+1 +7.79e+2 2.33e+1 +3.66e+2 4.63e+1 +3.68e+2 4.66e+1 +3.75e+2 6.96e+1 +3.80e+2 4.67e+1 +3.84e+2 4.62e+1 +3.85e+2 4.62e+1 +3.86e+2 6.96e+1 +5.85e+2 4.62e+1 +3.94e+2 1.27e+2 +3.91e+2 1.28e+2 +3.78e+2 4.67e+1 +7.62e+2 6.20e+1 +4.05e+2 2.23e+1 +5.87e+2 4.62e+1 +3.90e+2 6.91e+1 +3.94e+2 4.52e+1 +3.84e+2 6.96e+1 +3.62e+2 4.57e+1 +5.90e+2 4.50e+1 +5.92e+2 4.44e+1 +5.86e+2 4.62e+1 +3.73e+2 2.28e+1 +3.85e+2 6.96e+1 +7.96e+2 2.33e+1 +3.90e+2 6.40e+1 +5.06e+2 1.88e+1 +3.85e+2 1.93e+2 +3.75e+2 2.33e+1 +3.95e+2 4.52e+1 +3.77e+2 2.33e+1 +3.75e+2 1.29e+2 +3.96e+2 4.52e+1 +3.74e+2 2.33e+1 +3.96e+2 6.25e+1 +3.97e+2 6.25e+1 +3.92e+2 6.86e+1 +4.02e+2 2.23e+1 +3.98e+2 4.47e+1 +5.07e+2 3.76e+1 +3.94e+2 6.35e+1 +5.62e+2 1.88e+1 +3.97e+2 6.71e+1 +2.03e+2 1.99e+2 +4.10e+2 2.18e+1 +3.99e+2 6.25e+1 +7.88e+2 2.28e+1 +3.94e+2 6.80e+1 +3.96e+2 6.74e+1 +5.67e+2 1.94e+1 +5.69e+2 1.97e+1 +3.09e+2 1.99e+2 +4.00e+2 4.47e+1 +3.72e+2 1.28e+2 +4.03e+2 6.25e+1 +4.01e+2 6.20e+1 +4.04e+2 6.25e+1 +3.98e+2 6.71e+1 +4.00e+2 6.65e+1 +4.11e+2 2.13e+1 +4.04e+2 6.71e+1 +6.37e+2 5.13e+1 +4.05e+2 6.20e+1 +4.02e+2 1.24e+2 +4.05e+2 6.15e+1 +4.06e+2 6.20e+1 +6.40e+2 5.23e+1 +4.14e+2 6.15e+1 +4.16e+2 6.15e+1 +4.08e+2 6.15e+1 +4.10e+2 6.14e+1 +4.12e+2 6.11e+1 +4.03e+2 6.71e+1 +7.39e+2 3.76e+1 +7.61e+2 2.23e+1 +7.63e+2 2.26e+1 +7.65e+2 2.29e+1 +7.67e+2 2.32e+1 +6.41e+2 5.23e+1 +5.64e+2 1.88e+1 +5.08e+2 3.76e+1 +6.43e+2 5.39e+1 +5.71e+2 2.03e+1 +5.73e+2 2.08e+1 +5.75e+2 2.13e+1 +5.57e+2 5.08e+1 +5.59e+2 5.08e+1 +5.62e+2 5.28e+1 +5.63e+2 5.28e+1 +5.65e+2 5.36e+1 +7.52e+2 5.69e+1 +4.01e+2 4.47e+1 +7.49e+2 5.54e+1 +4.05e+2 1.23e+2 +4.07e+2 1.23e+2 +7.95e+2 4.62e+1 +7.51e+2 5.69e+1 +7.42e+2 3.83e+1 +4.12e+2 1.19e+2 +4.14e+2 1.18e+2 +4.02e+2 4.47e+1 +2.16e+2 1.99e+2 +4.16e+2 2.08e+1 +4.14e+2 1.98e+1 +4.05e+2 6.71e+1 +5.69e+2 5.59e+1 +6.42e+2 5.34e+1 +7.53e+2 5.79e+1 +5.10e+2 3.76e+1 +4.09e+2 6.56e+1 +5.19e+2 3.70e+1 +5.21e+2 3.67e+1 +4.05e+2 4.47e+1 +7.93e+2 4.62e+1 +5.70e+2 5.64e+1 +7.54e+2 5.83e+1 +7.56e+2 5.88e+1 +6.50e+2 5.69e+1 +6.52e+2 5.78e+1 +6.54e+2 5.82e+1 +4.05e+2 1.25e+2 +4.05e+2 4.42e+1 +6.46e+2 5.49e+1 +6.13e+2 5.39e+1 +7.47e+2 5.49e+1 +4.10e+2 4.32e+1 +7.50e+2 4.06e+1 +5.14e+2 3.76e+1 +4.10e+2 6.51e+1 +4.09e+2 4.37e+1 +5.68e+2 5.47e+1 +7.53e+2 4.17e+1 +6.17e+2 1.02e+2 +6.19e+2 1.01e+2 +5.13e+2 3.76e+1 +5.16e+2 3.76e+1 +4.19e+2 4.11e+1 +4.14e+2 6.35e+1 +4.21e+2 2.03e+1 +4.15e+2 6.30e+1 +4.11e+2 8.64e+1 +5.12e+2 3.76e+1 +2.39e+2 1.99e+2 +7.57e+2 2.18e+1 +4.16e+2 6.30e+1 +5.21e+2 1.02e+2 +7.75e+2 1.30e+2 +4.14e+2 4.24e+1 +4.16e+2 4.22e+1 +4.20e+2 2.03e+1 +4.20e+2 6.17e+1 +4.17e+2 6.30e+1 +6.90e+2 5.79e+1 +7.49e+2 4.01e+1 +4.13e+2 1.06e+2 +4.17e+2 2.08e+1 +4.23e+2 6.12e+1 +4.25e+2 6.10e+1 +7.67e+2 1.29e+2 +6.46e+2 1.94e+1 +7.63e+2 1.26e+2 +7.65e+2 1.29e+2 +4.22e+2 4.06e+1 +7.68e+2 1.29e+2 +7.70e+2 1.31e+2 +7.56e+2 2.16e+1 +5.73e+2 5.81e+1 +5.75e+2 5.88e+1 +7.47e+2 3.91e+1 +7.53e+2 2.08e+1 +4.21e+2 6.15e+1 +4.87e+2 5.08e+1 +7.77e+2 1.29e+2 +7.79e+2 1.29e+2 +7.58e+2 1.21e+2 +7.60e+2 1.23e+2 +7.55e+2 4.19e+1 +7.57e+2 4.20e+1 +7.71e+2 1.30e+2 +7.73e+2 1.30e+2 +7.53e+2 2.08e+1 +7.55e+2 1.17e+2 +7.57e+2 1.18e+2 +5.71e+2 5.69e+1 +7.61e+2 1.24e+2 +6.45e+2 5.44e+1 +7.53e+2 4.17e+1 +6.50e+2 2.05e+1 +5.04e+2 3.71e+1 +5.17e+2 5.23e+1 +7.59e+2 2.18e+1 +7.71e+2 4.62e+1 +7.44e+2 5.34e+1 +7.46e+2 5.37e+1 +6.48e+2 1.99e+1 +5.59e+2 1.53e+2 +6.92e+2 4.11e+1 +7.45e+2 3.86e+1 +7.41e+2 5.28e+1 +5.11e+2 1.05e+2 +5.13e+2 1.06e+2 +5.15e+2 1.06e+2 +6.94e+2 5.64e+1 +5.19e+2 5.13e+1 +5.18e+2 5.18e+1 +5.10e+2 1.05e+2 +7.46e+2 3.91e+1 +6.91e+2 5.74e+1 +6.56e+2 2.14e+1 +6.58e+2 2.17e+1 +6.94e+2 4.06e+1 +7.80e+2 4.62e+1 +6.95e+2 5.59e+1 +5.05e+2 1.03e+2 +5.07e+2 1.04e+2 +5.09e+2 1.05e+2 +4.94e+2 5.10e+1 +7.51e+2 1.12e+2 +7.35e+2 5.18e+1 +4.99e+2 1.01e+2 +5.01e+2 1.02e+2 +5.03e+2 1.02e+2 +6.44e+2 1.93e+1 +5.21e+2 5.10e+1 +5.22e+2 5.07e+1 +7.39e+2 5.23e+1 +4.18e+2 2.08e+1 +5.09e+2 5.23e+1 +7.40e+2 5.28e+1 +6.92e+2 5.74e+1 +7.50e+2 1.13e+2 +4.09e+2 2.01e+2 +5.12e+2 5.23e+1 +4.98e+2 1.01e+2 +4.88e+2 5.03e+1 +7.23e+2 1.78e+1 +5.08e+2 5.23e+1 +4.25e+2 4.01e+1 +7.03e+2 5.18e+1 +6.53e+2 2.11e+1 +7.07e+2 5.08e+1 +7.34e+2 5.18e+1 +6.37e+2 1.02e+2 +6.38e+2 1.02e+2 +7.04e+2 5.13e+1 +6.95e+2 3.99e+1 +4.97e+2 1.01e+2 +6.22e+2 9.96e+1 +4.96e+2 1.01e+2 +4.96e+2 5.03e+1 +4.98e+2 5.00e+1 +7.28e+2 1.83e+1 +4.86e+2 5.44e+1 +7.29e+2 1.02e+2 +3.46e+2 4.57e+1 +4.27e+2 4.01e+1 +7.22e+2 1.78e+1 +4.95e+2 1.00e+2 +4.91e+2 5.03e+1 +7.01e+2 5.23e+1 +7.30e+2 1.02e+2 +7.32e+2 1.03e+2 +7.34e+2 1.04e+2 +4.90e+2 5.03e+1 +4.09e+2 8.85e+1 +6.25e+2 5.28e+1 +7.05e+2 5.13e+1 +6.96e+2 3.91e+1 +7.31e+2 5.13e+1 +7.32e+2 5.13e+1 +4.25e+2 1.97e+1 +7.29e+2 1.83e+1 +7.00e+2 5.28e+1 +6.99e+2 5.34e+1 +4.91e+2 1.01e+2 +7.25e+2 1.00e+2 +7.27e+2 1.01e+2 +4.89e+2 1.01e+2 +6.98e+2 3.86e+1 +4.27e+2 2.03e+1 +7.27e+2 1.83e+1 +7.21e+2 9.86e+1 +4.26e+2 1.98e+1 +6.18e+2 5.08e+1 +6.20e+2 5.04e+1 +6.22e+2 5.01e+1 +7.26e+2 1.83e+1 +7.04e+2 5.59e+1 +7.32e+2 1.83e+1 +7.29e+2 5.13e+1 +4.25e+2 5.59e+1 +6.99e+2 3.81e+1 +4.28e+2 1.93e+1 +4.30e+2 4.01e+1 +7.09e+2 5.03e+1 +7.11e+2 4.99e+1 +7.13e+2 4.97e+1 +7.00e+2 3.76e+1 +7.02e+2 3.69e+1 +7.04e+2 3.66e+1 +4.93e+2 1.51e+2 +6.91e+2 1.15e+2 +7.25e+2 1.78e+1 +4.27e+2 5.59e+1 +5.05e+2 5.18e+1 +4.83e+2 1.01e+2 +7.33e+2 1.88e+1 +4.86e+2 1.01e+2 +7.26e+2 5.03e+1 +6.39e+2 1.88e+1 +4.80e+2 1.01e+2 +4.84e+2 1.01e+2 +4.23e+2 1.42e+2 +4.78e+2 1.01e+2 +4.74e+2 1.53e+2 +7.24e+2 5.03e+1 +4.94e+2 1.78e+1 +4.77e+2 1.01e+2 +4.84e+2 1.51e+2 +4.86e+2 1.51e+2 +4.73e+2 1.53e+2 +7.44e+2 1.93e+1 +4.94e+2 3.66e+1 +4.84e+2 3.61e+1 +4.79e+2 1.52e+2 +7.10e+2 1.78e+1 +7.35e+2 1.88e+1 +4.28e+2 5.59e+1 +7.42e+2 1.93e+1 +6.38e+2 1.88e+1 +4.76e+2 1.52e+2 +4.78e+2 1.52e+2 +4.73e+2 1.02e+2 +7.21e+2 4.93e+1 +7.23e+2 4.93e+1 +4.71e+2 1.54e+2 +7.20e+2 4.93e+1 +4.80e+2 1.83e+1 +5.04e+2 5.18e+1 +4.85e+2 1.83e+1 +6.37e+2 1.83e+1 +4.84e+2 1.83e+1 +4.30e+2 5.83e+1 +4.32e+2 5.94e+1 +4.77e+2 1.83e+1 +4.73e+2 3.66e+1 +6.36e+2 1.83e+1 +4.81e+2 1.83e+1 +4.32e+2 4.01e+1 +4.96e+2 3.61e+1 +4.98e+2 3.58e+1 +5.03e+2 1.88e+1 +5.05e+2 1.90e+1 +4.74e+2 3.66e+1 +7.39e+2 1.88e+1 +4.70e+2 1.02e+2 +4.68e+2 1.03e+2 +4.99e+2 1.83e+1 +4.21e+2 5.74e+1 +7.38e+2 1.88e+1 +4.93e+2 1.83e+1 +4.34e+2 4.01e+1 +4.76e+2 3.66e+1 +4.67e+2 1.03e+2 +7.12e+2 1.78e+1 +4.98e+2 1.83e+1 +4.79e+2 1.83e+1 +4.66e+2 1.03e+2 +4.72e+2 3.66e+1 +4.75e+2 5.48e+1 +4.77e+2 5.45e+1 +6.35e+2 1.83e+1 +4.78e+2 2.03e+1 +4.36e+2 4.06e+1 +4.71e+2 5.52e+1 +4.73e+2 5.51e+1 +7.37e+2 1.88e+1 +4.90e+2 3.61e+1 +4.35e+2 4.01e+1 +4.37e+2 4.11e+1 +4.69e+2 3.71e+1 +4.79e+2 3.66e+1 +4.81e+2 3.66e+1 +4.64e+2 1.04e+2 +4.68e+2 5.54e+1 +7.13e+2 1.78e+1 +7.15e+2 1.78e+1 +7.17e+2 1.78e+1 +7.30e+2 3.71e+1 +7.32e+2 3.78e+1 +4.33e+2 1.98e+1 +4.77e+2 5.07e+1 +4.79e+2 5.06e+1 +4.63e+2 1.06e+2 +5.07e+2 1.88e+1 +4.66e+2 5.59e+1 +4.35e+2 5.59e+1 +4.90e+2 1.83e+1 +4.87e+2 3.60e+1 +5.09e+2 1.88e+1 +4.74e+2 5.08e+1 +4.36e+2 5.64e+1 +4.39e+2 5.79e+1 +4.89e+2 3.61e+1 +4.55e+2 1.03e+2 +4.74e+2 1.83e+1 +4.76e+2 1.83e+1 +5.08e+2 1.88e+1 +4.73e+2 5.13e+1 +4.97e+2 1.83e+1 +5.58e+2 1.83e+1 +5.60e+2 1.83e+1 +4.57e+2 1.00e+2 +4.59e+2 9.82e+1 +4.62e+2 1.06e+2 +7.88e+2 2.28e+1 +4.96e+2 1.83e+1 +1.01e+2 7.88e+1 +4.41e+2 6.10e+1 +4.67e+2 3.71e+1 +4.35e+2 1.98e+1 +4.75e+2 1.83e+1 +4.39e+2 2.08e+1 +4.42e+2 4.47e+1 +4.65e+2 3.76e+1 +4.42e+2 6.15e+1 +4.41e+2 1.54e+2 +4.61e+2 1.09e+2 +4.60e+2 7.76e+1 +4.62e+2 7.63e+1 +4.64e+2 3.76e+1 +5.12e+2 1.88e+1 +5.14e+2 1.88e+1 +4.51e+2 8.90e+1 +4.41e+2 2.23e+1 +4.57e+2 5.59e+1 +4.63e+2 5.57e+1 +4.65e+2 5.47e+1 +4.61e+2 5.34e+1 +4.53e+2 8.59e+1 +4.40e+2 8.39e+1 +4.58e+2 7.93e+1 +4.42e+2 1.54e+2 +4.44e+2 1.57e+2 +4.46e+2 1.58e+2 +4.60e+2 1.98e+1 +4.44e+2 4.57e+1 +4.56e+2 8.13e+1 +4.52e+2 6.56e+1 +4.54e+2 6.40e+1 +4.40e+2 6.20e+1 +4.59e+2 3.91e+1 +4.60e+2 3.91e+1 +4.62e+2 3.81e+1 +4.62e+2 5.74e+1 +4.43e+2 1.97e+2 +4.61e+2 5.74e+1 +4.48e+2 1.84e+2 +4.44e+2 2.28e+1 +4.57e+2 4.01e+1 +4.56e+2 2.03e+1 +4.56e+2 1.25e+2 +4.44e+2 6.35e+1 +4.54e+2 1.93e+2 +4.56e+2 1.94e+2 +4.52e+2 1.53e+2 +4.54e+2 1.49e+2 +4.53e+2 4.32e+1 +4.55e+2 2.08e+1 +4.56e+2 4.06e+1 +4.45e+2 2.28e+1 +4.51e+2 1.55e+2 +4.71e+2 5.13e+1 +4.48e+2 1.92e+2 +4.50e+2 1.94e+2 +4.52e+2 1.94e+2 +4.56e+2 1.22e+2 +4.58e+2 1.17e+2 +4.60e+2 1.15e+2 +4.51e+2 4.42e+1 +4.49e+2 9.10e+1 +4.55e+2 1.05e+2 +6.11e+2 1.93e+1 +6.13e+2 1.93e+1 +4.50e+2 4.52e+1 +4.55e+2 1.24e+2 +4.42e+2 1.32e+2 +4.71e+2 1.83e+1 +4.48e+2 4.62e+1 +4.54e+2 2.08e+1 +4.48e+2 6.92e+1 +4.50e+2 6.94e+1 +4.48e+2 9.20e+1 +4.46e+2 9.10e+1 +4.57e+2 6.07e+1 +4.59e+2 5.93e+1 +4.53e+2 1.29e+2 +4.52e+2 1.31e+2 +4.46e+2 6.35e+1 +4.69e+2 1.83e+1 +4.43e+2 1.10e+2 +4.53e+2 1.09e+2 +4.52e+2 2.18e+1 +4.45e+2 1.36e+2 +4.51e+2 2.01e+2 +4.47e+2 6.40e+1 +4.45e+2 1.13e+2 +4.48e+2 6.40e+1 +4.45e+2 6.86e+1 +4.46e+2 6.86e+1 +4.48e+2 2.28e+1 +4.48e+2 1.29e+2 +4.50e+2 2.23e+1 +4.55e+2 6.20e+1 +4.44e+2 9.10e+1 +4.54e+2 6.30e+1 +4.64e+2 1.87e+1 +4.49e+2 4.57e+1 +4.60e+2 1.93e+1 +4.53e+2 6.45e+1 +4.49e+2 1.14e+2 +4.51e+2 1.14e+2 +4.53e+2 1.14e+2 +4.52e+2 6.10e+1 +4.49e+2 6.35e+1 +4.63e+2 5.28e+1 +4.42e+2 8.79e+1 +4.66e+2 1.88e+1 +4.78e+2 2.23e+1 + +4.63e+2 5.18e+1 +4.65e+2 1.88e+1 +4.64e+2 5.23e+1 +7.10e+2 5.03e+1 +5.05e+2 1.83e+1 +4.05e+2 8.90e+1 +7.77e+2 8.85e+1 +3.26e+2 9.96e+1 +4.59e+2 2.18e+1 +3.28e+2 1.02e+2 +3.30e+2 1.03e+2 +1.62e+2 8.13e+1 +1.63e+2 8.08e+1 +1.65e+2 8.05e+1 +6.97e+1 8.90e+1 +7.58e+2 8.90e+1 +5.78e+2 1.15e+2 +6.99e+2 8.82e+1 +6.36e+2 8.90e+1 +4.80e+2 8.90e+1 +4.24e+2 8.85e+1 +2.46e+2 6.86e+1 +7.50e+2 8.90e+1 +3.87e+2 8.90e+1 +2.54e+2 7.22e+1 +2.82e+2 8.90e+1 +5.89e+2 1.15e+2 +6.42e+2 8.90e+1 +1.73e+2 8.90e+1 +6.06e+2 1.93e+2 +5.91e+2 1.16e+2 +5.85e+2 1.14e+2 +5.87e+2 1.14e+2 +5.83e+2 1.14e+2 +4.86e+2 8.90e+1 +1.41e+2 1.47e+2 +5.20e+2 8.90e+1 +6.26e+2 1.19e+2 +6.28e+2 1.19e+2 +6.40e+2 1.19e+2 +7.07e+2 8.90e+1 +6.62e+2 1.19e+2 +3.70e+2 8.90e+1 +3.08e+2 8.90e+1 +3.10e+2 8.90e+1 +6.64e+2 1.19e+2 +6.66e+2 1.19e+2 +6.68e+2 1.19e+2 +7.13e+2 8.90e+1 +5.95e+2 1.19e+2 +3.28e+2 8.90e+1 +3.30e+2 8.90e+1 +3.03e+2 8.90e+1 +2.14e+2 1.75e+2 +6.44e+2 1.19e+2 +6.43e+2 1.19e+2 +3.92e+2 8.90e+1 +4.18e+2 1.47e+2 +1.57e+2 1.94e+2 +6.19e+2 1.19e+2 +6.21e+2 1.19e+2 +6.23e+2 1.19e+2 +6.55e+2 1.19e+2 +6.30e+2 1.19e+2 +4.30e+2 1.75e+2 +6.52e+2 1.19e+2 +5.86e+2 8.90e+1 +4.98e+2 8.90e+1 +6.56e+2 1.19e+2 +1.81e+2 8.90e+1 +6.36e+2 1.47e+2 +1.85e+2 8.90e+1 +1.87e+2 8.90e+1 +2.27e+2 8.90e+1 +6.38e+2 1.19e+2 +2.67e+2 8.90e+1 +6.53e+2 1.19e+2 +3.07e+2 1.75e+2 +6.32e+2 1.19e+2 +6.34e+2 1.19e+2 +3.95e+2 1.47e+2 +5.48e+2 1.75e+2 +6.01e+2 1.18e+2 +6.41e+2 1.19e+2 +6.49e+2 1.19e+2 +6.61e+2 1.19e+2 +3.52e+2 1.75e+2 +5.22e+2 1.46e+2 +6.18e+2 1.19e+2 +6.45e+2 1.19e+2 +6.47e+2 1.19e+2 +6.59e+2 1.19e+2 +5.48e+2 1.46e+2 +3.33e+2 8.90e+1 +3.96e+2 1.49e+2 +3.95e+2 8.85e+1 +5.45e+2 1.46e+2 +6.78e+2 1.50e+2 +5.43e+2 1.49e+2 +3.97e+2 1.48e+2 +3.99e+2 1.48e+2 +5.46e+2 8.90e+1 +6.16e+2 1.19e+2 +5.21e+2 1.48e+2 +2.17e+2 1.50e+2 +6.48e+2 1.19e+2 +6.17e+2 1.19e+2 +5.21e+2 1.47e+2 +5.23e+2 1.47e+2 +4.31e+2 1.78e+2 +9.04e+1 1.78e+2 +9.24e+1 1.81e+2 +5.94e+2 8.90e+1 +5.98e+2 1.19e+2 +1.83e+2 1.46e+2 +9.92e+1 1.48e+2 +1.01e+2 1.48e+2 +6.05e+2 1.19e+2 +6.07e+2 1.19e+2 +5.97e+2 1.75e+2 +2.68e+2 1.02e+2 +7.19e+2 1.48e+2 +3.96e+2 1.48e+2 +3.98e+2 1.48e+2 +6.38e+2 1.48e+2 +5.99e+2 1.78e+2 +6.01e+2 1.79e+2 +7.96e+2 7.87e+1 +2.01e+2 1.79e+2 +5.21e+2 8.90e+1 +5.51e+2 1.48e+2 +1.89e+2 8.90e+1 +1.74e+2 1.78e+2 +4.33e+2 1.79e+2 +6.09e+2 1.77e+2 +1.84e+2 1.78e+2 +5.42e+2 8.90e+1 +5.44e+2 8.90e+1 +7.13e+2 1.47e+2 +7.15e+2 1.47e+2 +2.20e+2 8.90e+1 +6.63e+2 8.90e+1 +1.83e+2 1.78e+2 +7.21e+2 8.90e+1 +3.54e+2 1.79e+2 +1.04e+2 1.46e+2 +5.52e+2 1.49e+2 +8.55e+1 1.48e+2 +6.95e+2 1.48e+2 +6.97e+2 1.48e+2 +7.36e+2 1.78e+2 +6.16e+2 1.78e+2 +6.22e+2 1.77e+2 +6.04e+2 1.79e+2 +6.12e+2 1.78e+2 +1.07e+2 1.48e+2 +6.15e+2 1.79e+2 +7.09e+2 8.90e+1 +2.81e+2 1.48e+2 +5.75e+2 1.11e+2 +1.85e+2 1.78e+2 +6.14e+2 1.79e+2 +4.49e+2 1.77e+2 +2.38e+2 1.78e+2 +3.27e+2 8.90e+1 +2.28e+2 1.79e+2 +1.91e+2 1.75e+2 +1.93e+2 1.73e+2 +1.95e+2 1.72e+2 +4.50e+2 1.78e+2 +4.36e+2 1.79e+2 +4.38e+2 1.79e+2 +6.08e+2 1.79e+2 +7.77e+2 1.74e+2 +6.13e+2 1.78e+2 +7.40e+2 1.80e+2 +2.23e+2 1.80e+2 +3.07e+2 1.46e+2 +1.57e+2 9.71e+1 +4.73e+2 1.75e+2 +1.26e+2 1.79e+2 +6.20e+2 1.78e+2 +7.80e+2 1.78e+2 +2.25e+2 1.78e+2 +2.92e+2 1.47e+2 +2.94e+2 1.46e+2 +2.82e+2 1.49e+2 +6.18e+2 1.79e+2 +7.91e+2 7.93e+1 +6.07e+2 1.79e+2 +6.30e+2 1.78e+2 +6.98e+2 1.78e+2 +7.17e+2 8.90e+1 +7.19e+2 8.90e+1 +3.05e+2 1.78e+2 +4.44e+2 1.79e+2 +6.06e+2 1.79e+2 +5.98e+2 1.78e+2 +7.96e+1 1.48e+2 +7.37e+2 1.78e+2 +7.55e+2 1.78e+2 +5.70e+2 1.47e+2 +6.09e+2 1.79e+2 +4.47e+2 1.78e+2 +4.51e+2 1.78e+2 +2.20e+2 1.78e+2 +2.19e+2 1.78e+2 +6.01e+2 8.90e+1 +1.24e+2 1.79e+2 +2.36e+2 1.78e+2 +4.33e+2 1.79e+2 +4.35e+2 1.80e+2 +2.17e+2 1.78e+2 +4.32e+2 1.79e+2 +5.25e+2 1.79e+2 +3.03e+2 1.80e+2 +2.19e+2 1.77e+2 +5.70e+1 1.78e+2 +5.43e+2 1.79e+2 +5.38e+2 1.79e+2 +5.42e+2 1.79e+2 +2.83e+2 1.79e+2 +7.95e+2 1.58e+2 +7.77e+2 1.78e+2 +7.51e+2 1.79e+2 +7.53e+2 1.80e+2 +2.15e+2 1.78e+2 +2.01e+2 1.78e+2 +5.79e+1 1.79e+2 +2.21e+2 1.78e+2 +7.37e+2 1.48e+2 +5.53e+2 1.49e+2 +2.84e+2 1.79e+2 +2.33e+2 1.78e+2 +2.35e+2 1.78e+2 +4.30e+2 1.77e+2 +6.88e+2 1.79e+2 +5.21e+2 1.78e+2 +5.16e+2 1.49e+2 +4.34e+2 1.78e+2 +6.14e+2 1.81e+2 +7.50e+2 1.78e+2 +2.24e+2 1.80e+2 +2.26e+2 1.81e+2 +5.32e+2 1.78e+2 +4.54e+2 1.78e+2 +6.98e+2 1.46e+2 +7.00e+2 1.46e+2 +6.12e+2 1.19e+2 +5.79e+2 1.48e+2 +4.42e+2 1.78e+2 +1.78e+2 1.78e+2 +5.21e+2 1.78e+2 +6.29e+1 1.51e+2 +6.48e+1 1.51e+2 +6.68e+1 1.52e+2 +6.28e+2 1.78e+2 +7.96e+2 1.78e+2 +6.13e+2 1.19e+2 +6.06e+2 1.75e+2 +7.95e+2 1.78e+2 +1.52e+2 9.56e+1 +6.82e+2 1.78e+2 +6.37e+2 1.19e+2 +5.45e+2 1.78e+2 +6.97e+2 1.79e+2 +5.36e+2 1.79e+2 +6.12e+2 1.79e+2 +7.93e+2 1.79e+2 +4.42e+2 1.79e+2 +1.88e+2 1.78e+2 +2.82e+2 1.50e+2 +2.84e+2 1.50e+2 +2.86e+2 1.50e+2 +5.05e+2 1.79e+2 +2.75e+2 1.47e+2 +6.85e+2 1.78e+2 +6.73e+2 1.79e+2 +1.84e+2 8.90e+1 +7.43e+2 1.75e+2 +6.95e+2 1.79e+2 +6.72e+2 1.78e+2 +5.60e+1 1.78e+2 +1.90e+2 1.79e+2 +6.71e+2 1.75e+2 +6.95e+2 1.47e+2 +5.46e+2 1.78e+2 +6.20e+2 1.79e+2 +7.47e+1 8.90e+1 +7.66e+1 8.99e+1 +1.05e+2 1.49e+2 +1.07e+2 1.49e+2 +1.10e+2 1.79e+2 +7.90e+2 7.98e+1 +4.26e+2 1.78e+2 +7.90e+2 1.78e+2 +2.89e+2 1.81e+2 +6.16e+2 1.79e+2 +6.18e+2 1.79e+2 +2.67e+2 1.78e+2 +5.30e+2 1.79e+2 +4.38e+2 1.79e+2 +4.36e+2 1.78e+2 +2.17e+2 1.79e+2 +2.89e+2 1.79e+2 +1.31e+2 1.78e+2 +1.76e+2 1.78e+2 +3.73e+1 8.85e+1 +3.93e+1 8.74e+1 +4.40e+2 1.78e+2 +2.00e+2 1.79e+2 +3.04e+2 1.50e+2 +7.87e+2 1.79e+2 +4.37e+2 1.78e+2 +4.23e+2 1.77e+2 +2.66e+2 1.78e+2 +5.97e+2 1.47e+2 +5.99e+2 1.46e+2 +1.23e+2 1.78e+2 +6.95e+2 1.79e+2 +4.05e+2 1.78e+2 +2.11e+2 8.85e+1 +3.06e+2 1.79e+2 +5.54e+2 1.49e+2 +6.86e+2 1.79e+2 +2.14e+2 1.78e+2 +7.02e+2 1.79e+2 +1.66e+2 1.78e+2 +3.07e+2 1.79e+2 +4.41e+2 1.78e+2 +5.20e+2 1.78e+2 +2.86e+2 1.79e+2 +5.12e+2 1.79e+2 +7.57e+2 1.77e+2 +2.79e+2 1.49e+2 +3.44e+1 9.15e+1 +3.63e+1 9.34e+1 +1.33e+2 1.78e+2 +6.73e+2 8.90e+1 +2.16e+2 1.81e+2 +7.84e+2 1.78e+2 +5.61e+2 1.49e+2 +5.34e+2 1.79e+2 +1.09e+2 1.79e+2 +1.08e+2 1.79e+2 +1.05e+2 1.80e+2 +1.97e+2 1.78e+2 +3.50e+2 1.78e+2 +7.49e+2 1.48e+2 +1.64e+2 1.79e+2 +2.90e+2 1.79e+2 +1.13e+2 1.78e+2 +7.33e+2 1.78e+2 +6.22e+2 1.80e+2 +6.74e+2 1.78e+2 +4.22e+2 1.78e+2 +1.37e+2 1.80e+2 +4.04e+2 1.80e+2 +4.75e+2 1.78e+2 +5.76e+2 1.16e+2 +5.78e+2 1.25e+2 +5.79e+2 1.28e+2 +5.07e+2 1.79e+2 +5.99e+1 1.79e+2 +6.75e+2 1.79e+2 +2.28e+2 1.75e+2 +5.15e+2 1.78e+2 +2.30e+2 1.79e+2 +3.64e+2 1.79e+2 +2.03e+2 1.78e+2 +3.90e+2 1.78e+2 +5.08e+2 1.79e+2 +3.89e+2 1.78e+2 +2.42e+2 1.77e+2 +1.78e+2 1.46e+2 +2.45e+2 1.49e+2 +1.45e+2 1.80e+2 +2.02e+2 1.79e+2 +7.37e+1 1.78e+2 +7.85e+2 1.79e+2 +3.01e+2 1.78e+2 +6.92e+2 1.78e+2 +7.83e+2 1.78e+2 +1.96e+2 1.78e+2 +5.59e+2 1.49e+2 +1.22e+2 1.79e+2 +4.14e+2 1.78e+2 +5.65e+2 1.48e+2 +6.43e+2 1.78e+2 +3.46e+2 1.78e+2 +6.19e+1 1.51e+2 +4.04e+2 1.49e+2 +4.43e+2 1.79e+2 +4.45e+2 1.79e+2 +7.47e+1 1.80e+2 +1.34e+2 1.79e+2 +6.48e+1 1.79e+2 +7.82e+2 1.78e+2 +6.27e+2 1.79e+2 +1.82e+2 1.48e+2 +3.61e+2 1.78e+2 +1.44e+2 1.79e+2 +5.80e+2 1.79e+2 +6.52e+2 1.78e+2 +4.01e+2 1.78e+2 +5.77e+2 1.49e+2 +9.73e+1 1.49e+2 +4.77e+2 1.48e+2 +7.86e+0 1.48e+2 +3.55e+2 1.79e+2 +6.49e+2 1.78e+2 +6.09e+2 1.19e+2 +6.11e+2 1.19e+2 +5.10e+2 1.78e+2 +2.44e+2 1.78e+2 +3.54e+2 1.49e+2 +3.56e+2 1.50e+2 +2.10e+2 1.78e+2 +3.08e+2 1.78e+2 +3.18e+2 1.79e+2 +7.12e+2 1.78e+2 +1.11e+2 1.49e+2 +1.78e+2 1.79e+2 +1.80e+2 1.79e+2 +6.80e+2 1.79e+2 +9.92e+1 1.79e+2 +7.79e+2 1.79e+2 +5.31e+2 1.47e+2 +5.33e+2 1.46e+2 +2.46e+2 1.49e+2 +5.75e+2 1.78e+2 +5.09e+2 1.78e+2 +1.86e+2 1.48e+2 +2.54e+2 1.49e+2 +2.30e+2 1.79e+2 +5.76e+2 1.79e+2 +2.83e+2 1.49e+2 +3.79e+2 1.49e+2 +5.82e+2 1.48e+2 +1.03e+2 1.80e+2 +6.68e+1 1.49e+2 +1.54e+2 1.80e+2 +5.19e+2 1.78e+2 +6.88e+0 1.49e+2 +1.04e+2 1.79e+2 +7.88e+2 1.79e+2 +5.43e+2 1.50e+2 +6.53e+2 1.79e+2 +4.18e+2 1.78e+2 +4.20e+2 1.78e+2 +1.09e+2 1.49e+2 +9.24e+1 1.79e+2 +1.06e+2 1.79e+2 +5.37e+2 1.48e+2 +6.19e+1 1.79e+2 +6.58e+1 1.78e+2 +6.62e+2 1.79e+2 +4.92e+2 1.78e+2 +6.97e+1 1.49e+2 +6.37e+2 1.49e+2 +4.00e+2 1.79e+2 +5.30e+1 1.47e+2 +2.40e+2 1.79e+2 +2.61e+2 1.79e+2 +1.98e+2 1.79e+2 +2.80e+2 1.79e+2 +5.18e+2 1.78e+2 +7.47e+2 1.49e+2 +5.93e+2 1.49e+2 +5.73e+2 1.48e+2 +2.40e+2 1.49e+2 +1.60e+2 1.79e+2 +2.09e+2 1.78e+2 +5.57e+2 1.48e+2 +5.86e+2 1.48e+2 +6.70e+2 1.80e+2 +7.22e+2 8.85e+1 +7.24e+2 8.82e+1 +7.26e+2 8.79e+1 +2.40e+2 1.78e+2 +5.55e+2 1.49e+2 +6.35e+2 1.79e+2 +4.94e+2 1.77e+2 +3.57e+2 1.79e+2 +6.48e+2 1.79e+2 +6.46e+2 1.79e+2 +3.59e+2 1.79e+2 +6.24e+2 1.78e+2 +2.12e+2 1.80e+2 +4.87e+2 1.78e+2 +7.59e+2 1.78e+2 +2.39e+2 1.49e+2 +3.76e+2 1.79e+2 +1.55e+2 1.79e+2 +7.84e+2 8.74e+1 +6.56e+2 1.79e+2 +7.45e+2 1.49e+2 +2.45e+2 1.80e+2 +2.47e+2 1.81e+2 +3.79e+2 1.80e+2 +3.48e+2 1.78e+2 +1.40e+2 1.79e+2 +2.38e+2 1.49e+2 +5.55e+2 1.47e+2 +5.88e+2 1.79e+2 +6.90e+2 1.49e+2 +5.58e+2 1.49e+2 +3.84e+2 1.79e+2 +2.88e+2 1.49e+2 +7.44e+2 1.79e+2 +7.41e+2 1.78e+2 +5.62e+2 1.78e+2 +7.50e+2 1.48e+2 +2.04e+2 1.78e+2 +3.09e+2 1.78e+2 +6.23e+2 1.79e+2 +4.71e+1 1.50e+2 +3.19e+2 1.79e+2 +7.48e+2 1.78e+2 +5.86e+2 1.79e+2 +4.91e+1 1.48e+2 +7.25e+2 1.49e+2 +7.27e+2 1.51e+2 +5.79e+1 1.51e+2 +5.99e+1 1.51e+2 +3.83e+1 1.47e+2 +1.87e+2 1.49e+2 +3.17e+2 1.78e+2 +2.60e+2 1.80e+2 +5.82e+2 1.79e+2 +8.45e+1 1.49e+2 +7.66e+2 1.79e+2 +3.95e+2 1.79e+2 +5.57e+2 1.78e+2 +5.01e+2 1.79e+2 +7.08e+2 1.78e+2 +7.22e+2 1.45e+2 +6.22e+2 1.47e+2 +2.56e+2 1.49e+2 +5.66e+2 1.79e+2 +5.81e+2 1.78e+2 +3.93e+2 1.79e+2 +5.83e+2 1.79e+2 +3.00e+2 1.49e+2 +6.59e+2 1.79e+2 +7.11e+2 1.79e+2 +7.56e+1 1.79e+2 +1.70e+2 1.79e+2 +4.50e+2 8.90e+1 +4.52e+2 8.90e+1 +4.82e+2 1.78e+2 +5.96e+2 1.49e+2 +3.75e+2 1.78e+2 +1.63e+2 1.79e+2 +4.61e+2 1.49e+2 +1.67e+1 1.48e+2 +2.97e+2 1.49e+2 +7.74e+2 1.79e+2 +8.74e+1 1.78e+2 +2.77e+2 1.79e+2 +9.63e+1 1.79e+2 +5.16e+2 1.80e+2 +2.96e+2 1.79e+2 +5.84e+2 1.48e+2 +2.71e+2 1.79e+2 +7.71e+2 1.78e+2 +3.73e+2 1.78e+2 +1.76e+2 1.48e+2 +4.83e+2 1.79e+2 +4.85e+2 1.79e+2 +5.56e+2 1.79e+2 +6.89e+2 1.49e+2 +6.79e+2 1.79e+2 +5.44e+2 1.49e+2 +6.35e+2 1.49e+2 +3.83e+2 1.78e+2 +5.65e+2 1.79e+2 +7.06e+2 1.78e+2 +6.41e+2 1.79e+2 +1.89e+2 1.78e+2 +7.36e+2 1.78e+2 +4.86e+2 1.78e+2 +4.77e+2 1.79e+2 +4.83e+2 1.48e+2 +1.59e+2 1.79e+2 +1.17e+2 1.78e+2 +3.74e+2 1.79e+2 +1.21e+2 1.81e+2 +6.68e+1 1.79e+2 +2.74e+2 1.80e+2 +5.49e+2 1.79e+2 +5.21e+1 1.46e+2 +4.80e+2 1.78e+2 +1.74e+2 1.49e+2 +5.74e+2 1.49e+2 +6.45e+2 1.79e+2 +8.06e+1 1.81e+2 +4.11e+2 1.78e+2 +4.17e+2 1.77e+2 +4.06e+2 1.49e+2 +4.80e+2 1.79e+2 +4.82e+2 1.79e+2 +6.95e+2 1.49e+2 +5.73e+2 1.80e+2 +5.61e+2 1.79e+2 +9.24e+1 1.49e+2 +6.38e+2 1.78e+2 +4.76e+2 1.50e+2 +4.78e+2 1.78e+2 +9.83e+1 1.48e+2 +7.66e+2 1.49e+2 +3.81e+2 1.50e+2 +3.83e+2 1.51e+2 +3.85e+2 1.51e+2 +2.34e+2 1.80e+2 +3.58e+2 1.79e+2 +6.19e+2 1.47e+2 +2.72e+2 1.80e+2 +3.75e+2 1.48e+2 +3.40e+2 1.78e+2 +7.62e+2 1.77e+2 +3.65e+2 1.79e+2 +5.64e+2 1.79e+2 +9.63e+1 1.49e+2 +5.01e+1 1.50e+2 +8.65e+1 1.49e+2 +4.27e+2 1.49e+2 +1.14e+2 1.49e+2 +6.39e+2 1.78e+2 +3.52e+2 1.78e+2 +2.23e+2 1.48e+2 +3.34e+2 8.90e+1 +3.36e+2 8.90e+1 +9.83e+0 1.48e+2 +2.38e+2 1.80e+2 +7.34e+2 1.78e+2 +2.53e+2 1.50e+2 +2.89e+2 1.51e+2 +9.33e+1 1.49e+2 +7.70e+2 1.75e+2 +7.72e+2 1.72e+2 +7.74e+2 1.70e+2 +6.05e+2 1.48e+2 +7.26e+2 1.78e+2 +5.59e+2 1.79e+2 +6.63e+2 1.79e+2 +2.35e+2 1.48e+2 +2.33e+2 1.79e+2 +5.63e+2 1.49e+2 +7.66e+1 1.78e+2 +5.46e+2 1.48e+2 +7.73e+2 1.78e+2 +2.58e+2 1.79e+2 +8.35e+1 1.78e+2 +6.03e+2 8.82e+1 +3.52e+2 1.46e+2 +1.42e+2 1.78e+2 +4.48e+2 1.49e+2 +1.08e+1 1.49e+2 +2.45e+2 1.79e+2 +3.41e+2 1.81e+2 +2.05e+2 1.48e+2 +9.04e+1 1.49e+2 +5.62e+2 1.49e+2 +2.67e+2 1.46e+2 +4.28e+2 1.47e+2 +5.45e+2 1.49e+2 +3.80e+2 1.79e+2 +4.76e+2 1.78e+2 +2.75e+1 1.46e+2 +2.94e+1 1.44e+2 +4.22e+1 1.49e+2 +5.48e+2 8.83e+1 +3.97e+2 1.78e+2 +7.07e+1 1.79e+2 +8.84e+1 1.79e+2 +7.07e+2 1.79e+2 +4.78e+2 1.79e+2 +3.76e+2 1.49e+2 +5.92e+2 1.79e+2 +3.18e+2 1.48e+2 +4.05e+2 1.49e+2 +5.11e+1 8.90e+1 +2.73e+2 1.79e+2 +4.71e+2 1.78e+2 +1.16e+2 1.80e+2 +2.22e+2 1.49e+2 +7.70e+2 1.79e+2 +7.80e+2 8.90e+1 +4.98e+2 1.79e+2 +6.97e+1 1.79e+2 +2.57e+2 1.78e+2 +2.55e+2 1.49e+2 +3.78e+2 1.48e+2 +6.03e+2 1.80e+2 +6.05e+2 1.80e+2 +1.80e+2 1.45e+2 +2.06e+2 1.79e+2 +5.78e+2 1.48e+2 +3.79e+2 8.90e+1 +5.72e+2 1.79e+2 +1.86e+1 1.49e+2 +5.67e+2 1.79e+2 +6.57e+2 1.78e+2 +2.95e+2 1.78e+2 +2.54e+2 1.49e+2 +5.11e+1 1.48e+2 +1.13e+2 1.49e+2 +6.03e+2 1.47e+2 +4.74e+2 1.49e+2 +3.15e+2 1.79e+2 +7.04e+2 1.79e+2 +7.24e+2 1.78e+2 +7.64e+2 1.51e+2 +7.48e+2 1.49e+2 +8.55e+1 1.79e+2 +1.15e+2 1.49e+2 +1.16e+2 1.48e+2 +6.00e+2 1.78e+2 +5.96e+2 1.78e+2 +4.93e+2 1.79e+2 +7.53e+2 1.50e+2 +7.54e+2 1.50e+2 +3.05e+2 1.49e+2 +2.59e+2 1.81e+2 +6.73e+2 1.49e+2 +5.23e+2 8.90e+1 +2.75e+2 1.49e+2 +2.86e+2 1.49e+2 +7.18e+2 1.49e+2 +6.72e+2 1.49e+2 +3.67e+2 1.78e+2 +4.11e+2 1.50e+2 +4.73e+2 1.78e+2 +4.14e+2 1.49e+2 +4.12e+1 1.49e+2 +4.91e+2 1.78e+2 +4.12e+2 1.48e+2 +4.52e+2 1.48e+2 +3.42e+2 1.80e+2 +2.29e+2 1.48e+2 +3.38e+2 1.78e+2 +1.67e+1 1.49e+2 +4.10e+2 1.49e+2 +5.64e+2 1.49e+2 +6.34e+2 1.49e+2 +4.84e+2 1.48e+2 +4.80e+2 1.47e+2 +4.82e+2 1.46e+2 +7.25e+2 1.78e+2 +4.86e+2 1.81e+2 +4.88e+2 1.81e+2 +4.90e+2 1.82e+2 +4.25e+2 1.50e+2 +5.48e+2 1.49e+2 +6.64e+2 1.48e+2 +6.70e+2 1.51e+2 +7.68e+2 1.82e+2 +2.03e+2 8.90e+1 +2.07e+2 1.49e+2 +4.59e+2 1.50e+2 +3.27e+2 1.49e+2 +3.53e+1 1.49e+2 +2.02e+2 1.48e+2 +2.04e+2 1.48e+2 +7.24e+2 1.50e+2 +3.05e+2 8.90e+1 +3.07e+2 8.90e+1 +4.13e+2 1.48e+2 +1.86e+2 1.78e+2 +5.71e+2 1.49e+2 +5.97e+2 1.78e+2 +3.96e+2 1.49e+2 +6.65e+2 1.49e+2 +6.78e+2 1.80e+2 +8.74e+1 1.48e+2 +7.11e+2 1.48e+2 +6.77e+2 1.79e+2 +1.73e+2 1.49e+2 +7.38e+2 1.79e+2 +9.43e+1 1.48e+2 +2.12e+2 1.48e+2 +4.03e+1 8.90e+1 +4.22e+1 8.86e+1 +4.42e+1 8.89e+1 +3.82e+2 1.79e+2 +5.91e+2 1.79e+2 +3.97e+2 1.50e+2 +5.42e+2 1.49e+2 +3.34e+2 1.78e+2 +4.58e+2 1.79e+2 +4.71e+1 1.48e+2 +7.05e+2 1.78e+2 +5.77e+2 1.50e+2 +4.69e+2 1.78e+2 +5.72e+2 1.49e+2 +1.83e+2 1.47e+2 +1.19e+2 1.79e+2 +3.44e+1 1.48e+2 +4.23e+2 1.48e+2 +3.93e+0 1.48e+2 +5.99e+2 1.79e+2 +7.37e+1 8.90e+1 +1.37e+1 1.49e+2 +2.63e+2 1.49e+2 +2.06e+2 1.95e+2 +4.66e+2 1.49e+2 +4.10e+2 1.80e+2 +3.29e+2 1.49e+2 +3.14e+1 1.49e+2 +5.81e+2 1.47e+2 +2.53e+2 1.78e+2 +7.52e+2 1.49e+2 +7.63e+2 1.49e+2 +3.62e+2 8.90e+1 +3.64e+2 8.90e+1 +8.25e+1 1.78e+2 +3.81e+2 1.80e+2 +1.83e+2 1.74e+2 +1.85e+2 1.72e+2 +2.11e+2 1.49e+2 +2.21e+2 1.49e+2 +4.22e+2 1.49e+2 +4.91e+0 1.48e+2 +8.25e+1 1.49e+2 +9.53e+1 1.49e+2 +5.75e+2 1.48e+2 +2.81e+2 1.49e+2 +7.29e+2 8.90e+1 +2.94e+0 1.49e+2 +6.06e+2 1.49e+2 +1.27e+1 1.49e+2 +3.83e+2 1.49e+2 +3.69e+2 1.79e+2 +2.08e+2 1.48e+2 +1.48e+2 1.48e+2 +4.81e+1 1.49e+2 +2.33e+2 1.48e+2 +7.73e+2 1.49e+2 +4.20e+2 1.49e+2 +4.09e+2 1.48e+2 +4.59e+2 1.80e+2 +4.12e+2 1.48e+2 +5.87e+2 1.49e+2 +3.32e+2 1.78e+2 +5.65e+2 1.49e+2 +5.01e+2 1.49e+2 +3.98e+2 1.49e+2 +5.22e+2 1.48e+2 +5.87e+2 1.78e+2 +1.20e+2 1.80e+2 +4.32e+1 1.50e+2 +4.52e+1 1.50e+2 +1.86e+1 1.50e+2 +3.16e+2 1.49e+2 +2.92e+2 1.49e+2 +6.52e+2 1.48e+2 +6.54e+2 1.47e+2 +6.63e+2 1.49e+2 +5.99e+1 1.81e+2 +4.49e+2 1.79e+2 +4.51e+2 1.79e+2 +5.05e+2 1.49e+2 +7.53e+2 1.49e+2 +4.49e+2 1.47e+2 +2.95e+2 1.49e+2 +7.49e+2 1.48e+2 +2.56e+2 1.78e+2 +2.47e+2 1.49e+2 +6.68e+2 1.48e+2 +1.76e+1 1.48e+2 +1.73e+2 1.79e+2 +6.91e+2 1.48e+2 +6.92e+2 1.47e+2 +4.74e+2 1.79e+2 +1.32e+2 1.48e+2 +1.34e+2 1.48e+2 +8.06e+1 1.49e+2 +4.65e+2 1.78e+2 +2.26e+1 1.51e+2 +2.45e+1 1.52e+2 +4.63e+2 1.78e+2 +2.61e+2 1.49e+2 +4.15e+2 1.49e+2 +3.30e+2 1.78e+2 +5.85e+2 1.49e+2 +2.13e+2 1.48e+2 +4.31e+2 1.50e+2 +7.59e+2 1.48e+2 +4.73e+2 1.50e+2 +7.06e+2 1.49e+2 +7.58e+2 1.48e+2 +7.28e+2 1.78e+2 +1.95e+2 1.96e+2 +5.51e+2 1.49e+2 +4.47e+2 1.79e+2 +2.68e+2 1.49e+2 +7.21e+2 1.78e+2 +3.53e+1 1.50e+2 +2.07e+2 1.48e+2 +7.28e+2 1.48e+2 +6.76e+2 1.49e+2 +5.94e+2 1.48e+2 +3.04e+1 1.48e+2 +1.94e+2 1.49e+2 +3.29e+2 1.79e+2 +7.29e+2 1.49e+2 +5.40e+1 8.90e+1 +7.16e+2 8.90e+1 +7.31e+2 1.49e+2 +2.21e+2 1.48e+2 +2.23e+2 1.48e+2 +4.67e+2 1.49e+2 +3.23e+2 1.79e+2 +4.26e+2 1.46e+2 +2.46e+2 1.79e+2 +2.25e+2 1.49e+2 +2.19e+2 1.49e+2 +1.62e+2 1.49e+2 +1.37e+2 1.49e+2 +3.86e+2 1.48e+2 +3.84e+2 1.49e+2 +4.53e+2 1.48e+2 +7.44e+2 1.46e+2 +7.46e+2 1.46e+2 +1.40e+2 1.49e+2 +1.47e+1 1.48e+2 +4.98e+2 1.49e+2 +4.34e+2 1.48e+2 +1.21e+2 1.48e+2 +3.22e+2 1.47e+2 +3.24e+2 1.47e+2 +2.00e+2 1.46e+2 +2.14e+2 1.49e+2 +2.05e+2 1.48e+2 +5.81e+2 1.49e+2 +5.79e+2 1.49e+2 +7.71e+2 1.48e+2 +7.73e+2 1.48e+2 +5.41e+2 8.90e+1 +5.30e+1 1.49e+2 +7.30e+2 1.78e+2 +4.08e+2 1.50e+2 +4.10e+2 1.51e+2 +6.02e+2 1.49e+2 +6.15e+2 1.49e+2 +5.92e+2 1.49e+2 +2.09e+2 1.47e+2 +2.11e+2 1.46e+2 +5.74e+2 1.50e+2 +4.05e+2 1.48e+2 +4.35e+2 1.48e+2 +1.94e+2 9.76e+1 +3.44e+1 1.49e+2 +8.15e+1 1.49e+2 +5.68e+2 1.79e+2 +3.25e+2 1.79e+2 +7.20e+2 1.78e+2 +7.66e+2 1.78e+2 +5.90e+2 1.47e+2 +6.69e+2 1.50e+2 +3.94e+2 1.50e+2 +1.51e+2 1.49e+2 +5.73e+2 1.50e+2 +4.47e+2 1.49e+2 +4.68e+2 1.79e+2 +2.60e+2 1.49e+2 +1.97e+2 1.48e+2 +4.06e+2 1.50e+2 +3.24e+2 1.79e+2 +4.12e+1 1.51e+2 +3.28e+2 1.78e+2 +6.73e+2 1.48e+2 +2.51e+2 1.79e+2 +2.55e+2 1.79e+2 +4.83e+2 1.49e+2 +4.85e+2 1.49e+2 +3.05e+2 1.48e+2 +7.62e+2 1.49e+2 +4.92e+2 1.49e+2 +4.99e+2 1.49e+2 +5.21e+1 1.48e+2 +7.17e+2 1.81e+2 +1.90e+2 1.48e+2 +1.90e+2 1.50e+2 +1.92e+2 1.50e+2 +1.92e+2 1.49e+2 +1.33e+2 1.49e+2 +3.25e+2 1.49e+2 +7.83e+2 8.90e+1 +3.22e+2 1.79e+2 +7.68e+2 1.79e+2 +4.56e+2 1.49e+2 +2.47e+2 1.79e+2 +7.90e+2 1.59e+2 +5.60e+1 1.47e+2 +3.83e+1 1.49e+2 +1.63e+2 1.49e+2 +5.57e+2 1.50e+2 +5.59e+2 1.50e+2 +5.61e+2 1.50e+2 +3.11e+2 1.49e+2 +2.09e+2 1.49e+2 +1.45e+2 1.50e+2 +4.93e+2 1.49e+2 +4.58e+2 1.49e+2 +5.40e+1 1.49e+2 +7.70e+2 1.49e+2 +1.52e+2 1.50e+2 +4.77e+2 1.48e+2 +3.26e+2 1.79e+2 +7.65e+2 1.78e+2 +3.93e+2 1.49e+2 +1.42e+2 1.50e+2 +4.27e+2 1.49e+2 +4.89e+2 1.49e+2 +1.86e+2 1.49e+2 +1.70e+2 1.49e+2 +4.56e+2 1.49e+2 +1.17e+2 1.49e+2 +4.52e+2 1.49e+2 +3.10e+2 1.48e+2 +6.31e+2 1.49e+2 +6.33e+2 1.49e+2 +1.56e+2 1.45e+2 +6.52e+2 1.50e+2 +5.40e+1 1.79e+2 +6.13e+2 1.48e+2 +7.16e+2 1.48e+2 +5.23e+2 1.49e+2 +6.03e+2 1.49e+2 +7.87e+2 1.60e+2 +4.92e+2 1.49e+2 +1.69e+2 1.50e+2 +2.73e+2 1.49e+2 +7.67e+2 1.49e+2 +7.88e+2 1.60e+2 +1.61e+2 1.49e+2 +4.81e+2 1.49e+2 +4.21e+2 1.48e+2 +7.01e+2 1.49e+2 +4.16e+2 1.49e+2 +4.63e+2 1.49e+2 +7.69e+2 1.49e+2 +7.68e+2 1.49e+2 +4.78e+2 1.49e+2 +3.20e+2 1.48e+2 +3.91e+2 1.49e+2 +4.68e+2 1.49e+2 +5.10e+2 1.49e+2 +7.41e+2 1.49e+2 +6.21e+2 1.49e+2 +5.35e+2 1.49e+2 +4.97e+2 1.49e+2 +6.88e+2 1.49e+2 +6.14e+2 1.49e+2 +1.50e+2 1.49e+2 +6.56e+2 1.49e+2 +4.32e+2 1.48e+2 +3.81e+2 8.90e+1 +3.83e+2 8.90e+1 +2.71e+2 1.49e+2 +5.89e+1 1.49e+2 +1.98e+2 1.46e+2 +5.32e+2 8.90e+1 +3.93e+1 1.49e+2 +2.01e+2 1.45e+2 +2.07e+2 8.90e+1 +4.54e+2 1.49e+2 +2.32e+2 1.49e+2 +6.14e+2 1.49e+2 +6.16e+2 1.50e+2 +7.04e+2 1.49e+2 +7.19e+2 1.48e+2 +6.20e+2 1.49e+2 +1.41e+2 1.49e+2 +7.81e+2 1.62e+2 +4.03e+1 1.50e+2 +4.63e+2 1.48e+2 +1.47e+2 1.49e+2 +1.31e+2 1.50e+2 +6.39e+2 1.48e+2 +1.08e+2 1.47e+2 +5.21e+2 1.49e+2 +4.69e+2 1.49e+2 +5.70e+2 1.49e+2 +7.53e+2 1.49e+2 +7.03e+2 1.49e+2 +6.48e+1 1.49e+2 +5.03e+2 1.49e+2 +3.07e+2 1.50e+2 +2.91e+2 1.49e+2 +2.52e+2 1.48e+2 +7.09e+2 1.49e+2 +7.75e+2 1.49e+2 +4.82e+2 1.49e+2 +7.85e+2 1.49e+2 +7.63e+2 1.78e+2 +1.17e+2 1.48e+2 +1.19e+2 1.48e+2 +6.01e+2 1.49e+2 +7.18e+2 1.79e+2 +3.69e+2 1.48e+2 +2.20e+2 1.49e+2 +2.26e+1 1.48e+2 +1.49e+2 1.48e+2 +1.48e+2 1.48e+2 +2.16e+1 1.49e+2 +1.51e+2 1.47e+2 +2.79e+2 1.49e+2 +3.24e+1 1.50e+2 +5.60e+1 8.90e+1 +4.17e+2 1.49e+2 +6.51e+2 1.50e+2 +3.27e+2 1.51e+2 +3.29e+2 1.52e+2 +1.52e+2 1.49e+2 +1.53e+2 1.49e+2 +1.55e+2 1.49e+2 +7.57e+2 1.49e+2 +6.28e+2 1.48e+2 +4.00e+2 1.49e+2 +5.60e+1 1.79e+2 +5.79e+1 1.80e+2 +6.44e+2 1.49e+2 +7.40e+2 1.48e+2 +6.78e+2 1.48e+2 +7.42e+2 1.49e+2 +1.72e+2 1.48e+2 +3.70e+2 1.50e+2 +2.90e+2 1.49e+2 +3.57e+2 1.49e+2 +4.70e+2 1.50e+2 +4.78e+2 1.49e+2 +7.50e+2 1.49e+2 +6.18e+2 1.49e+2 +4.43e+2 1.48e+2 +4.45e+2 1.48e+2 +5.07e+2 1.49e+2 +7.05e+2 1.48e+2 +1.02e+2 1.49e+2 +6.88e+1 1.50e+2 +3.12e+2 1.50e+2 +2.27e+2 1.49e+2 +2.35e+1 1.49e+2 +1.75e+2 1.46e+2 +2.51e+2 1.49e+2 +3.31e+2 1.48e+2 +1.71e+2 1.49e+2 +4.62e+2 1.48e+2 +6.62e+2 1.49e+2 +4.19e+2 1.49e+2 +7.89e+2 1.59e+2 +3.47e+2 1.48e+2 +2.67e+2 1.49e+2 +2.18e+2 1.48e+2 +2.20e+2 1.48e+2 +5.12e+2 1.49e+2 +3.35e+2 1.48e+2 +7.86e+2 8.85e+1 +2.85e+1 1.48e+2 +5.40e+2 1.49e+2 +2.48e+2 1.79e+2 +3.49e+2 1.46e+2 +3.51e+2 1.46e+2 +2.49e+2 1.78e+2 +7.17e+1 1.49e+2 +5.53e+2 1.47e+2 +3.90e+2 1.50e+2 +2.28e+2 1.49e+2 +7.14e+2 1.49e+2 +1.46e+2 1.49e+2 +3.31e+2 1.46e+2 +3.33e+2 1.43e+2 +1.83e+2 1.49e+2 +1.85e+2 1.48e+2 +6.60e+2 1.49e+2 +3.04e+2 1.48e+2 +4.31e+2 1.49e+2 +3.36e+2 1.49e+2 +1.43e+2 1.50e+2 +6.45e+2 1.48e+2 +4.50e+2 1.49e+2 +6.19e+1 1.49e+2 +2.66e+2 1.49e+2 +5.28e+2 1.49e+2 +7.83e+2 1.48e+2 +2.06e+1 1.48e+2 +7.10e+2 1.48e+2 +7.56e+2 1.48e+2 +3.36e+2 1.50e+2 +3.38e+2 1.50e+2 +4.59e+2 1.49e+2 +1.89e+2 1.50e+2 +3.32e+2 1.80e+2 +6.61e+2 1.48e+2 +6.11e+2 1.48e+2 +4.40e+2 1.48e+2 +6.26e+2 1.50e+2 +4.96e+2 1.49e+2 +5.99e+2 1.49e+2 +4.42e+2 1.49e+2 +5.39e+2 1.49e+2 +4.81e+1 8.90e+1 +1.68e+2 1.49e+2 +5.21e+2 8.90e+1 +5.75e+2 1.50e+2 +4.40e+2 1.48e+2 +1.45e+2 1.49e+2 +1.79e+2 1.49e+2 +4.53e+2 1.49e+2 +7.21e+2 1.49e+2 +6.64e+2 8.90e+1 +6.66e+2 8.90e+1 +1.23e+2 1.48e+2 +2.44e+2 1.48e+2 +2.46e+2 1.47e+2 +2.48e+2 1.46e+2 +3.68e+2 1.48e+2 +3.70e+2 1.49e+2 +7.20e+2 1.48e+2 +1.69e+2 1.49e+2 +1.71e+2 1.49e+2 +5.38e+2 1.49e+2 +5.26e+2 8.90e+1 +1.88e+2 1.49e+2 +5.51e+2 8.90e+1 +4.44e+2 1.49e+2 +2.91e+2 1.78e+2 +5.21e+1 8.90e+1 +1.58e+2 1.46e+2 +1.60e+2 1.45e+2 +1.62e+2 1.45e+2 +3.41e+2 1.48e+2 +4.20e+2 1.46e+2 +1.81e+2 1.50e+2 +6.19e+1 1.81e+2 +6.38e+1 1.82e+2 +6.58e+1 1.82e+2 +3.55e+2 1.49e+2 +8.45e+1 1.47e+2 +5.36e+2 1.50e+2 +4.45e+2 1.48e+2 +3.56e+2 1.47e+2 +2.65e+1 1.49e+2 +3.46e+2 1.48e+2 +5.67e+2 1.48e+2 +3.58e+2 1.49e+2 +1.25e+2 1.48e+2 +6.59e+2 1.49e+2 +3.71e+2 1.49e+2 +7.36e+2 1.49e+2 +3.58e+2 1.46e+2 +4.17e+2 1.48e+2 +6.78e+1 1.48e+2 +5.16e+2 1.49e+2 +1.67e+2 1.50e+2 +1.16e+2 1.49e+2 +4.52e+1 8.90e+1 +1.90e+2 1.48e+2 +3.18e+2 1.49e+2 +3.39e+2 1.50e+2 +2.50e+2 1.49e+2 +4.30e+2 1.48e+2 +1.44e+2 1.47e+2 +1.15e+2 1.48e+2 +1.72e+2 1.49e+2 +7.62e+2 1.78e+2 +7.34e+2 1.49e+2 +5.11e+2 8.90e+1 +6.46e+2 1.48e+2 +5.06e+2 1.48e+2 +4.96e+2 1.49e+2 +7.71e+2 2.95e+1 +2.30e+2 1.49e+2 +1.23e+2 1.47e+2 +7.81e+2 1.49e+2 +7.83e+2 1.50e+2 +3.59e+2 1.49e+2 +1.73e+2 1.48e+2 +5.29e+2 1.48e+2 +4.16e+2 1.48e+2 +3.14e+2 1.46e+2 +6.09e+2 1.47e+2 +3.68e+2 1.49e+2 +3.66e+2 1.48e+2 +2.10e+2 1.96e+2 +3.89e+2 1.49e+2 +6.58e+2 1.49e+2 +5.25e+2 1.49e+2 +3.77e+2 8.90e+1 +3.54e+2 1.49e+2 +2.00e+2 1.99e+2 +6.23e+2 1.49e+2 +3.17e+2 1.50e+2 +7.80e+2 1.48e+2 +7.11e+2 1.49e+2 +4.38e+2 1.49e+2 +7.84e+2 8.90e+1 +4.12e+1 1.46e+2 +6.86e+2 1.49e+2 +3.45e+2 1.49e+2 +1.40e+2 1.49e+2 +6.50e+2 1.49e+2 +1.15e+2 1.49e+2 +5.28e+2 8.90e+1 +3.34e+1 8.90e+1 +6.57e+2 1.50e+2 +3.22e+2 8.79e+1 +6.58e+1 1.51e+2 +5.17e+2 1.49e+2 +1.28e+2 1.49e+2 +3.45e+2 1.50e+2 +3.43e+2 1.48e+2 +5.54e+2 8.90e+1 +4.34e+2 1.50e+2 +7.33e+2 1.49e+2 +6.85e+2 1.48e+2 +6.47e+2 1.49e+2 +6.49e+2 1.49e+2 +3.92e+2 1.49e+2 +5.25e+2 8.90e+1 +6.24e+2 1.49e+2 +5.36e+2 8.90e+1 +5.38e+2 8.90e+1 +5.40e+2 8.90e+1 +7.76e+2 1.47e+2 +2.32e+2 1.49e+2 +4.97e+2 1.48e+2 +7.61e+2 1.79e+2 +3.64e+2 1.49e+2 +7.07e+1 8.71e+1 +7.27e+1 8.62e+1 +5.85e+2 1.77e+2 +5.95e+2 1.48e+2 +3.60e+2 1.48e+2 +4.37e+2 1.47e+2 +4.39e+2 1.47e+2 +7.58e+2 1.79e+2 +7.60e+2 1.79e+2 +4.66e+2 8.90e+1 +1.11e+2 1.48e+2 +4.75e+2 1.49e+2 +3.47e+2 1.49e+2 +3.19e+2 1.46e+2 +4.13e+2 1.49e+2 +4.15e+2 1.49e+2 +2.11e+2 1.97e+2 +3.38e+2 8.90e+1 +3.50e+2 1.48e+2 +3.61e+2 1.48e+2 +1.87e+2 1.50e+2 +4.74e+2 1.49e+2 +6.64e+2 1.48e+2 +7.52e+2 1.46e+2 +3.53e+2 1.50e+2 +5.79e+2 1.47e+2 +2.00e+2 1.49e+2 +7.80e+2 1.49e+2 +2.42e+2 1.50e+2 +3.24e+1 8.73e+1 +3.41e+2 8.90e+1 +3.43e+2 1.49e+2 +2.58e+2 1.50e+2 +2.60e+2 1.51e+2 +5.12e+2 8.90e+1 +5.14e+2 8.90e+1 +2.12e+2 1.97e+2 +7.62e+2 8.90e+1 +5.79e+1 8.90e+1 +1.99e+2 1.48e+2 +5.35e+2 8.90e+1 +7.60e+2 8.90e+1 +3.48e+2 1.49e+2 +7.78e+2 1.63e+2 +7.80e+2 1.63e+2 +4.99e+2 1.48e+2 +5.01e+2 1.48e+2 +7.53e+2 1.79e+2 +7.55e+2 1.80e+2 +1.98e+2 1.49e+2 +7.10e+2 1.46e+2 +5.31e+2 8.90e+1 +3.47e+2 8.84e+1 +3.49e+2 8.83e+1 +9.04e+1 1.46e+2 +7.74e+2 1.64e+2 +3.41e+2 1.49e+2 +5.73e+2 1.47e+2 +2.21e+2 1.00e+2 +3.04e+1 8.90e+1 +7.59e+2 8.90e+1 +2.36e+2 1.49e+2 +4.70e+2 8.90e+1 +7.89e+2 8.90e+1 +2.37e+2 1.50e+2 +2.39e+2 1.50e+2 +2.41e+2 1.51e+2 +7.76e+2 1.49e+2 +6.56e+2 8.90e+1 +4.65e+2 8.90e+1 +3.60e+2 1.47e+2 +3.62e+2 1.47e+2 +7.79e+2 1.49e+2 +7.71e+2 8.90e+1 +7.73e+2 8.90e+1 +7.75e+2 8.90e+1 +4.68e+2 8.90e+1 +2.21e+2 2.00e+2 +2.23e+2 2.00e+2 +2.25e+2 2.00e+2 +6.27e+2 1.49e+2 +4.72e+2 8.90e+1 +4.74e+2 8.90e+1 +6.59e+2 1.49e+2 +3.43e+2 8.90e+1 +7.66e+2 8.39e+1 +2.16e+2 1.99e+2 +6.68e+1 8.90e+1 +6.88e+1 8.90e+1 +1.96e+2 1.46e+2 +4.22e+2 1.46e+2 +2.15e+2 1.99e+2 +7.33e+2 8.90e+1 +2.20e+2 2.01e+2 +7.55e+2 8.90e+1 +7.57e+2 8.90e+1 +5.71e+2 9.15e+1 +2.19e+2 2.00e+2 + + +1.17e+1 8.90e+1 +3.51e+2 8.90e+1 +3.53e+2 8.93e+1 +7.63e+2 8.90e+1 +2.65e+1 8.83e+1 +2.85e+1 8.80e+1 +3.46e+2 8.90e+1 +5.30e+2 8.90e+1 +7.86e+2 1.46e+2 +7.88e+2 1.45e+2 +7.70e+2 8.90e+1 +3.00e+2 1.50e+2 +5.89e+1 8.90e+1 +4.02e+2 8.90e+1 +5.55e+2 1.46e+2 +7.86e+0 8.90e+1 +7.96e+2 8.90e+1 +4.06e+2 8.90e+1 +4.63e+2 8.90e+1 +7.64e+2 8.90e+1 +2.71e+2 8.90e+1 +3.75e+2 8.90e+1 +7.51e+2 1.78e+2 +4.67e+2 1.47e+2 +4.69e+2 1.46e+2 +4.98e+2 1.47e+2 +1.76e+1 8.90e+1 +1.96e+1 8.90e+1 +7.66e+2 8.90e+1 +7.68e+2 8.89e+1 +2.06e+1 8.90e+1 +2.26e+1 8.90e+1 +2.45e+1 8.90e+1 +7.47e+2 1.74e+2 +9.04e+1 8.83e+1 +9.24e+1 8.80e+1 +7.66e+2 1.67e+2 +7.68e+2 1.66e+2 +3.45e+2 8.83e+1 +2.74e+2 2.03e+2 +2.76e+2 2.03e+2 +7.50e+2 8.90e+1 +7.52e+2 8.91e+1 +7.53e+2 8.91e+1 +7.38e+2 8.90e+1 +7.57e+2 1.70e+2 +7.59e+2 1.70e+2 +2.98e+2 1.48e+2 +6.09e+1 8.90e+1 +7.92e+2 8.85e+1 +8.74e+1 8.90e+1 +4.61e+2 8.90e+1 +5.56e+2 8.90e+1 +5.58e+2 8.89e+1 +5.60e+2 8.91e+1 +4.04e+2 8.90e+1 +5.63e+2 8.90e+1 +5.65e+2 8.90e+1 +5.89e+0 8.90e+1 +6.29e+1 8.90e+1 +6.48e+1 8.90e+1 +5.68e+2 8.90e+1 +5.70e+2 8.90e+1 +9.53e+1 8.91e+1 +4.90e+2 8.85e+1 +4.92e+2 8.82e+1 +7.50e+2 1.73e+2 +6.21e+2 8.90e+1 +6.23e+2 8.90e+1 +7.45e+2 1.48e+2 +8.55e+1 8.90e+1 +1.47e+1 8.90e+1 +1.68e+2 8.90e+1 +4.73e+2 1.47e+2 +5.06e+2 8.90e+1 +7.43e+2 8.79e+1 +7.45e+2 8.78e+1 +4.94e+2 8.90e+1 +6.20e+2 8.90e+1 +7.48e+2 8.92e+1 +5.76e+2 8.90e+1 +5.98e+2 8.90e+1 +1.31e+2 8.85e+1 +2.93e+2 8.90e+1 +7.96e+1 8.90e+1 +4.00e+2 8.90e+1 +4.87e+2 8.90e+1 +4.89e+2 8.90e+1 +6.85e+2 1.49e+2 +4.28e+2 8.85e+1 +1.74e+2 8.85e+1 +5.78e+2 8.82e+1 +2.74e+2 8.85e+1 +2.76e+2 8.77e+1 +4.21e+2 8.85e+1 +4.23e+2 8.82e+1 +4.31e+2 8.92e+1 +6.49e+2 8.90e+1 +6.51e+2 8.90e+1 +7.47e+2 8.74e+1 +2.88e+2 8.90e+1 +4.19e+2 8.90e+1 +6.47e+2 8.90e+1 +3.68e+2 8.90e+1 +3.31e+2 8.85e+1 +6.42e+2 8.90e+1 +1.75e+2 8.85e+1 +1.77e+2 8.85e+1 +7.41e+2 8.85e+1 +3.57e+2 8.85e+1 +2.97e+2 8.90e+1 +4.17e+2 8.90e+1 +2.79e+2 1.97e+2 +6.83e+2 1.47e+2 +2.59e+2 1.97e+2 +3.11e+2 8.90e+1 +7.75e+2 6.66e+1 +4.55e+2 8.90e+1 +3.92e+2 9.35e+1 +7.26e+2 8.90e+1 +1.83e+2 9.35e+1 +1.85e+2 9.35e+1 +4.77e+2 9.35e+1 +6.86e+2 1.47e+2 +3.23e+2 9.35e+1 +3.22e+2 9.35e+1 +2.13e+2 8.85e+1 +2.35e+1 9.35e+1 +5.36e+2 9.35e+1 +3.21e+2 9.35e+1 +4.91e+2 9.35e+1 +2.89e+2 9.35e+1 +7.07e+1 9.35e+1 +5.25e+2 9.35e+1 +2.16e+1 9.35e+1 +7.17e+1 9.35e+1 +3.26e+2 9.35e+1 +2.89e+2 9.35e+1 +3.20e+2 9.35e+1 +3.14e+1 9.35e+1 +3.34e+1 9.35e+1 +1.27e+1 9.35e+1 +2.97e+2 9.35e+1 +3.04e+1 9.35e+1 +3.44e+1 9.35e+1 +7.56e+1 9.35e+1 +2.93e+2 9.35e+1 +3.29e+2 9.35e+1 +3.39e+2 9.35e+1 +2.98e+2 9.35e+1 +2.08e+2 8.90e+1 +3.41e+2 9.35e+1 +2.85e+1 9.35e+1 +1.08e+2 9.35e+1 +3.40e+2 9.35e+1 +2.55e+1 9.35e+1 +2.65e+1 9.35e+1 +3.38e+2 9.35e+1 +1.11e+2 9.35e+1 +8.55e+1 9.35e+1 +2.77e+2 9.35e+1 +1.96e+1 9.35e+1 +1.05e+2 9.35e+1 +1.03e+2 9.35e+1 +2.90e+2 9.35e+1 +7.47e+1 9.35e+1 +6.88e+2 1.47e+2 +2.75e+2 9.35e+1 +2.58e+2 9.35e+1 +9.92e+1 9.35e+1 +3.31e+2 9.35e+1 +2.86e+2 9.35e+1 +3.43e+2 9.35e+1 +5.79e+2 9.35e+1 +3.36e+2 9.35e+1 +3.50e+2 9.35e+1 +3.10e+2 9.35e+1 +3.52e+2 9.35e+1 +9.04e+1 9.35e+1 +3.18e+2 9.35e+1 +3.45e+2 9.35e+1 +3.47e+2 9.35e+1 +5.30e+1 9.35e+1 +1.99e+2 8.85e+1 +3.17e+2 9.35e+1 +2.05e+2 8.85e+1 +3.80e+2 9.35e+1 +3.82e+2 9.35e+1 +3.54e+2 9.35e+1 +8.45e+1 9.35e+1 +1.15e+2 9.35e+1 +9.73e+1 9.35e+1 +1.18e+2 9.35e+1 +1.20e+2 9.35e+1 +4.52e+1 9.35e+1 +5.21e+1 9.35e+1 +9.63e+1 9.35e+1 +1.16e+2 9.35e+1 +3.32e+2 9.35e+1 +8.94e+1 9.35e+1 +9.53e+1 9.35e+1 +5.50e+1 9.35e+1 +2.52e+2 9.35e+1 +3.09e+2 9.35e+1 +7.66e+1 9.35e+1 +3.49e+2 9.35e+1 +5.56e+2 9.35e+1 +1.01e+2 9.35e+1 +3.08e+2 9.35e+1 +4.71e+1 9.35e+1 +4.91e+1 9.35e+1 +3.11e+2 9.35e+1 +1.95e+2 8.85e+1 +9.33e+1 9.35e+1 +3.83e+1 9.35e+1 +2.57e+2 9.35e+1 +7.82e+2 9.35e+1 +2.47e+2 9.35e+1 +2.78e+2 9.30e+1 +2.37e+2 9.35e+1 +4.81e+1 9.35e+1 +2.69e+2 9.35e+1 +3.61e+2 9.35e+1 +3.60e+2 9.35e+1 +3.77e+2 9.35e+1 +2.51e+2 9.35e+1 +6.09e+1 9.35e+1 +2.53e+2 9.35e+1 +5.79e+1 9.35e+1 +3.03e+2 9.35e+1 +3.55e+2 9.35e+1 +7.09e+2 8.85e+1 +2.91e+2 9.35e+1 +3.71e+2 9.35e+1 +3.34e+2 9.35e+1 +8.74e+1 9.35e+1 +6.78e+1 9.35e+1 +1.97e+2 8.85e+1 +2.45e+2 9.35e+1 +3.04e+2 9.35e+1 +2.80e+2 9.30e+1 +3.53e+1 9.35e+1 +5.99e+1 9.35e+1 +3.62e+2 9.35e+1 +3.48e+2 9.35e+1 +4.22e+1 9.35e+1 +7.58e+2 9.35e+1 +7.60e+2 9.35e+1 +2.01e+2 8.85e+1 +3.72e+2 9.35e+1 +5.27e+2 8.85e+1 +3.13e+2 9.35e+1 +2.79e+2 9.35e+1 +2.02e+2 8.85e+1 +2.83e+2 9.36e+1 +3.68e+2 9.35e+1 +3.57e+2 9.35e+1 +3.02e+2 9.35e+1 +3.73e+1 9.35e+1 +7.21e+2 1.47e+2 +7.23e+2 1.47e+2 +2.42e+2 9.35e+1 +2.44e+2 9.35e+1 +2.26e+1 8.90e+1 +7.76e+1 9.35e+1 +4.33e+2 1.75e+2 +3.76e+2 9.35e+1 +2.13e+2 9.35e+1 +2.66e+2 9.35e+1 +3.66e+2 9.35e+1 +3.64e+2 9.35e+1 +7.01e+2 1.47e+2 +2.65e+2 9.35e+1 +7.96e+1 9.35e+1 +8.15e+1 9.35e+1 +3.74e+2 9.35e+1 +5.50e+2 9.35e+1 +3.15e+2 8.85e+1 +3.17e+2 8.85e+1 +3.80e+2 8.85e+1 +4.61e+2 9.35e+1 +5.04e+2 9.35e+1 +3.73e+2 9.35e+1 +4.71e+2 8.85e+1 +7.03e+2 1.47e+2 +7.53e+2 9.35e+1 +2.16e+2 9.35e+1 +7.86e+1 9.35e+1 +2.32e+2 7.37e+1 +2.85e+1 8.85e+1 +5.61e+2 1.51e+2 +6.11e+2 7.37e+1 +6.13e+2 7.37e+1 +2.07e+2 9.35e+1 +5.10e+2 9.35e+1 +6.94e+2 2.95e+1 +5.55e+2 1.32e+2 +6.91e+2 1.47e+2 +6.93e+2 1.47e+2 +7.00e+2 1.47e+2 +1.52e+2 9.35e+1 +5.74e+2 1.47e+2 +5.76e+2 1.47e+2 +5.78e+2 1.47e+2 +2.15e+2 8.85e+1 +1.98e+2 9.35e+1 +2.00e+2 9.35e+1 +4.27e+2 1.48e+2 +4.29e+2 1.49e+2 +3.83e+1 8.90e+1 +7.80e+2 1.47e+2 +7.82e+2 1.47e+2 +5.73e+2 1.47e+2 +5.71e+2 1.47e+2 +6.95e+2 1.47e+2 +4.18e+2 7.37e+1 +7.79e+2 1.47e+2 +7.96e+2 1.75e+2 +5.63e+2 1.47e+2 +6.16e+2 7.37e+1 +5.70e+2 8.85e+1 +5.72e+2 8.85e+1 +7.72e+2 9.35e+1 +5.64e+2 1.48e+2 +4.19e+2 7.37e+1 +5.67e+2 1.47e+2 +5.69e+2 1.47e+2 +4.99e+2 7.37e+1 +5.95e+2 7.37e+1 +4.17e+2 7.37e+1 +4.46e+2 7.37e+1 +4.39e+2 7.37e+1 +2.29e+2 8.85e+1 +3.11e+2 7.37e+1 +5.94e+2 7.37e+1 +4.03e+1 8.84e+1 +6.78e+1 8.91e+1 +5.60e+2 1.47e+2 +7.24e+2 1.47e+2 +5.80e+2 1.32e+2 +2.60e+2 7.37e+1 +7.47e+1 7.37e+1 +3.53e+2 7.37e+1 +2.42e+2 1.47e+2 +2.44e+2 1.47e+2 +3.10e+2 7.37e+1 +3.83e+2 8.83e+1 +3.51e+2 7.37e+1 +3.09e+2 7.37e+1 +4.37e+2 7.37e+1 +4.41e+2 7.37e+1 +1.02e+2 7.37e+1 +3.49e+2 7.37e+1 +5.57e+2 1.48e+2 +3.45e+2 1.47e+2 +3.47e+2 1.47e+2 +3.48e+2 1.47e+2 +6.97e+1 7.37e+1 +2.15e+2 1.47e+2 +5.50e+1 1.46e+2 +6.77e+2 1.47e+2 +7.65e+2 1.47e+2 +7.81e+2 1.47e+2 +3.51e+2 1.49e+2 +1.01e+2 7.37e+1 +5.00e+2 7.37e+1 +5.62e+2 1.47e+2 +7.72e+2 8.85e+1 +7.74e+2 8.81e+1 +2.57e+2 7.37e+1 +1.87e+2 1.47e+2 +1.00e+2 7.37e+1 +7.09e+2 1.47e+2 +3.48e+2 7.37e+1 +6.09e+1 8.85e+1 +6.29e+1 8.85e+1 +7.37e+1 7.37e+1 +5.03e+2 7.37e+1 +2.12e+2 1.47e+2 +4.52e+1 1.47e+2 +4.43e+2 7.37e+1 +5.21e+1 1.47e+2 +7.70e+2 8.90e+1 +5.01e+2 7.37e+1 +6.18e+2 7.37e+1 +6.20e+2 7.37e+1 +6.22e+2 7.37e+1 +3.57e+2 7.37e+1 +4.22e+2 7.37e+1 +4.24e+2 7.37e+1 +2.59e+2 7.37e+1 +3.63e+1 8.85e+1 +7.56e+1 7.37e+1 +3.37e+2 8.85e+1 +2.82e+2 1.80e+2 +7.41e+2 1.48e+2 +3.53e+1 1.47e+2 +4.03e+2 7.37e+1 +2.14e+2 1.47e+2 +4.48e+2 7.37e+1 +7.68e+2 1.47e+2 +7.70e+2 1.47e+2 +7.27e+1 7.37e+1 +5.70e+1 8.85e+1 +5.89e+1 8.85e+1 +4.05e+2 7.37e+1 +3.80e+2 7.37e+1 +2.34e+2 2.95e+1 +6.96e+2 1.47e+2 +7.86e+1 7.37e+1 +3.58e+2 7.37e+1 +7.74e+2 1.47e+2 +7.76e+2 1.47e+2 +4.31e+2 1.47e+2 +7.56e+2 1.75e+2 +5.55e+2 1.47e+2 +2.77e+2 7.37e+1 +3.99e+2 7.37e+1 +3.05e+2 7.37e+1 +4.47e+2 7.37e+1 +2.07e+2 7.37e+1 +1.89e+2 1.47e+2 +1.91e+2 1.47e+2 +3.84e+2 8.85e+1 +3.86e+2 8.85e+1 +3.65e+2 7.37e+1 +4.49e+2 7.37e+1 +3.25e+2 7.37e+1 +7.05e+2 1.47e+2 +2.79e+2 7.37e+1 +3.14e+2 7.37e+1 +2.54e+2 7.37e+1 +6.38e+1 7.37e+1 +5.02e+2 7.37e+1 +4.32e+1 7.37e+1 +9.83e+1 7.37e+1 +4.12e+2 7.37e+1 +4.14e+2 7.37e+1 +7.26e+2 1.47e+2 +7.28e+2 1.47e+2 +4.52e+1 7.37e+1 +2.72e+2 7.37e+1 +4.09e+2 7.37e+1 +7.64e+2 1.47e+2 +6.48e+1 8.90e+1 +2.70e+2 7.37e+1 +4.91e+1 1.47e+2 +6.09e+2 7.37e+1 +7.66e+1 7.37e+1 +7.91e+2 7.37e+1 +6.78e+1 7.37e+1 +2.53e+2 7.37e+1 +5.60e+1 1.99e+2 +2.56e+2 1.47e+2 +3.47e+2 7.37e+1 +5.90e+2 7.37e+1 +4.03e+1 1.47e+2 +9.53e+1 7.37e+1 +3.42e+2 7.37e+1 +3.94e+2 7.37e+1 +2.37e+2 1.47e+2 +7.84e+2 1.47e+2 +7.86e+2 1.47e+2 +3.24e+2 7.37e+1 +4.02e+2 7.37e+1 +7.88e+2 1.47e+2 +2.56e+2 7.37e+1 +7.10e+2 1.48e+2 +7.12e+2 1.48e+2 +2.68e+2 7.37e+1 +2.67e+2 7.37e+1 +1.47e+1 1.50e+2 +5.98e+2 7.37e+1 +2.71e+2 7.37e+1 +3.22e+2 7.37e+1 +3.75e+2 7.37e+1 +3.46e+2 7.37e+1 +4.71e+1 1.47e+2 +2.11e+2 1.47e+2 +3.23e+2 7.37e+1 +7.77e+2 1.47e+2 +4.62e+1 7.37e+1 +7.55e+2 8.85e+1 +2.34e+2 1.49e+2 +6.00e+2 7.37e+1 +2.45e+2 1.47e+2 +2.00e+2 7.37e+1 +2.02e+2 7.37e+1 +5.66e+2 7.37e+1 +4.26e+2 7.37e+1 +3.84e+2 7.37e+1 +1.94e+2 1.47e+2 +6.03e+2 7.37e+1 +6.05e+2 7.37e+1 +3.31e+2 7.37e+1 +3.96e+2 7.37e+1 +4.15e+2 7.37e+1 +3.38e+2 7.37e+1 +3.32e+2 7.37e+1 +3.73e+1 1.47e+2 +3.08e+2 7.37e+1 +3.34e+2 7.37e+1 +3.30e+2 7.37e+1 +3.98e+2 7.37e+1 +4.12e+1 7.37e+1 +6.58e+1 7.37e+1 +3.15e+2 7.37e+1 +4.08e+2 7.37e+1 +4.27e+2 7.37e+1 +2.01e+2 1.32e+2 +2.03e+2 1.32e+2 +7.95e+2 1.47e+2 +2.49e+2 7.37e+1 +6.29e+1 7.37e+1 +1.33e+2 7.37e+1 +1.35e+2 7.37e+1 +3.10e+2 1.48e+2 +3.78e+2 7.37e+1 +2.40e+2 7.37e+1 +2.66e+2 7.37e+1 +3.88e+2 8.85e+1 +3.90e+2 8.85e+1 +3.92e+2 8.85e+1 +3.64e+2 7.37e+1 +2.84e+2 1.77e+2 +5.16e+2 7.37e+1 +3.83e+2 7.37e+1 +2.84e+2 7.37e+1 +8.25e+1 7.37e+1 +4.92e+2 7.37e+1 +5.28e+2 7.37e+1 +9.14e+1 7.37e+1 +9.33e+1 7.37e+1 +3.63e+2 7.37e+1 +4.30e+2 1.77e+2 +7.96e+2 7.37e+1 +7.86e+0 1.47e+2 +9.83e+0 1.47e+2 +4.96e+2 7.37e+1 +2.44e+2 7.37e+1 +8.65e+1 7.37e+1 +4.50e+2 7.37e+1 +7.19e+2 1.47e+2 +4.93e+2 7.37e+1 +3.40e+2 7.37e+1 +4.33e+2 1.47e+2 +4.87e+2 8.85e+1 +2.55e+2 7.37e+1 +5.05e+2 7.37e+1 +7.43e+2 1.47e+2 +3.36e+2 7.37e+1 +1.05e+2 7.37e+1 +5.01e+1 1.47e+2 +4.03e+1 7.37e+1 +3.50e+2 8.85e+1 +4.32e+2 7.37e+1 +2.41e+2 7.37e+1 +2.43e+2 7.37e+1 +4.98e+2 1.47e+2 +5.04e+2 7.37e+1 +1.68e+2 1.48e+2 +1.25e+2 7.37e+1 +1.27e+2 7.37e+1 +6.02e+2 1.77e+2 +4.29e+2 7.37e+1 +2.89e+2 7.37e+1 +2.36e+2 1.47e+2 +7.17e+1 1.47e+2 +5.27e+2 7.37e+1 +3.21e+2 7.37e+1 +1.16e+2 7.37e+1 +1.18e+2 7.37e+1 +3.94e+2 1.77e+2 +2.85e+2 1.77e+2 +3.60e+2 7.37e+1 +3.29e+2 7.37e+1 +2.48e+2 7.37e+1 +3.41e+2 7.37e+1 +4.26e+2 1.47e+2 +5.79e+1 1.47e+2 +2.21e+2 9.35e+1 +3.24e+1 8.90e+1 +5.36e+2 1.78e+2 +3.17e+2 7.37e+1 +5.17e+2 9.35e+1 +4.28e+2 1.77e+2 +6.03e+2 1.77e+2 +2.65e+2 8.90e+1 +4.66e+2 7.37e+1 +4.22e+1 8.85e+1 +4.42e+1 8.83e+1 +4.62e+1 8.83e+1 +1.13e+2 7.37e+1 +1.15e+2 7.37e+1 +2.16e+2 7.37e+1 +3.75e+2 1.77e+2 +5.41e+2 1.77e+2 +3.71e+2 7.37e+1 +5.14e+2 7.37e+1 +9.04e+1 7.37e+1 +7.06e+2 1.47e+2 +7.08e+2 1.47e+2 +3.87e+2 7.37e+1 +4.32e+2 1.77e+2 +7.31e+2 1.48e+2 +1.23e+2 7.37e+1 +2.39e+2 1.47e+2 +4.72e+2 1.77e+2 +1.30e+2 7.37e+1 +1.42e+2 1.47e+2 +2.86e+2 1.77e+2 +1.08e+1 1.75e+2 +1.77e+2 1.77e+2 +5.07e+2 7.37e+1 +1.10e+2 7.37e+1 +8.35e+1 8.85e+1 +4.28e+2 1.47e+2 +7.33e+2 1.47e+2 +1.21e+2 7.37e+1 +3.60e+2 1.47e+2 +3.34e+2 1.47e+2 +5.72e+2 7.37e+1 +5.19e+2 1.47e+2 +5.21e+2 1.47e+2 +5.22e+2 1.47e+2 +7.37e+1 1.47e+2 +7.56e+1 1.47e+2 +6.97e+1 1.47e+2 +7.36e+2 1.47e+2 +3.56e+2 1.77e+2 +3.83e+1 7.37e+1 +6.04e+2 1.77e+2 +2.08e+2 1.77e+2 +1.76e+2 1.77e+2 +7.66e+2 1.77e+2 +5.12e+2 7.37e+1 +1.20e+2 1.77e+2 +3.97e+2 1.77e+2 +6.97e+2 1.77e+2 +5.19e+2 7.37e+1 +1.37e+1 1.50e+2 +5.02e+2 1.47e+2 +6.01e+2 1.77e+2 +2.94e+1 1.32e+2 +5.63e+2 7.37e+1 +3.96e+2 8.85e+1 +3.98e+2 8.85e+1 +6.73e+2 1.78e+2 +3.89e+2 7.37e+1 +4.19e+2 1.77e+2 +5.06e+2 1.77e+2 +1.99e+2 1.75e+2 +2.77e+2 1.47e+2 +8.15e+1 7.37e+1 +7.30e+2 1.46e+2 +2.89e+2 7.37e+1 +2.69e+2 1.77e+2 +5.37e+2 1.78e+2 +7.67e+2 1.77e+2 +5.18e+2 1.75e+2 +5.66e+2 8.85e+1 +4.81e+1 7.37e+1 +1.21e+2 1.77e+2 +3.00e+2 7.37e+1 +3.98e+2 1.77e+2 +6.48e+1 1.48e+2 +6.68e+1 1.48e+2 +6.88e+1 1.48e+2 +4.71e+1 7.37e+1 +2.48e+2 8.85e+1 +4.75e+2 1.77e+2 +3.13e+2 1.77e+2 +3.73e+1 7.37e+1 +5.88e+2 7.37e+1 +4.20e+2 1.77e+2 +6.98e+2 1.77e+2 +4.75e+2 1.48e+2 +4.77e+2 1.49e+2 +5.64e+2 7.37e+1 +4.74e+2 1.77e+2 +5.42e+2 7.37e+1 +4.76e+2 1.77e+2 +9.53e+1 1.32e+2 +2.46e+2 1.47e+2 +3.14e+2 1.77e+2 +3.11e+2 1.77e+2 +4.99e+2 1.77e+2 +3.84e+2 1.77e+2 +2.87e+2 1.77e+2 +3.93e+1 1.77e+2 +9.83e+1 1.77e+2 +4.26e+2 1.77e+2 +2.67e+2 1.77e+2 +2.18e+2 1.47e+2 +5.39e+2 1.77e+2 +4.87e+2 7.37e+1 +4.89e+2 7.37e+1 +1.22e+2 1.77e+2 +2.13e+2 1.77e+2 +5.43e+2 1.77e+2 +8.84e+1 7.37e+1 +4.83e+2 7.37e+1 +3.09e+2 1.77e+2 +2.72e+2 1.77e+2 +1.19e+2 1.77e+2 +3.86e+2 1.77e+2 +3.03e+2 7.37e+1 +2.68e+2 1.77e+2 +2.89e+2 1.77e+2 +4.64e+2 1.47e+2 +4.66e+2 1.47e+2 +5.71e+2 7.37e+1 +3.85e+2 1.77e+2 +3.74e+2 1.77e+2 +3.87e+2 1.77e+2 +4.01e+2 1.47e+2 +4.27e+2 1.77e+2 +3.83e+1 1.77e+2 +1.96e+2 1.47e+2 +3.68e+2 7.37e+1 +2.14e+2 1.77e+2 +1.23e+2 1.76e+2 +2.66e+2 1.77e+2 +2.45e+2 7.37e+1 +3.82e+2 1.77e+2 +2.89e+2 1.77e+2 +5.50e+2 7.37e+1 +5.90e+2 8.85e+1 +4.60e+2 1.77e+2 +4.62e+2 1.77e+2 +2.18e+2 1.32e+2 +5.54e+2 1.77e+2 +5.31e+2 1.77e+2 +2.19e+2 1.77e+2 +4.51e+2 1.77e+2 +1.17e+2 1.77e+2 +5.53e+2 1.77e+2 +4.34e+2 1.77e+2 +7.91e+2 1.47e+2 +3.63e+1 1.77e+2 +3.58e+2 1.77e+2 +3.34e+1 1.77e+2 +5.08e+2 1.77e+2 +2.45e+1 1.32e+2 +5.01e+1 1.77e+2 +4.03e+1 1.77e+2 +7.75e+2 1.77e+2 +2.23e+2 1.47e+2 +5.00e+2 1.77e+2 +4.21e+2 1.77e+2 +4.00e+2 1.77e+2 +7.94e+2 1.77e+2 +7.51e+2 1.77e+2 +4.35e+2 1.47e+2 +4.37e+2 1.47e+2 +6.07e+2 1.77e+2 +3.07e+2 1.77e+2 +4.39e+2 1.47e+2 +7.69e+2 1.77e+2 +2.21e+2 7.37e+1 +2.23e+2 7.37e+1 +5.44e+2 1.77e+2 +1.69e+2 1.77e+2 +3.52e+2 1.76e+2 +7.52e+2 1.77e+2 +3.63e+2 1.77e+2 +1.67e+2 1.77e+2 +5.33e+2 1.77e+2 +1.24e+2 1.76e+2 +1.68e+2 1.77e+2 +4.35e+2 1.77e+2 +6.99e+2 1.77e+2 +4.12e+1 1.77e+2 +2.12e+2 1.77e+2 +1.63e+2 1.47e+2 +6.21e+2 1.77e+2 +4.64e+2 1.77e+2 +6.08e+2 1.77e+2 +5.55e+2 1.77e+2 +2.20e+2 1.77e+2 +5.32e+2 1.77e+2 +2.88e+2 7.37e+1 +5.45e+2 1.77e+2 +5.34e+2 1.77e+2 +2.15e+2 1.77e+2 +4.77e+2 1.77e+2 +1.55e+2 1.77e+2 +7.88e+2 8.85e+1 +3.04e+1 1.77e+2 +4.22e+1 1.77e+2 +1.53e+2 1.77e+2 +6.47e+2 1.77e+2 +4.16e+2 1.77e+2 +4.25e+2 1.77e+2 +1.73e+2 1.77e+2 +8.35e+1 7.37e+1 +1.51e+2 1.77e+2 +1.91e+2 1.77e+2 +3.67e+2 7.37e+1 +2.55e+1 1.77e+2 +4.63e+2 1.77e+2 +1.92e+2 1.77e+2 +6.22e+2 1.77e+2 +4.71e+2 1.77e+2 +5.50e+2 1.77e+2 +3.54e+2 1.77e+2 +2.94e+1 1.77e+2 +7.93e+2 1.77e+2 +4.23e+2 1.77e+2 +3.17e+2 1.47e+2 +1.06e+2 1.77e+2 +6.19e+2 1.77e+2 +3.59e+2 1.77e+2 +1.93e+2 1.77e+2 +6.74e+2 1.77e+2 +9.43e+1 1.77e+2 +2.95e+2 1.77e+2 +7.58e+2 1.77e+2 +5.35e+2 1.77e+2 +7.49e+2 1.51e+2 +7.51e+2 1.52e+2 +4.32e+1 1.77e+2 +4.96e+2 1.47e+2 +1.17e+1 1.77e+2 +3.00e+2 1.77e+2 +3.89e+2 1.77e+2 +4.42e+1 1.77e+2 +2.99e+2 1.77e+2 +3.47e+2 1.77e+2 +2.16e+2 1.77e+2 +1.05e+2 1.77e+2 +5.14e+2 1.77e+2 +4.18e+2 1.77e+2 +2.92e+2 1.77e+2 +3.90e+2 1.77e+2 +3.61e+2 1.77e+2 +3.56e+2 1.46e+2 +7.78e+2 1.77e+2 +1.56e+2 1.77e+2 +6.51e+2 1.77e+2 +8.84e+0 1.77e+2 +2.25e+2 1.47e+2 +6.42e+2 1.77e+2 +2.97e+2 1.77e+2 +6.09e+2 1.77e+2 +1.26e+2 1.77e+2 +5.97e+2 1.77e+2 +2.92e+2 7.37e+1 +1.57e+2 1.77e+2 +1.74e+2 1.77e+2 +4.95e+2 1.77e+2 +5.15e+2 1.77e+2 +7.37e+2 1.47e+2 +4.71e+1 1.77e+2 +7.00e+2 1.77e+2 +5.85e+2 7.37e+1 +3.67e+2 1.77e+2 +1.61e+2 1.77e+2 +4.17e+2 1.77e+2 +4.78e+2 1.77e+2 +4.50e+2 1.77e+2 +5.01e+1 7.37e+1 +1.82e+2 1.77e+2 +5.11e+1 7.37e+1 +4.84e+2 1.77e+2 +6.68e+2 1.77e+2 +1.25e+2 1.77e+2 +4.53e+2 1.77e+2 +7.91e+2 1.77e+2 +1.27e+1 1.77e+2 +3.93e+2 1.77e+2 +3.14e+1 1.77e+2 +4.03e+2 1.77e+2 +5.30e+2 1.77e+2 +4.05e+2 1.77e+2 +6.24e+2 1.77e+2 +4.56e+2 1.77e+2 +2.55e+1 7.37e+1 +4.65e+2 1.77e+2 +5.68e+2 7.37e+1 +9.43e+1 1.32e+2 +6.25e+2 1.77e+2 +2.36e+2 1.47e+2 +1.28e+2 1.77e+2 +1.11e+2 7.37e+1 +5.82e+2 7.37e+1 +5.61e+2 1.77e+2 +7.32e+2 1.76e+2 +6.43e+2 1.77e+2 +2.33e+2 1.77e+2 +4.62e+2 1.47e+2 +4.68e+2 1.77e+2 +1.15e+2 1.77e+2 +1.00e+2 1.77e+2 +5.56e+2 1.77e+2 +4.81e+1 1.92e+2 +3.19e+2 1.77e+2 +4.79e+2 1.47e+2 +3.47e+2 1.77e+2 +4.67e+2 1.77e+2 +1.58e+2 1.77e+2 +2.26e+1 1.32e+2 +7.04e+2 1.77e+2 +4.11e+2 1.77e+2 +5.99e+2 1.77e+2 +7.39e+2 1.47e+2 +5.30e+1 7.37e+1 +1.15e+2 1.77e+2 +5.13e+2 1.77e+2 +3.52e+2 8.85e+1 +4.49e+2 1.77e+2 +2.96e+2 1.77e+2 +4.66e+2 1.77e+2 +5.79e+1 7.37e+1 +3.11e+2 1.47e+2 +3.13e+2 1.47e+2 +1.14e+2 1.77e+2 +4.38e+2 1.77e+2 +7.37e+2 1.77e+2 +1.10e+2 1.77e+2 +1.27e+2 1.77e+2 +6.39e+2 1.77e+2 +6.52e+2 1.77e+2 +4.14e+2 1.47e+2 +7.01e+2 1.77e+2 +3.93e+0 1.77e+2 +1.09e+2 1.77e+2 +5.21e+1 1.77e+2 +1.04e+2 1.77e+2 +2.23e+2 1.77e+2 +3.34e+1 7.37e+1 +2.47e+2 1.47e+2 +1.97e+2 1.77e+2 +4.81e+2 1.77e+2 +4.63e+2 7.37e+1 +1.67e+2 1.75e+2 +7.77e+2 1.77e+2 +2.78e+2 1.76e+2 +4.45e+2 1.77e+2 +2.59e+2 1.77e+2 +7.06e+2 1.77e+2 +3.71e+2 1.77e+2 +7.35e+2 1.77e+2 +2.34e+2 8.85e+1 +2.36e+2 8.85e+1 +1.35e+2 1.77e+2 +4.48e+2 1.77e+2 +5.76e+2 7.37e+1 +3.04e+2 1.77e+2 +7.12e+2 1.77e+2 +7.27e+1 1.32e+2 +5.03e+2 1.47e+2 +4.39e+2 1.77e+2 +4.63e+2 1.47e+2 +7.56e+2 1.77e+2 +1.39e+2 1.77e+2 +6.48e+2 1.77e+2 +3.72e+2 1.77e+2 +7.86e+2 1.77e+2 +3.93e+1 1.32e+2 +1.13e+2 1.77e+2 +3.59e+2 1.47e+2 +7.76e+2 1.77e+2 +6.67e+2 1.77e+2 +1.57e+1 1.77e+2 +7.31e+2 1.76e+2 +1.36e+2 1.77e+2 +7.15e+2 1.77e+2 +4.44e+2 1.47e+2 +4.46e+2 1.47e+2 +4.48e+2 1.47e+2 +2.69e+2 1.47e+2 +7.34e+2 1.47e+2 +6.09e+1 1.77e+2 +1.08e+2 1.77e+2 +2.00e+2 1.77e+2 +1.40e+2 1.77e+2 +2.71e+2 1.47e+2 +2.09e+2 1.50e+2 +5.28e+2 1.77e+2 +2.56e+2 1.77e+2 +4.37e+2 1.77e+2 +7.34e+2 1.76e+2 +1.34e+2 1.77e+2 +1.37e+2 1.47e+2 +1.42e+2 1.77e+2 +1.67e+1 1.77e+2 +4.70e+2 1.77e+2 +5.57e+2 1.77e+2 +2.35e+1 1.32e+2 +7.14e+2 1.77e+2 +2.47e+2 1.77e+2 +2.20e+2 1.47e+2 +5.41e+2 7.37e+1 +7.86e+1 1.77e+2 +6.70e+2 1.77e+2 +6.79e+2 1.77e+2 +5.77e+2 7.37e+1 +6.50e+2 1.77e+2 +1.33e+2 1.77e+2 +2.55e+2 1.48e+2 +7.83e+2 1.77e+2 +4.58e+2 7.37e+1 +6.26e+2 1.77e+2 +6.80e+2 1.77e+2 +6.27e+2 1.77e+2 +7.96e+1 1.77e+2 +6.83e+2 1.77e+2 +5.65e+2 1.77e+2 +7.79e+2 1.77e+2 +3.15e+2 1.47e+2 +2.52e+2 1.77e+2 +6.28e+2 1.77e+2 +7.16e+2 1.76e+2 +3.11e+2 1.16e+2 +7.47e+1 1.32e+2 +1.88e+2 1.77e+2 +2.95e+2 7.37e+1 +1.32e+2 1.77e+2 +1.37e+2 1.77e+2 +7.07e+2 1.77e+2 +7.26e+2 1.77e+2 +6.11e+2 1.77e+2 +6.58e+2 1.76e+2 +6.38e+1 1.77e+2 +2.48e+2 1.77e+2 +7.50e+2 1.77e+2 +2.36e+2 1.77e+2 +2.37e+2 1.77e+2 +2.43e+2 1.77e+2 +2.49e+2 1.77e+2 +2.32e+2 1.77e+2 +7.80e+2 1.77e+2 +6.82e+2 1.77e+2 +8.06e+1 1.77e+2 +7.81e+2 1.77e+2 +4.79e+2 1.77e+2 +4.55e+2 1.47e+2 +6.88e+0 1.77e+2 +1.76e+1 1.77e+2 +3.02e+2 1.77e+2 +4.87e+2 1.77e+2 +3.63e+1 1.32e+2 +3.83e+1 1.32e+2 +5.26e+2 1.77e+2 +4.88e+2 1.77e+2 +2.02e+2 1.77e+2 +5.26e+2 1.47e+2 +1.12e+2 1.77e+2 +5.80e+2 1.77e+2 +5.66e+2 1.77e+2 +2.46e+2 1.77e+2 +2.80e+2 1.77e+2 +7.19e+2 1.77e+2 +7.17e+1 1.77e+2 +2.78e+2 1.47e+2 +1.76e+1 1.47e+2 +4.80e+2 1.77e+2 +5.74e+2 7.37e+1 +2.55e+2 1.77e+2 +6.56e+2 1.76e+2 +1.86e+1 1.77e+2 +6.65e+2 1.77e+2 +2.26e+2 1.47e+2 +2.31e+2 1.77e+2 +6.38e+2 1.77e+2 +5.25e+2 1.77e+2 +5.60e+1 1.77e+2 +4.52e+2 7.37e+1 +4.54e+2 7.37e+1 +1.86e+1 1.33e+2 +5.89e+1 1.75e+2 +6.09e+1 1.75e+2 +5.89e+2 1.77e+2 +2.01e+2 1.77e+2 +2.03e+2 1.77e+2 +3.20e+2 1.77e+2 +8.35e+1 1.77e+2 +5.20e+2 1.77e+2 +2.45e+1 1.77e+2 +4.13e+2 1.77e+2 +2.42e+2 1.77e+2 +6.84e+2 1.77e+2 +4.67e+2 7.37e+1 +6.77e+2 1.77e+2 +6.09e+1 7.37e+1 +2.41e+2 1.77e+2 +2.50e+2 1.77e+2 +5.63e+2 1.77e+2 +7.07e+1 1.77e+2 +7.11e+2 1.77e+2 +6.48e+1 1.77e+2 +5.70e+1 7.37e+1 +3.28e+2 1.77e+2 +4.91e+1 8.85e+1 +6.36e+2 1.77e+2 +7.29e+2 1.76e+2 +6.15e+2 1.77e+2 +3.29e+2 1.77e+2 +7.85e+2 1.77e+2 +9.83e+1 1.32e+2 +1.65e+2 1.47e+2 +5.52e+2 1.47e+2 +5.54e+2 1.47e+2 +3.50e+2 1.77e+2 +4.68e+2 1.47e+2 +5.79e+2 1.77e+2 +5.48e+2 1.77e+2 +4.08e+2 1.77e+2 +6.68e+1 1.77e+2 +1.96e+1 1.77e+2 +5.30e+1 1.77e+2 +6.78e+2 1.77e+2 +2.26e+1 1.77e+2 +1.43e+2 1.77e+2 +5.67e+2 1.77e+2 +5.47e+2 1.77e+2 +7.28e+2 1.77e+2 +2.50e+2 1.47e+2 +1.82e+2 1.47e+2 +1.84e+2 1.47e+2 +7.96e+2 1.77e+2 +2.16e+1 1.77e+2 +3.62e+2 1.47e+2 +4.40e+2 1.77e+2 +4.67e+2 1.47e+2 +6.63e+2 1.77e+2 +3.23e+2 1.77e+2 +4.90e+2 8.85e+1 +2.04e+2 1.77e+2 +8.45e+1 1.77e+2 +4.53e+2 1.47e+2 +6.88e+2 1.77e+2 +6.85e+2 1.77e+2 +5.37e+2 1.77e+2 +5.39e+2 1.77e+2 +3.42e+2 1.77e+2 +6.88e+1 1.77e+2 +6.86e+2 1.77e+2 +2.05e+2 1.77e+2 +3.46e+2 1.32e+2 +5.40e+1 1.76e+2 +4.90e+2 1.77e+2 +8.55e+1 1.77e+2 +2.44e+2 1.32e+2 +7.17e+2 1.77e+2 +2.70e+2 8.85e+1 +2.72e+2 8.85e+1 +2.08e+2 1.76e+2 +2.60e+2 1.47e+2 +2.38e+2 8.85e+1 +2.40e+2 8.85e+1 +1.41e+2 1.47e+2 +6.12e+2 1.77e+2 +8.65e+1 1.77e+2 +3.01e+2 1.48e+2 +7.20e+2 1.77e+2 +5.27e+2 1.47e+2 +3.30e+2 1.77e+2 +5.82e+2 1.76e+2 +7.18e+2 1.77e+2 +6.14e+2 1.77e+2 +4.22e+1 1.32e+2 +2.29e+2 7.37e+1 +8.94e+1 1.32e+2 +4.44e+2 1.77e+2 +2.16e+1 1.32e+2 +4.62e+2 7.37e+1 +1.00e+2 1.32e+2 +2.35e+1 1.75e+2 +2.55e+1 1.75e+2 +2.45e+1 7.37e+1 +4.04e+2 1.47e+2 +5.84e+2 1.76e+2 +3.27e+2 8.91e+1 +3.38e+2 1.77e+2 +4.49e+2 1.47e+2 +5.37e+2 8.85e+1 +2.51e+2 1.47e+2 +6.92e+2 1.77e+2 +5.45e+2 7.37e+1 +9.14e+1 1.32e+2 +3.21e+2 1.77e+2 +4.61e+2 7.37e+1 +7.43e+2 1.77e+2 +5.15e+2 1.47e+2 +6.35e+2 1.77e+2 +2.92e+2 1.32e+2 +5.87e+2 1.77e+2 +5.22e+2 1.77e+2 +6.19e+1 1.47e+2 +3.53e+1 8.90e+1 +7.25e+2 1.77e+2 +1.10e+2 1.48e+2 +3.44e+2 1.77e+2 +5.11e+1 1.33e+2 +2.14e+2 1.32e+2 +3.25e+2 1.77e+2 +2.06e+1 1.32e+2 +3.27e+2 1.77e+2 +4.62e+2 8.85e+1 +5.42e+2 1.32e+2 +7.45e+2 1.77e+2 +3.18e+2 1.48e+2 +3.20e+2 1.48e+2 +2.93e+2 7.37e+1 +4.11e+2 1.47e+2 +4.13e+2 1.47e+2 +6.89e+2 1.77e+2 +5.84e+2 7.37e+1 +3.41e+2 1.47e+2 +7.46e+2 1.77e+2 +5.75e+2 1.77e+2 +1.32e+2 1.47e+2 +1.49e+2 1.47e+2 +3.81e+2 1.48e+2 +8.45e+1 1.32e+2 +8.65e+1 1.32e+2 +5.86e+2 1.76e+2 +1.98e+2 1.46e+2 +5.99e+1 1.47e+2 +3.35e+2 1.77e+2 +5.31e+2 1.47e+2 +2.90e+2 1.32e+2 +3.31e+2 1.77e+2 +1.96e+1 1.47e+2 +4.03e+1 1.32e+2 +3.46e+2 1.77e+2 +5.69e+2 1.77e+2 +5.23e+2 7.37e+1 +4.82e+2 7.37e+1 +2.00e+2 1.47e+2 +7.24e+2 1.77e+2 +2.75e+2 1.47e+2 +1.52e+2 1.47e+2 +2.51e+2 8.91e+1 +5.70e+2 1.77e+2 +3.32e+2 1.77e+2 +3.85e+2 1.47e+2 +3.22e+2 1.47e+2 +4.05e+2 1.47e+2 +5.51e+2 1.47e+2 +4.57e+2 7.37e+1 +7.17e+1 1.16e+2 +5.73e+2 1.77e+2 +5.44e+2 7.37e+1 +3.36e+2 1.77e+2 +5.11e+2 7.37e+1 +5.01e+1 1.32e+2 +1.93e+2 7.37e+1 +3.92e+2 1.47e+2 +2.79e+2 1.46e+2 +3.21e+2 1.17e+2 +3.23e+2 1.17e+2 +1.01e+2 1.47e+2 +1.03e+2 1.47e+2 +5.52e+2 7.37e+1 +2.65e+2 1.47e+2 +2.83e+2 1.47e+2 +5.34e+2 1.47e+2 +5.77e+2 1.77e+2 +9.33e+1 1.48e+2 +2.94e+2 1.47e+2 +5.74e+2 1.77e+2 +3.57e+2 1.32e+2 +2.45e+2 1.32e+2 +1.05e+2 1.47e+2 +1.07e+2 1.47e+2 +5.50e+2 1.47e+2 +6.00e+2 8.85e+1 +1.46e+2 1.47e+2 +1.71e+2 1.47e+2 +4.52e+2 1.47e+2 +6.32e+2 1.47e+2 +6.34e+2 1.47e+2 +4.80e+2 1.47e+2 +2.25e+2 1.32e+2 +2.54e+2 1.32e+2 +2.85e+2 1.48e+2 +5.60e+2 7.37e+1 +4.17e+2 1.47e+2 +3.47e+2 1.32e+2 +1.76e+2 1.77e+2 +5.22e+2 7.37e+1 +4.60e+2 7.37e+1 +5.33e+2 1.47e+2 +3.14e+1 1.47e+2 +2.49e+2 1.47e+2 +3.24e+2 1.47e+2 +8.15e+1 1.32e+2 +4.51e+2 1.47e+2 +2.89e+2 1.47e+2 +1.88e+2 1.18e+2 +5.62e+2 7.37e+1 +3.23e+2 1.47e+2 +1.76e+2 1.47e+2 +3.04e+1 7.37e+1 +5.05e+2 1.46e+2 +3.43e+2 1.47e+2 +2.09e+2 1.18e+2 +9.43e+1 1.47e+2 +1.83e+2 1.18e+2 +1.30e+2 1.47e+2 +4.57e+2 1.47e+2 +4.59e+2 1.47e+2 +2.72e+2 1.47e+2 +2.74e+2 1.47e+2 +5.61e+2 7.37e+1 +1.38e+2 1.47e+2 +1.40e+2 1.47e+2 +1.62e+2 1.47e+2 +1.29e+2 1.47e+2 +6.48e+1 1.32e+2 +6.17e+2 1.47e+2 +1.47e+1 1.32e+2 +2.11e+2 1.18e+2 +3.63e+1 1.91e+2 +1.61e+2 1.47e+2 +4.81e+1 1.32e+2 +2.97e+2 1.32e+2 +2.12e+2 1.18e+2 +8.94e+1 1.18e+2 +2.21e+2 1.18e+2 +3.17e+2 1.16e+2 +3.19e+2 1.16e+2 +1.96e+1 1.75e+2 +1.71e+2 1.32e+2 +2.61e+2 1.48e+2 +2.82e+2 1.18e+2 +2.01e+2 1.47e+2 +3.34e+1 1.32e+2 +2.37e+2 1.32e+2 +2.89e+2 1.32e+2 +1.36e+2 1.47e+2 +4.70e+2 1.47e+2 +4.72e+2 1.47e+2 +5.23e+2 1.47e+2 +2.22e+2 1.18e+2 +7.86e+2 1.18e+2 +2.80e+2 1.47e+2 +2.32e+2 8.85e+1 +2.36e+2 1.32e+2 +3.06e+2 1.32e+2 +1.90e+2 1.18e+2 +4.21e+2 1.18e+2 +4.71e+1 1.32e+2 +2.79e+2 1.18e+2 +3.27e+2 1.47e+2 +1.14e+2 1.18e+2 +4.12e+1 1.75e+2 +1.37e+1 1.32e+2 +6.58e+1 1.32e+2 +1.69e+2 1.18e+2 +4.22e+2 1.18e+2 +2.84e+2 1.18e+2 +7.88e+2 1.18e+2 +1.70e+2 1.18e+2 +5.36e+2 7.37e+1 +2.79e+2 8.85e+1 +2.20e+2 1.18e+2 +1.71e+2 1.18e+2 +2.31e+2 8.85e+1 +3.29e+2 1.47e+2 +3.31e+2 1.47e+2 +1.68e+2 1.18e+2 +7.48e+2 1.47e+2 +2.95e+2 1.47e+2 +4.72e+2 1.18e+2 +1.33e+2 1.47e+2 +2.86e+2 1.32e+2 +6.17e+2 1.18e+2 +9.53e+1 1.47e+2 +4.32e+1 1.32e+2 +2.88e+2 1.18e+2 +4.20e+2 1.18e+2 +6.99e+2 1.18e+2 +6.26e+2 1.18e+2 +6.03e+2 1.47e+2 +2.33e+2 1.32e+2 +2.89e+2 1.32e+2 +7.79e+2 1.18e+2 +1.74e+2 1.47e+2 +6.09e+1 1.18e+2 +2.87e+2 1.18e+2 +7.16e+2 1.47e+2 +1.73e+2 1.47e+2 +1.15e+2 1.18e+2 +6.16e+2 1.18e+2 +5.79e+1 1.32e+2 +2.15e+2 1.18e+2 +1.64e+2 1.18e+2 +7.00e+2 1.18e+2 +6.27e+2 1.18e+2 +8.45e+1 1.18e+2 +2.82e+2 1.77e+2 +2.84e+2 1.78e+2 +2.33e+2 1.47e+2 +1.91e+2 1.18e+2 +7.07e+2 1.18e+2 +2.26e+1 1.47e+2 +2.17e+2 1.18e+2 +2.07e+2 1.18e+2 +1.14e+2 1.47e+2 +7.85e+2 1.18e+2 +1.17e+2 1.18e+2 +6.22e+2 1.47e+2 +8.84e+1 1.18e+2 +8.55e+1 1.18e+2 +5.11e+2 1.18e+2 +7.96e+1 1.32e+2 +2.16e+2 1.18e+2 +7.74e+2 1.18e+2 +2.24e+2 1.18e+2 +5.17e+2 1.18e+2 +2.75e+2 1.18e+2 +7.17e+1 1.32e+2 +2.96e+2 1.47e+2 +2.98e+2 1.47e+2 +6.77e+2 1.18e+2 +6.19e+1 1.18e+2 +1.65e+2 8.85e+1 +7.84e+2 1.18e+2 +4.42e+1 1.32e+2 +2.35e+1 7.37e+1 +1.72e+2 1.18e+2 +8.35e+1 1.32e+2 +7.27e+2 1.18e+2 +2.12e+2 1.32e+2 +3.93e+2 1.47e+2 +3.95e+2 1.47e+2 +3.97e+2 1.47e+2 +5.99e+1 1.18e+2 +5.06e+2 1.47e+2 +6.80e+2 1.18e+2 +7.06e+2 1.18e+2 +7.10e+2 1.18e+2 +7.92e+2 1.18e+2 +2.19e+2 1.18e+2 +5.14e+2 1.47e+2 +3.75e+2 1.18e+2 +4.19e+2 1.18e+2 +5.18e+2 1.18e+2 +8.65e+1 1.18e+2 +1.81e+2 1.18e+2 +4.41e+2 1.47e+2 +2.66e+2 1.18e+2 +9.43e+1 1.18e+2 +6.30e+2 1.18e+2 +6.79e+2 1.18e+2 +5.32e+2 7.37e+1 +7.32e+2 1.18e+2 +3.39e+2 1.47e+2 +2.28e+2 1.47e+2 +2.74e+2 1.18e+2 +5.09e+2 1.18e+2 +2.92e+2 1.18e+2 +1.10e+2 1.18e+2 +4.47e+2 1.18e+2 +2.49e+2 1.16e+2 +3.84e+2 1.47e+2 +8.25e+1 1.32e+2 +1.46e+2 1.18e+2 +6.29e+2 1.18e+2 +5.15e+2 1.18e+2 +6.22e+2 1.18e+2 +1.66e+2 1.18e+2 +3.47e+2 1.18e+2 +4.63e+2 1.18e+2 +6.97e+2 1.18e+2 +5.43e+2 1.18e+2 +9.63e+1 1.18e+2 +1.47e+2 1.18e+2 +1.76e+2 1.18e+2 +7.31e+2 1.17e+2 +5.79e+2 8.85e+1 +3.77e+2 1.18e+2 +1.36e+2 1.18e+2 +5.81e+2 1.18e+2 +2.43e+2 1.32e+2 +6.24e+2 1.18e+2 +5.95e+2 1.18e+2 +6.23e+2 1.18e+2 +4.48e+2 1.18e+2 +6.69e+2 1.18e+2 +4.11e+2 1.18e+2 +2.18e+2 1.18e+2 +6.68e+2 1.18e+2 +7.16e+2 1.18e+2 +2.90e+2 1.18e+2 +5.42e+2 1.18e+2 +2.26e+2 1.18e+2 +5.94e+2 1.18e+2 +6.19e+2 1.47e+2 +5.96e+2 1.18e+2 +4.36e+2 1.18e+2 +1.50e+2 1.18e+2 +7.69e+2 1.18e+2 +3.55e+2 1.18e+2 +5.08e+2 1.18e+2 +2.68e+2 1.32e+2 +6.21e+2 1.18e+2 +2.26e+1 1.62e+2 +4.37e+2 1.18e+2 +5.16e+2 8.85e+1 +5.00e+2 8.85e+1 +5.93e+2 1.18e+2 +4.10e+2 1.18e+2 +3.53e+2 1.18e+2 +1.09e+2 1.18e+2 +5.07e+2 1.18e+2 +6.66e+2 1.18e+2 +7.28e+2 1.18e+2 +5.06e+2 1.18e+2 +4.69e+2 1.18e+2 +4.71e+2 1.18e+2 +1.21e+2 1.18e+2 +5.97e+2 1.18e+2 +3.03e+2 1.32e+2 +7.20e+2 1.18e+2 +3.61e+2 1.32e+2 +3.63e+2 1.32e+2 +4.35e+2 1.18e+2 +7.35e+2 1.18e+2 +5.21e+2 1.18e+2 +8.15e+1 1.18e+2 +6.73e+2 1.18e+2 +3.83e+2 1.47e+2 +5.46e+2 1.18e+2 +5.79e+2 1.18e+2 +5.32e+2 1.18e+2 +2.52e+2 1.18e+2 +4.64e+2 1.18e+2 +5.44e+2 1.18e+2 +4.49e+2 1.18e+2 +4.51e+2 1.18e+2 +3.14e+2 1.18e+2 +7.15e+2 1.18e+2 +6.14e+2 1.18e+2 +6.67e+2 1.18e+2 +6.59e+2 1.18e+2 +1.73e+2 1.18e+2 +2.64e+2 1.18e+2 +6.00e+2 1.18e+2 +1.53e+2 1.18e+2 +3.24e+1 1.32e+2 +5.82e+2 1.18e+2 +3.44e+2 1.18e+2 +3.15e+2 1.32e+2 +1.51e+2 1.18e+2 +1.39e+2 1.18e+2 +6.76e+2 1.18e+2 +1.30e+2 1.18e+2 +3.99e+2 1.18e+2 +4.75e+2 7.37e+1 +2.49e+2 1.18e+2 +3.13e+2 1.18e+2 +5.05e+2 1.18e+2 +5.98e+2 1.18e+2 +3.85e+2 1.18e+2 +7.34e+2 1.18e+2 +6.31e+2 1.18e+2 +7.25e+2 1.18e+2 +4.70e+2 1.18e+2 +3.84e+2 1.18e+2 +1.62e+2 1.18e+2 +7.19e+2 1.18e+2 +6.28e+2 1.47e+2 +4.98e+2 1.18e+2 +6.04e+2 1.48e+2 +6.58e+2 1.18e+2 +1.23e+2 1.18e+2 +3.83e+2 1.18e+2 +4.88e+2 1.47e+2 +2.04e+2 1.18e+2 +3.18e+2 1.18e+2 +7.95e+2 1.18e+2 +6.32e+2 1.18e+2 +1.41e+2 1.18e+2 +2.91e+2 1.47e+2 +6.03e+2 1.18e+2 +5.90e+2 1.18e+2 +2.34e+2 1.18e+2 +2.45e+2 1.18e+2 +3.32e+2 1.47e+2 +7.13e+2 1.18e+2 +7.71e+2 1.18e+2 +3.11e+2 1.32e+2 +5.85e+2 1.18e+2 +4.67e+2 1.18e+2 +2.47e+2 1.18e+2 +7.67e+2 1.18e+2 +4.72e+2 7.37e+1 +3.45e+2 1.18e+2 +6.63e+2 1.18e+2 +4.18e+2 1.47e+2 +4.20e+2 1.47e+2 +1.07e+2 1.18e+2 +3.04e+2 1.32e+2 +1.05e+2 1.32e+2 +5.61e+2 1.18e+2 +7.68e+2 1.18e+2 +2.87e+2 1.32e+2 +3.74e+2 1.18e+2 +4.50e+2 1.18e+2 +1.26e+2 1.18e+2 +5.60e+2 1.18e+2 +7.47e+1 1.18e+2 +3.42e+2 1.18e+2 +6.72e+2 1.18e+2 +5.52e+2 1.18e+2 +2.06e+2 1.18e+2 +5.37e+2 1.18e+2 +4.66e+2 1.18e+2 +2.59e+2 1.18e+2 +7.37e+1 1.18e+2 +1.25e+2 1.18e+2 +2.99e+2 1.18e+2 +6.71e+2 1.18e+2 +5.44e+2 1.47e+2 +7.62e+2 1.47e+2 +4.38e+2 1.18e+2 +5.32e+2 1.47e+2 +5.91e+2 1.18e+2 +1.61e+2 1.18e+2 +2.53e+2 1.18e+2 +1.06e+2 1.18e+2 +5.99e+2 1.18e+2 +3.70e+2 1.18e+2 +6.19e+1 1.32e+2 +1.24e+2 1.18e+2 +5.35e+2 7.37e+1 +6.96e+2 1.18e+2 +2.56e+2 1.18e+2 +3.68e+2 1.18e+2 +3.96e+2 1.18e+2 +7.37e+2 1.18e+2 +3.53e+2 1.32e+2 +5.90e+2 1.77e+2 +2.05e+2 1.18e+2 +2.62e+2 1.18e+2 +2.27e+2 1.18e+2 +2.28e+2 1.18e+2 +7.38e+2 1.18e+2 +2.81e+2 1.75e+2 +5.29e+2 1.18e+2 +3.51e+2 1.18e+2 +6.05e+2 1.18e+2 +6.38e+1 1.18e+2 +5.70e+2 1.18e+2 +5.23e+2 1.18e+2 +1.28e+2 1.18e+2 +3.16e+2 1.18e+2 +7.65e+2 1.18e+2 +1.54e+2 1.18e+2 +2.02e+2 1.18e+2 +5.34e+2 1.18e+2 +3.79e+2 1.18e+2 +1.00e+2 1.18e+2 +3.80e+2 1.18e+2 +4.33e+2 1.18e+2 +5.50e+1 8.85e+1 +3.08e+2 1.18e+2 +2.33e+2 1.18e+2 +4.61e+2 1.18e+2 +4.43e+2 1.18e+2 +5.24e+2 1.18e+2 +9.53e+1 1.75e+2 +1.79e+2 1.47e+2 +1.81e+2 1.47e+2 +1.06e+2 8.85e+1 +4.25e+2 1.18e+2 +3.00e+2 1.18e+2 +6.09e+1 1.32e+2 +5.10e+2 1.47e+2 +1.56e+2 1.18e+2 +3.25e+2 1.18e+2 +3.50e+2 1.18e+2 +5.63e+2 1.18e+2 +2.55e+1 1.62e+2 +7.56e+1 1.18e+2 +3.52e+2 1.18e+2 +5.25e+2 1.47e+2 +7.24e+2 1.18e+2 +2.55e+2 1.18e+2 +3.27e+2 1.18e+2 +3.22e+2 1.18e+2 +1.55e+2 1.18e+2 +1.06e+2 1.32e+2 +6.06e+2 1.18e+2 +9.83e+1 1.18e+2 +3.01e+2 1.18e+2 +6.15e+2 1.47e+2 +5.22e+2 1.18e+2 +7.63e+2 1.18e+2 +6.44e+2 1.47e+2 +6.46e+2 1.47e+2 +6.48e+2 1.47e+2 +1.94e+2 1.18e+2 +3.86e+2 1.18e+2 +4.94e+2 1.47e+2 +7.22e+2 1.18e+2 +3.94e+2 1.18e+2 +7.46e+2 1.18e+2 +4.28e+2 1.18e+2 +4.17e+2 1.18e+2 +4.32e+2 1.18e+2 +5.11e+2 1.47e+2 +7.52e+2 1.18e+2 +5.66e+2 1.18e+2 +1.32e+2 1.18e+2 +1.58e+2 1.18e+2 +2.07e+2 1.47e+2 +1.33e+2 1.18e+2 +5.53e+2 1.18e+2 +1.78e+2 1.18e+2 +3.44e+1 1.32e+2 +3.52e+2 1.32e+2 +6.95e+2 1.18e+2 +6.55e+2 1.18e+2 +3.67e+2 1.18e+2 +2.54e+2 1.18e+2 +7.62e+2 1.18e+2 +3.07e+2 1.18e+2 +3.32e+2 1.18e+2 +1.57e+2 1.18e+2 +3.54e+2 1.32e+2 +1.02e+2 1.18e+2 diff --git a/src/graphics/grxlib.c b/src/graphics/grxlib.c new file mode 100644 index 0000000..0e6896e --- /dev/null +++ b/src/graphics/grxlib.c @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include + +static const char cvs_ident[] = "$Id$"; + +#ifdef _AIX +# include +#else +# include +#endif + +#include "grxlib.h" + +/*----------------------------------------------------------------------*/ + +void Done (void) { putchar (':'); } +void StartLine (long id) { printf ("\033GL%ld", id); } +void StartPoint (long id) { printf ("\033GP%ld", id); } +void StartFill (long id) { printf ("\033GF%ld", id); } +void Extend (int x, int y) { printf (";%d;%d", x, y); } +void FillArea (int x1, int y1, int x2, int y2) +{ + printf (";%d;%d;%d;%d", x1, y1, x2, y2); +} + +void PlaceText (long id, int x, int y, int mode, char *text) +{ + printf ("\033GT%ld;%d;%d;%d;%d:%s", id, x, y, mode, strlen(text), text); + fflush (stdout); +} + +void ClearWindow (long id) { printf ("\033GC%ld:", id); } +void ForeColor (int col) { printf ("\033[3%dm", (col<0||col>7)?0:col); } +void DefaultRendition (void) { printf ("\033[m"); } + +#define LINESZ 100 +static char line [LINESZ]; +static FILE *infd = NULL; + +long +CreateWin (int x, int y, int w, int h) +{ + long id = 0; + + fflush (stdout); + printf ("\033GW%d;%d;%d;%d:", x, y, w, h); + fflush (stdout); + while (1) + { + if ((fgets (line, LINESZ, infd) != NULL) && + (sscanf (line,"\033W%ld", &id) == 1)) + break; + } + return id; +} + +void +QueryWin (long id, int *nfwidth, int *nfheight) +{ + int id1, x, y, width, height, fwidth, fheight; + printf ("\033GG%ld:",id); + fflush (stdout); + while (1) + { + if ((fgets (line, sizeof(line), infd) != NULL) && + (sscanf (line,"\033G%ld %ld %ld %ld %ld %ld %ld %ld %ld", + &id1, &x, &y, &width, &height, + &fwidth, &fheight, nfwidth, nfheight) != 0)) + break; + } +} + +int +WaitForCarriageReturn (long *win, int *x, int *y) +{ + int i, len; + + fgets (line, LINESZ, infd); + line [LINESZ-1] = 0; + len = strlen (line); + for (i = 0; i < len; i++) + { + if (line [i] == '\033') + { + int ret = 1; + i++; + switch (line[i]) { + case 'R': ret++; + /* drop */ + case 'P': + sscanf (&line[i+1],"%ld;%d;%d", win, x, y); + return ret; + break; + } + } + } + return 0; +} + +static int fno2; +static struct termios ttmode; + +int +InitializeGraphics (int scroll_text_up) +{ + int fno, i; + char *screen_tty; + struct winsize winsize; + + fno = fileno (stdout); + if (!isatty (fno)) + { + fprintf (stderr, "stdout must be a tty\n"); + return 0; + } + screen_tty = ttyname (fno); + ioctl (fno, TCGETS, (char *)&ttmode); + ttmode.c_lflag &= ~ECHO; + ioctl (fno, TCSETS, (char *)&ttmode); + + infd = fopen (screen_tty, "rw"); + + fno2 = fileno (infd); + ioctl (fno2, TCGETS, (char *)&ttmode); + ttmode.c_lflag &= ~ECHO; + ioctl (fno2, TCSETS, (char *)&ttmode); + + /* query rxvt to find if graphics are available */ + fflush (stdout); + printf ("\033GQ"); + fflush (stdout); + while (1) + { + if ((fgets (line, LINESZ, infd) != NULL) && + (sscanf (line,"\033G%d", &i) == 1)) + { + if (!i) + { + fprintf (stderr, "rxvt graphics not available\n"); + CloseGraphics (); + return 0; + } + break; + } + } + if (scroll_text_up) + { + ioctl (fno, TIOCGWINSZ, &winsize); + fflush (stdout); + for (i = 0; i < winsize.ws_row; i++) + putchar ('\n'); + fflush (stdout); + } + return i; +} + +void +CloseGraphics (void) +{ + DefaultRendition (); + fflush (stdout); + ttmode.c_lflag |= ECHO; + ioctl (fno2, TCSETS, (char *)&ttmode); + fclose (infd); +} +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/graphics/grxlib.h b/src/graphics/grxlib.h new file mode 100644 index 0000000..2b44e78 --- /dev/null +++ b/src/graphics/grxlib.h @@ -0,0 +1,28 @@ +#include "../grx.h" /* text alignment */ + +/*function pointer to either StartLine or StartPoint */ +typedef void (*LineFunction) (long id); + +#ifdef __cplusplus +extern "C" { +#endif + extern void StartLine (long id); + extern void StartPoint (long id); + extern void Extend (int x, int y); + extern void StartFill (long id); + extern void FillArea (int x1, int y1, int x2, int y2); + extern void Done (void); + extern void PlaceText (long id, int x, int y, int mode, char *text); + + extern void ClearWindow (long id); + extern long CreateWin (int x, int y, int w, int h); + extern void QueryWin (long id, int *nfwidth, int *nfheight); + extern void ForeColor (int color); + extern void DefaultRendition (void); + extern int WaitForCarriageReturn (long *win, int *x, int *y); + extern int InitializeGraphics (int scroll_text_up); + extern void CloseGraphics (void); +#ifdef __cplusplus +} +#endif +/*----------------------- end-of-file (C header) -----------------------*/ diff --git a/src/graphics/qplot.c b/src/graphics/qplot.c new file mode 100644 index 0000000..5e1e253 --- /dev/null +++ b/src/graphics/qplot.c @@ -0,0 +1,257 @@ +#include +#include +#include +#include +#include "grxlib.h" + +static const char cvs_ident[] = "$Id$"; + +#define Real float + +#ifndef GRX_SCALE +# define GRX_SCALE 10000 +#endif + +#define DEFAULT_DATA_FILE "data" + +static void +axis_round (Real *min, Real *max, Real *grid_spacing) +{ + int logspace; + + logspace = (int)(log10 ((*max - *min)/10.0) + 0.5); + *grid_spacing = pow (10, (double)logspace); + *min = (Real)((int)(*min / (*grid_spacing))) * (*grid_spacing); + *max = (Real)((int)(*max / (*grid_spacing))+1) * (*grid_spacing); +} + +static int +nice_end (int junk) +{ + CloseGraphics (); + putchar ('\n'); + exit (EXIT_SUCCESS); + return 0; +} + +int +main (int argc, char **argv) +{ + char line[256], *file = NULL; + long id,winclick; + int Do_Start = 1,tmp; + Real x[1000000], y[1000000]; + Real nls[1000]; + int m, p, i, j, n, nchars, theight, twidth, xclick, yclick; + int downx = 1000,downy = 1000,upx,upy; + Real xmax, xmin, ymax, ymin, xdiff, ydiff, xgrid_spacing, ygrid_spacing; + FILE *fd; + char axis[100]; + + LineFunction linetype = StartLine; + + ymax = xmax = -HUGE_VAL; + ymin = xmin = HUGE_VAL; + + for (i = 1; i < argc; i++) + { + if (*argv[i] == '-') + { + if (!strcmp (argv[i], "-nl")) + linetype = StartPoint; + else if (argv[i][1] == '\0') /* use stdin */ + file = argv [i]; + else + { + + fprintf(stderr, + "Usage:\n\t %s [options] [file]\n\n", argv[0]); + fprintf(stderr, + "where options include:\n" + " -pt plot with points instead of lines\n\n"); + + fprintf(stderr, + "file name `-' specifies stdin\n" + "if no file name is specified, " + "the default is \"%s\"\n\n", + DEFAULT_DATA_FILE); + + return EXIT_FAILURE; + } + } + else + { + file = argv [i]; + } + } + + if (!strcmp (file, "-")) + { + fd = stdin; + file = "stdin"; + } + else + { + if (file == NULL) file = DEFAULT_DATA_FILE; + + if ((fd = fopen (file, "r")) == NULL) + { + fprintf (stderr, "%s: can't open file \"%s\"\n", argv[0], file); + return EXIT_FAILURE; + } + } + m = 0; + p = 0; + while (fgets(line, sizeof(line),fd) != NULL) + { + if (sscanf(line,"%f %f",&x[m], &y[m]) == 2) + { + if (x[m] > xmax) xmax = x[m]; else if (x[m] < xmin) xmin = x[m]; + if (y[m] > ymax) ymax = y[m]; else if (y[m] < ymin) ymin = y[m]; + m++; + } + else + { + nls [p] = m; + p++; + } + } + nls [p++] = m; + + if (m == 0) + return; + + signal (SIGTERM, nice_end); + signal (SIGSTOP, nice_end); + signal (SIGTSTP, nice_end); + signal (SIGINT, nice_end); + signal (SIGQUIT, nice_end); + if (!InitializeGraphics (1)) + return EXIT_FAILURE; + + n = 1; + do + { + axis_round (&xmin, &xmax, &xgrid_spacing); + axis_round (&ymin, &ymax, &ygrid_spacing); + + id = CreateWin (0, 0, GRX_SCALE, GRX_SCALE); + if (id == 0) + { + fprintf (stderr,"Help id = 0\n"); + return EXIT_FAILURE; + } + /* Fill the window in black for real eye-catching graphics! */ + ForeColor (0); + StartFill (id); + FillArea (0, 0, GRX_SCALE, GRX_SCALE); + Done (); + + /* draw outline box in white */ + ForeColor (7); + + /* Draw outline box */ + StartLine(id); + Extend (1000, 1000); + Extend (1000, 9000); + Extend (9000, 9000); + Extend (9000, 1000); + Extend (1000, 1000); + Done(); + + /* Draw the data - either lines or dots */ + xdiff = 8000 / (xmax-xmin); + ydiff = 8000 / (ymax-ymin); + + for (i = j = 0; j < p; j++) + { + int n = 0; + + ForeColor (j%6+1); + while (((x[i] < xmin) || (x[i] > xmax) || + (y[i] < ymin) || (y[i] > ymax)) && (i < nls [j])) + i++; + + while (i < nls [j]) + { + if (n == 0) + linetype (id); + Extend (1000+(x[i]-xmin)*xdiff,9000-(y[i]-ymin)*ydiff); + n++; + if (n > 450) + { + Done (); + n = 0; + continue; + } + i++; + while ((i < nls [j]) && + ((x [i] < xmin) || (x [i] > xmax) || + (y [i] < ymin) || (y [i] > ymax))) + i++; + } + if (n > 0) + Done (); + } + + /* Do axis labels in black */ + ForeColor (7); + QueryWin (id, &twidth,&theight); + PlaceText (id, GRX_SCALE/2, 0, HCENTER_TEXT|TOP_TEXT, file); + PlaceText (id, GRX_SCALE/2, GRX_SCALE, HCENTER_TEXT|BOTTOM_TEXT, "X"); + PlaceText (id, 0, GRX_SCALE/2, LEFT_TEXT|VCENTER_TEXT, "Y"); + sprintf (axis, "%f", ymax); + nchars = 1000 / twidth; + + axis [nchars] = 0; + PlaceText (id, GRX_SCALE/10, GRX_SCALE/10, + RIGHT_TEXT|TOP_TEXT, axis); + sprintf (axis, "%f", ymin); + axis [nchars] = 0; + PlaceText (id, GRX_SCALE/10, 9*GRX_SCALE/10, + RIGHT_TEXT|BOTTOM_TEXT,axis); + sprintf (axis, "%f",xmax); + PlaceText (id, 9*GRX_SCALE/10, 9*GRX_SCALE/10, + HCENTER_TEXT|TOP_TEXT,axis); + sprintf (axis,"%f",xmin); + PlaceText (id, GRX_SCALE/10, 9*GRX_SCALE/10, + HCENTER_TEXT|TOP_TEXT,axis); + fflush (stdout); + + do + { + n = WaitForCarriageReturn (&winclick, &xclick, &yclick); + switch (n) { + case 1: + downx = xclick; + downy = yclick; + break; + case 2: + upx = xclick; + upy = yclick; + if (upx < downx) + { + tmp = downx; + downx = upx; + upx = tmp; + } + if (upy < downy) + { + tmp = downy; + downy = upy; + upy = tmp; + } + xmin = (xmax - xmin) * (downx - 1000) / (8000) + xmin; + xmax = (xmax - xmin) * (upx - 1000) / (8000) + xmin; + ymax = ymax - (ymax - ymin) * (downy - 1000) / (8000); + ymin = ymax - (ymax - ymin) * (upy - 1000) / (8000); + break; + } + } + while (n && (n != 2)); + } + while (n); + nice_end (EXIT_SUCCESS); + return EXIT_SUCCESS; +} +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/grkelot.c b/src/grkelot.c new file mode 100644 index 0000000..7e328eb --- /dev/null +++ b/src/grkelot.c @@ -0,0 +1,389 @@ +/* + * File: grkelot.c + * + * Synopsis: string -> greek ELOT928 or IBM437 string; + * 4-state FSM implementation. + * + * System: Any (ANSI C) + * + * This is code derived from a more generic key remapper written by the same + * author and used in other environments. It was not written only + * for greek kbd bindings. An extension to other languages is easy + * (well don't know how the FSM lends itself to Far East languages). + * + * The FSM can have MAX_STATES states (change it for more). + * Each state contains: + * 1. many tranlsation tables (registered via kstate_add_xlat()) + * 2. many switch codes for transition to other states (registered via + * kstate_add_switcher()) : limit is static now: MAX_SWITCHER + * 3. life: the number of xlations allowed in a state (0 = unlimited) + * + * Format of tranlation strings: + * -:n1,n2,n3,... + * Format of switcher string: + * A: + * (other switchers apart from A=ascii can be supported; not in this context) + * Format of life string: + * L (N=0,1,...) + * + * Copyright (c) 1994,1995 Angelo Haritsis. All rights reserved. + * + * Redistribution and use in source and binary forms are permitted provided + * that the above copyright notice and this paragraph are duplicated in all + * such forms and that any documentation, advertising materials, and other + * materials related to such distribution and use acknowledge that the + * software was developed by Angelo Haritsis. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * NB: DO NOT ALTER! THIS CODE IS USED IN MANY PLATFORMS!!! + * + * TODO: make it more dynamic (linked lists is an idea but slower) + */ + +static const char cvs_ident[] = "$Id$"; + +#include "feature.h" +#include "grkelot.h" + +#ifdef GREEK_SUPPORT +# include "grkelot.h" +# include +# include + +/* --- Macros, Types --------- */ +# define MAX_STATES 4 /* max # states for the FSM */ +# define MAX_SWITCHER 2U /* per state */ +# define MAX_VAL 256 /* for temp allocation */ + +typedef unsigned char u_char; +typedef unsigned int u_int; +typedef unsigned long u_long; + +typedef struct s_xlat { + u_int first, last; + u_int *pval; /* array of translated values */ +} K_XLAT; + +typedef struct s_switch { + u_char type; /* Ascii, Virtual, Scan */ + u_int code; + u_char nextstate; + u_char on; /* current state of key: 0 = off */ +} K_SWITCH; + +typedef struct s_state { + u_int num_xlat; /* number of translations */ + K_XLAT *xlat; /* State translations ((dynamic - realloc'ed) */ + u_int num_switcher; /* number of switcher keys */ + K_SWITCH switcher[MAX_SWITCHER]; /* switcher keys to other states */ + u_char life; /* 0 = until switched by key */ + u_char prev_state; /* filled when jumped to a new state */ +} K_STATE; + +/* type for each one of the different greek standards (xlat types) */ +typedef struct s_xlat_type { + char *plain; + char *accent; + char *accent_xtra; + char *umlaut; + char *acc_uml; +} XLAT_TYPE; + +/* --- Local Data ------------ */ +static K_STATE State[MAX_STATES]; + +/* Current State */ +static u_char nStateNow = 0; +static K_STATE *pStateNow = &State[0]; +static int GreekMode = GREEK_ELOT928; + +/* + * The following are hard-coded for now. The idea is that such strings would + * be read from a config file making it possible to change language/encodings + * more flexibly. + */ +/* elot 928 xlations */ +static char elot_xlat_plain[] = "65-122:193,194,216,196,197,214,195,199,201,206,202,203,204,205,207,208,81,209,211,212,200,217,87,215,213,198,91,92,93,94,95,96,225,226,248,228,229,246,227,231,233,238,234,235,236,237,239,240,113,241,243,244,232,249,242,247,245,230"; + +/* c and s give copyright and section sign */ +static char elot_xlat_acc[] = "65-122:182,194,216,196,184,214,195,185,186,206,202,203,204,205,188,208,81,209,211,212,200,191,87,215,190,198,91,92,93,94,95,96,220,226," /*248 */ "169,228,221,246,227,222,223,238,234,235,236,237,252,240,113,241," /*243 */ "167,244,232,254,242,247,253,230"; +static char elot_xlat_acc_xtra[] = "46-62:183,47,48,49,50,51,52,53,54,55,56,57,58,59,171,61,187"; /* anw teleia, quotes */ +static char elot_xlat_uml[] = "65-122:193,194,216,196,197,214,195,199,218,206,202,203,204,205,207,208,81,209,211,212,200,217,87,215,219,198,91,92,93,94,95,96,225,226,248,228,229,246,227,231,250,238,234,235,236,237,239,240,113,241,243,244,232,249,242,247,251,230"; +static char elot_xlat_umacc[] = "65-122:193,194,216,196,197,214,195,199,201,206,202,203,204,205,207,208,81,209,211,212,200,217,87,215,213,198,91,92,93,94,95,96,225,226,248,228,229,246,227,231,192,238,234,235,236,237,239,240,113,241,243,244,232,249,242,247,224,230"; + +/* ibm 437 xlations */ +static char i437_xlat_plain[] = "65-122:128,129,150,131,132,148,130,134,136,141,137,138,139,140,142,143,81,144,145,146,135,151,87,149,147,133,91,92,93,94,95,96,152,153,175,155,156,173,154,158,160,165,161,162,163,164,166,167,113,168,169,171,159,224,170,174,172,157"; +static char i437_xlat_acc[] = "65-122:234,129,150,131,235,148,130,236,237,141,137,138,139,140,238,143,81,144,145,146,135,240,87,149,239,133,91,92,93,94,95,96,225,153,175,155,226,173,154,227,229,165,161,162,163,164,230,167,113,168,169,171,159,233,170,174,231,157"; +static char i437_xlat_acc_xtra[] = "46-46:250"; /* anw teleia */ +static char i437_xlat_uml[] = "65-122:128,129,150,131,132,148,130,134,136,141,137,138,139,140,142,143,81,144,145,146,135,151,87,149,147,133,91,92,93,94,95,96,152,153,175,155,156,173,154,158,228,165,161,162,163,164,166,167,113,168,169,171,159,224,170,174,232,157"; +static char i437_xlat_umacc[] = "65-122:128,129,150,131,132,148,130,134,136,141,137,138,139,140,142,143,81,144,145,146,135,151,87,149,147,133,91,92,93,94,95,96,152,153,175,155,156,173,154,158,42,165,161,162,163,164,166,167,113,168,169,171,159,224,170,174,42,157"; + + +/* + * currently ELOT928 and IBM437 are supported; easy to include others + * (not recommended: stick to just these 2 if not only the ELOT one) + */ +static XLAT_TYPE xlat_type[] = +{ + {elot_xlat_plain, elot_xlat_acc, elot_xlat_acc_xtra, elot_xlat_uml, elot_xlat_umacc}, + {i437_xlat_plain, i437_xlat_acc, i437_xlat_acc_xtra, i437_xlat_uml, i437_xlat_umacc}, +}; + +/* the current trasnaltion type */ +static XLAT_TYPE *xlat_now = &xlat_type[GREEK_ELOT928]; + +# define NUM_XLAT_TYPES (sizeof(xlat_type) / sizeof(xlat_type[0])) + +static void kstate_add_xlat(char *str); +static void kstate_add_switcher(char *str); +static void kstate_set_life(char *str); + +/* --- Functions ------------- */ +static void +kstate_setcurr(int stateno) +{ + u_char prev_state; + + if ((u_int) stateno > (u_int) MAX_STATES) + return; + if (pStateNow->life == 1) + prev_state = pStateNow->prev_state; + else + prev_state = nStateNow; + pStateNow = &State[nStateNow = stateno]; + pStateNow->prev_state = prev_state; +} + +static void +kstate_init(void) +{ + pStateNow->num_xlat = pStateNow->num_switcher = pStateNow->life = pStateNow->prev_state = 0; + pStateNow->xlat = NULL; +} + +static void +kstate_end(void) +{ + int i; + + for (i = 0; i < pStateNow->num_xlat; i++) + free(pStateNow->xlat[i].pval); + if (pStateNow->num_xlat > 0) + free(pStateNow->xlat); +} + +/* + * Hard coded ELOT-928 translations. Could read these from an rc-type file + * to support other remappers. + */ +static void +kstate_init_all(int greek_mode) +{ + /* the translation tables for the 4 FSM states for ELOT-928 mappings */ + int i; + + for (i = 0; i < MAX_STATES; i++) { + kstate_setcurr(i); + kstate_init(); + } + if (greek_mode < 0 || greek_mode >= NUM_XLAT_TYPES) /* avoid death */ + greek_mode = GREEK_ELOT928; + xlat_now = &xlat_type[greek_mode]; + kstate_setcurr(0); + kstate_add_xlat(xlat_now->plain); + kstate_add_switcher("A;:1"); + kstate_add_switcher("A::2"); + kstate_set_life("L0"); + + kstate_setcurr(1); + kstate_add_xlat(xlat_now->accent); + kstate_add_xlat(xlat_now->accent_xtra); + kstate_add_switcher("A::3"); + kstate_set_life("L1"); + + kstate_setcurr(2); + kstate_add_xlat(xlat_now->umlaut); + kstate_add_switcher("A;:3"); + kstate_set_life("L1"); + + kstate_setcurr(3); + kstate_add_xlat(xlat_now->acc_uml); + kstate_set_life("L1"); +} + +static void +kstate_end_all(void) +{ + int i; + + for (i = 0; i < MAX_STATES; i++) { + kstate_setcurr(i); + kstate_end(); + } + kstate_setcurr(0); +} + +/* + * reset FSM + */ +static void +kstate_reset(void) +{ + kstate_setcurr(0); +} + +static void +kstate_add_xlat(char *str) +{ + K_XLAT *xlat; + u_int *pval_tmp; + char *sval; + int i; + + if (str == NULL) + return; + /* add a new xlat table in state */ + if (pStateNow->num_xlat == 0) { + pStateNow->xlat = malloc(sizeof(K_XLAT)); + } else /* prefer contiguous data, realloc */ + pStateNow->xlat = realloc(pStateNow->xlat, (pStateNow->num_xlat + 1) * sizeof(K_XLAT)); + xlat = &pStateNow->xlat[pStateNow->num_xlat]; + /* parse str and derive first, last, values */ + xlat->first = (u_int) atoi(strtok(str, "-")); + xlat->last = (u_int) atoi(strtok(NULL, ":")); + i = 0; + pval_tmp = calloc(MAX_VAL, sizeof(K_XLAT)); + while ((sval = strtok(NULL, ",")) != NULL) { + pval_tmp[i++] = (u_int) (atoi(sval)); + } + xlat->pval = calloc(i, sizeof(K_XLAT)); + if (xlat->pval != NULL) + memcpy(xlat->pval, pval_tmp, i * sizeof(u_int)); + free(pval_tmp); + pStateNow->num_xlat++; +} + +/* + * Ascii only for this implementation + */ +static void +kstate_add_switcher(char *str) +{ + K_SWITCH *switcher; + + if (str == NULL) + return; + if (pStateNow->num_switcher >= MAX_SWITCHER) + return; + switcher = &pStateNow->switcher[pStateNow->num_switcher]; + switch (switcher->type = str[0]) { + case 'A': /* ascii eg: A;:2 */ + switcher->code = str[1]; + switcher->nextstate = atoi(&str[3]); + break; + } + switcher->on = 0; + pStateNow->num_switcher++; +} + +/* L1 or L0 */ +static void +kstate_set_life(char *str) +{ + pStateNow->life = atoi(&str[1]); +} + +static unsigned int +kstate_cxlat(unsigned int c) +{ + int i; + + /* check for ascii switcher */ + for (i = 0; i < pStateNow->num_switcher; i++) + if (pStateNow->switcher[i].type == 'A' && /* only ascii here */ + c == pStateNow->switcher[i].code) { + kstate_setcurr(pStateNow->switcher[i].nextstate); + pStateNow->switcher[i].on = 1; + return ((unsigned int) -1); + } + /* do translation */ + for (i = 0; i < pStateNow->num_xlat; i++) + if (c >= pStateNow->xlat[i].first && c <= pStateNow->xlat[i].last) { + c = pStateNow->xlat[i].pval[c - pStateNow->xlat[i].first]; + break; + } + /* switch back to previous state if life of current is 1 */ + if (pStateNow->life == 1) + kstate_setcurr(pStateNow->prev_state); + return (c); +} + +# ifdef RXVT +void +greek_init(void) +{ + kstate_init_all(GreekMode); +} + +void +greek_end(void) +{ + kstate_end_all(); +} + +void +greek_reset(void) +{ + kstate_reset(); +} + +void +greek_setmode(int greek_mode) +{ + GreekMode = greek_mode; +} + +int +greek_getmode(void) +{ + return (GreekMode); +} + +/* + * xlate a given string in-place - return new string length + */ +int +greek_xlat(char *s, int num_chars) +{ + int i, count; + unsigned int c; + + for (i = 0, count = 0; i < num_chars; i++) { + c = kstate_cxlat((unsigned int) s[i]); + if (c != -1) + s[count++] = (char) c; + } + s[count] = '\0'; + return (count); +} + +# ifdef TEST +int +main(void) +{ + /*char text[] = "abcdef;aGDZXC"; */ + char text[] = "abcdef;a:ibgdezhuiklmnjoprstyfxcv"; + + kstate_init_all(GREEK_ELOT928); + printf("text: %s\n", text); + greek_xlat(text, strlen(text)); + printf("xlat'ed text: %s\n", text); + kstate_end_all(); + return 0; +} +# endif +# endif /* RXVT */ + +#endif /* GREEK_SUPPORT */ diff --git a/src/grkelot.h b/src/grkelot.h new file mode 100644 index 0000000..37531c2 --- /dev/null +++ b/src/grkelot.h @@ -0,0 +1,38 @@ +/* + * File: grkelot.h + * + * Synopsis: string -> greek ELOT928 string; 4-state FSM. + * + * Copyright (c) 1994 Angelo Haritsis. All rights reserved. + * + * Redistribution and use in source and binary forms are permitted provided + * that the above copyright notice and this paragraph are duplicated in all + * such forms and that any documentation, advertising materials, and other + * materials related to such distribution and use acknowledge that the + * software was developed by Angelo Haritsis. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Header$ + */ + +#ifndef _GRKELOT_H +# define _GRKELOT_H + +# define GREEK_ELOT928 0 +# define GREEK_IBM437 1 + +# ifdef __cplusplus +extern "C" { +# endif + extern void greek_init (void); + extern void greek_end (void); + extern void greek_reset (void); + extern void greek_setmode(int greek_mode); + extern int greek_getmode(void); + extern int greek_xlat (char *s, int num_chars); +# ifdef __cplusplus +} +# endif +#endif /* _GRKELOT_H */ diff --git a/src/grx.h b/src/grx.h new file mode 100644 index 0000000..fca8ad3 --- /dev/null +++ b/src/grx.h @@ -0,0 +1,53 @@ +/*--------------------------------*-C-*---------------------------------* + * File: grx.h + * + * Stuff for text alignment for special graphics mode + * + * alignment + * Top: + * text is placed so that the specified point is at the top of the + * capital letters + * Center: + * text is placed so that the specified point is equidistant from the + * bottom of descenders and the top of the capital letters + * Botton: + * text is placed so that the bottom of descenders is on the specified + * point + * Base: + * text is placed so that the bottom of the characters with no descenders + * is on the specified point + * Caps_Center: + * text is placed so that the specified point is equidistant from the + * bottom and tops of capital letters + *----------------------------------------------------------------------*/ +#ifndef _RXVTGRX_H +# define _RXVTGRX_H + +# define GRX_SCALE 10000 + +# define RIGHT_TEXT 0x10 +# define HCENTER_TEXT 0x20 +# define LEFT_TEXT 0x30 +# define HORIZONTAL_ALIGNMENT 0x70 + +# define TOP_TEXT 0x01 +# define VCENTER_TEXT 0x02 +# define BOTTOM_TEXT 0x03 +# define BASE_TEXT 0x04 +# define VCAPS_CENTER_TEXT 0x05 +# define VERTICAL_ALIGNMENT 0x0F + +# if 0 /* this would be nicer */ +# define TXT_RIGHT 'r' +# define TXT_CENTER 'c' +# define TXT_LEFT 'l' + +# define TXT_TOP 't' +# define TXT_VCENTER 'v' +# define TXT_BOTTOM 'b' +# define TXT_BASE '_' +# define TXT_VCAPS_CENTER 'C' +# endif + +#endif /* whole file */ +/*----------------------- end-of-file (C header) -----------------------*/ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..f2c5d79 --- /dev/null +++ b/src/main.c @@ -0,0 +1,479 @@ +/* main.c -- Eterm main() function + * -- 22 August 1998, mej + * + * This file is original work by Michael Jennings and + * Tuomo Venalainen . This file, and any other file + * bearing this same message or a similar one, is distributed under + * the GNU Public License (GPL) as outlined in the COPYING file. + * + * Copyright (C) 1997, Michael Jennings and Tuomo Venalainen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +static const char cvs_ident[] = "$Id$"; + +/* includes */ +#include "main.h" +#ifdef USE_ACTIVE_TAGS +# include "activetags.h" +# include "activeeterm.h" +#endif + +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "command.h" +#include "feature.h" +#include "../libmej/debug.h" /* from libmej */ +#include "debug.h" +#include "../libmej/mem.h" +#include "../libmej/strings.h" +/* For strsep(). -vendu */ +#if defined(linux) +# include +#endif +#include "string.h" +#include "graphics.h" +#include "scrollbar.h" +#include "menubar.h" +#include "screen.h" +#include "options.h" +#include "pixmap.h" +#ifdef USE_POSIX_THREADS +# include "threads.h" +#endif + +/* Global attributes */ +XWindowAttributes attr; +XSetWindowAttributes Attributes; +char *orig_argv0; + +#ifdef PIXMAP_SUPPORT +/* Set to one in case there is no WM, or a lousy one + that doesn't send the right events (*cough* + Window Maker *cough*) -- mej */ +short bg_needs_update = 1; + +#endif + +/* extern functions referenced */ +#ifdef DISPLAY_IS_IP +extern char *network_display(const char *display); + +#endif + +extern void get_initial_options(int, char **); +extern void menubar_read(const char *filename); + +#ifdef USE_POSIX_THREADS +static void **retval; +static int join_value; +static pthread_t main_loop_thr; +static pthread_attr_t main_loop_attr; + +# ifdef MUTEX_SYNCH +pthread_mutex_t mutex; + +# endif +#endif + +#ifdef PIXMAP_SUPPORT +extern void render_pixmap(Window win, imlib_t image, pixmap_t pmap, + int which, renderop_t renderop); + +# ifdef BACKING_STORE +extern const char *rs_saveUnder; + +# endif + +extern char *rs_noCursor; + +# ifdef USE_IMLIB +extern ImlibData *imlib_id; + +# endif +#endif + +/* extern variables referenced */ +extern int my_ruid, my_rgid, my_euid, my_egid; +extern unsigned int rs_shadePct; +extern unsigned long rs_tintMask; + +/* extern variables declared here */ +TermWin_t TermWin; +Display *Xdisplay; /* display */ + +char *rs_color[NRS_COLORS]; +Pixel PixColors[NRS_COLORS + NSHADOWCOLORS]; + +unsigned long Options = (Opt_scrollBar); +unsigned int debug_level = 0; /* Level of debugging information to display */ + +const char *display_name = NULL; +char *rs_name = NULL; /* client instance (resource name) */ + +#ifndef NO_BOLDFONT +const char *rs_boldFont = NULL; + +#endif +const char *rs_font[NFONTS]; + +#ifdef KANJI +const char *rs_kfont[NFONTS]; + +#endif + +#ifdef PRINTPIPE +char *rs_print_pipe = NULL; + +#endif + +char *rs_cutchars = NULL; + +/* local variables */ +Cursor TermWin_cursor; /* cursor for vt window */ +unsigned int colorfgbg; +menuBar_t menuBar; + +XSizeHints szHint = +{ + PMinSize | PResizeInc | PBaseSize | PWinGravity, + 0, 0, 80, 24, /* x, y, width, height */ + 1, 1, /* Min width, height */ + 0, 0, /* Max width, height - unused */ + 1, 1, /* increments: width, height */ + {1, 1}, /* increments: x, y */ + {0, 0}, /* Aspect ratio - unused */ + 0, 0, /* base size: width, height */ + NorthWestGravity /* gravity */ +}; + +char *def_colorName[] = +{ + "rgb:0/0/0", "rgb:ff/ff/ff", /* fg/bg */ + "rgb:0/0/0", /* 0: black (#000000) */ +#ifndef NO_BRIGHTCOLOR + /* low-intensity colors */ + "rgb:cc/00/00", /* 1: red */ + "rgb:00/cc/00", /* 2: green */ + "rgb:cc/cc/00", /* 3: yellow */ + "rgb:00/00/cc", /* 4: blue */ + "rgb:cc/00/cc", /* 5: magenta */ + "rgb:00/cc/cc", /* 6: cyan */ + "rgb:fa/eb/d7", /* 7: white */ + /* high-intensity colors */ + "rgb:33/33/33", /* 8: bright black */ +#endif /* NO_BRIGHTCOLOR */ + "rgb:ff/00/00", /* 1/9: bright red */ + "rgb:00/ff/00", /* 2/10: bright green */ + "rgb:ff/ff/00", /* 3/11: bright yellow */ + "rgb:00/00/ff", /* 4/12: bright blue */ + "rgb:ff/00/ff", /* 5/13: bright magenta */ + "rgb:00/ff/ff", /* 6/14: bright cyan */ + "rgb:ff/ff/ff", /* 7/15: bright white */ +#ifndef NO_CURSORCOLOR + NULL, NULL, /* cursorColor, cursorColor2 */ +#endif /* NO_CURSORCOLOR */ + NULL, NULL /* pointerColor, borderColor */ +#ifndef NO_BOLDUNDERLINE + ,NULL, NULL /* colorBD, colorUL */ +#endif /* NO_BOLDUNDERLINE */ + ,"rgb:ff/ff/ff" /* menuTextColor */ +#ifdef KEEP_SCROLLCOLOR + ,"rgb:b2/b2/b2" /* scrollColor: match Netscape color */ +# ifdef CHANGE_SCROLLCOLOR_ON_FOCUS + ,NULL /* unfocusedscrollColor: somebody chose black? */ +# endif +#endif +}; + +#ifdef KANJI +/* Kanji font names, roman fonts sized to match */ +const char *def_kfontName[] = +{ + KFONT0, KFONT1, KFONT2, KFONT3, KFONT4 +}; + +#endif /* KANJI */ +const char *def_fontName[] = +{ + FONT0, FONT1, FONT2, FONT3, FONT4 +}; + +/* extern functions referenced */ +#ifdef PIXMAP_SUPPORT +/* the originally loaded pixmap and its scaling */ +extern pixmap_t bgPixmap; +extern void set_bgPixmap(const char * /* file */ ); + +# ifdef USE_IMLIB +extern imlib_t imlib_bg; + +# endif +# ifdef PIXMAP_SCROLLBAR +extern pixmap_t sbPixmap; +extern pixmap_t upPixmap, up_clkPixmap; +extern pixmap_t dnPixmap, dn_clkPixmap; +extern pixmap_t saPixmap, sa_clkPixmap; + +# ifdef USE_IMLIB +extern imlib_t imlib_sb, imlib_sa, imlib_saclk; + +# endif +# endif +# ifdef PIXMAP_MENUBAR +extern pixmap_t mbPixmap, mb_selPixmap; + +# ifdef USE_IMLIB +extern imlib_t imlib_mb, imlib_ms; + +# endif +# endif + +extern int scale_pixmap(const char *geom, pixmap_t * pmap); + +#endif /* PIXMAP_SUPPORT */ + +/* have we changed the font? Needed to avoid race conditions + * while window resizing */ +int font_change_count = 0; + +static void resize(void); + +extern XErrorHandler xerror_handler(Display *, XErrorEvent *); +extern void Create_Windows(int, char **); + +/* main() */ +int +main(int argc, char *argv[]) +{ + + int i, count; + char *val; + static char windowid_string[20], *display_string, *term_string; /* "WINDOWID=\0" = 10 chars, UINT_MAX = 10 chars */ + + orig_argv0 = argv[0]; + +#ifdef USE_POSIX_THREADS +# ifdef MUTEX_SYNCH + pthread_atfork((void *) &prepare, (void *) &parent, (void *) &child); +# endif +#endif + + /* Security enhancements -- mej */ + my_ruid = getuid(); + my_euid = geteuid(); + my_rgid = getgid(); + my_egid = getegid(); + privileges(REVERT); + + TermWin.wm_parent = None; + init_defaults(); + + /* Open display, get options/resources and create the window */ + if ((display_name = getenv("DISPLAY")) == NULL) + display_name = ":0"; + + /* This MUST be called before any other Xlib functions */ + +#ifdef USE_POSIX_THREADS + if (XInitThreads()) { + D_THREADS(("XInitThreads() succesful\n")); + } else { + D_THREADS(("XInitThreads() failed, I'm outta here\n")); + } +#endif + +#ifdef USE_THEMES + get_initial_options(argc, argv); +#endif + read_config(); +#ifdef PIXMAP_SUPPORT + if (rs_path) { + rs_path = REALLOC(rs_path, strlen(rs_path) + strlen(initial_dir) + 2); + strcat(rs_path, ":"); + strcat(rs_path, initial_dir); + } +#endif + get_options(argc, argv); +#ifdef USE_ACTIVE_TAGS + tag_init(); +#endif + D_UTMP(("Saved real uid/gid = [ %d, %d ] effective uid/gid = [ %d, %d ]\n", my_ruid, my_rgid, my_euid, my_egid)); + D_UTMP(("Now running with real uid/gid = [ %d, %d ] effective uid/gid = [ %d, %d ]\n", getuid(), getgid(), geteuid(), + getegid())); + +#ifdef NEED_LINUX_HACK + privileges(INVOKE); /* xdm in new Linux versions requires ruid != root to open the display -- mej */ +#endif + Xdisplay = XOpenDisplay(display_name); +#ifdef NEED_LINUX_HACK + privileges(REVERT); +#endif + + if (!Xdisplay) { + print_error("can't open display %s", display_name); + exit(EXIT_FAILURE); + } + +#if DEBUG >= DEBUG_X + if (debug_level >= DEBUG_X) { + XSetErrorHandler((XErrorHandler) abort); + } else { + XSetErrorHandler((XErrorHandler) xerror_handler); + } +#else + XSetErrorHandler((XErrorHandler) xerror_handler); +#endif + + /* Since we always use Imlib now, let's initialize it here. */ + imlib_id = Imlib_init(Xdisplay); + + post_parse(); + +#ifdef PREFER_24BIT + Xdepth = DefaultDepth(Xdisplay, Xscreen); + Xcmap = DefaultColormap(Xdisplay, Xscreen); + Xvisual = DefaultVisual(Xdisplay, Xscreen); + + /* + * If depth is not 24, look for a 24bit visual. + */ + if (Xdepth != 24) { + XVisualInfo vinfo; + + if (XMatchVisualInfo(Xdisplay, Xscreen, 24, TrueColor, &vinfo)) { + Xdepth = 24; + Xvisual = vinfo.visual; + Xcmap = XCreateColormap(Xdisplay, RootWindow(Xdisplay, Xscreen), + Xvisual, AllocNone); + } + } +#endif + + Create_Windows(argc, argv); + scr_reset(); /* initialize screen */ + Gr_reset(); /* reset graphics */ + + /* add scrollBar, do it directly to avoid resize() */ + scrollbar_mapping(Options & Opt_scrollBar); + /* we can now add menuBar */ + if (delay_menu_drawing) { + delay_menu_drawing = 0; + menubar_mapping(1); + } else if (rs_menubar == *false_vals) { + menubar_mapping(0); + } +#if DEBUG >= DEBUG_X + if (debug_level >= DEBUG_X) { + XSynchronize(Xdisplay, True); + } +#endif + +#ifdef DISPLAY_IS_IP + /* Fixup display_name for export over pty to any interested terminal + * clients via "ESC[7n" (e.g. shells). Note we use the pure IP number + * (for the first non-loopback interface) that we get from + * network_display(). This is more "name-resolution-portable", if you + * will, and probably allows for faster x-client startup if your name + * server is beyond a slow link or overloaded at client startup. Of + * course that only helps the shell's child processes, not us. + * + * Giving out the display_name also affords a potential security hole + */ + + val = display_name = network_display(display_name); + if (val == NULL) +#endif /* DISPLAY_IS_IP */ + val = XDisplayString(Xdisplay); + if (display_name == NULL) + display_name = val; /* use broken `:0' value */ + + i = strlen(val); + display_string = MALLOC((i + 9)); + + sprintf(display_string, "DISPLAY=%s", val); + sprintf(windowid_string, "WINDOWID=%u", (unsigned int) TermWin.parent); + + /* add entries to the environment: + * @ DISPLAY: in case we started with -display + * @ WINDOWID: X window id number of the window + * @ COLORTERM: terminal sub-name and also indicates its color + * @ TERM: terminal name + */ + putenv(display_string); + putenv(windowid_string); + if (Xdepth <= 2) { + putenv("COLORTERM=" COLORTERMENV "-mono"); + putenv("TERM=" TERMENV); + } else { + if (rs_term_name != NULL) { + i = strlen(rs_term_name); + term_string = MALLOC((i + 6) * sizeof(char)); + + sprintf(term_string, "TERM=%s", rs_term_name); + putenv(term_string); + } else { +#ifdef DEFINE_XTERM_COLOR + if (Xdepth <= 2) + putenv("TERM=" TERMENV); + else + putenv("TERM=" TERMENV "-color"); +#else + putenv("TERM=" TERMENV); +#endif + } +#ifdef PIXMAP_SUPPORT + putenv("COLORTERM=" COLORTERMENV "-pixmap"); +#else + putenv("COLORTERM=" COLORTERMENV); +#endif + } + + D_CMD(("init_command()\n")); + init_command(rs_execArgs); +#ifndef USE_POSIX_THREADS + if (Options & Opt_borderless) { + resize_window(); + } +#endif + +#ifdef USE_POSIX_THREADS + D_THREADS(("main_thread:")); + pthread_attr_init(&main_loop_attr); + pthread_create(&main_loop_thr, &main_loop_attr, + (void *) &main_thread, NULL); + D_THREADS(("done? :)\n")); + while (1); + /* main_loop(); */ +#else + main_loop(); /* main processing loop */ +#endif + + return (EXIT_SUCCESS); +} +/* EOF */ diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..e3b2fed --- /dev/null +++ b/src/main.h @@ -0,0 +1,304 @@ +/*--------------------------------*-C-*---------------------------------* + * File: main.h + */ +/* notes: */ +/*----------------------------------------------------------------------* + * Copyright 1992 John Bovey, University of Kent at Canterbury. + * + * You can do what you like with this source code as long as you don't try + * to make money out of it and you include an unaltered copy of this + * message (including the copyright). + * + * This module has been heavily modified by R. Nation + * + * No additional restrictions are applied + * + * Additional modifications by mj olesen + * No additional restrictions are applied. + * + * As usual, the author accepts no responsibility for anything, nor does + * he guarantee anything whatsoever. + *----------------------------------------------------------------------*/ + +#ifndef _MAIN_H +# define _MAIN_H +# include "config.h" +# include "feature.h" +# include +# include +# include +# include + +/* STDC_HEADERS + * don't check for these using configure, since we need them regardless. + * if you don't have them -- figure a workaround. + * + * Sun is often reported as not being STDC_HEADERS, but it's not true + * for our purposes and only generates spurious bug reports. + */ +# include +# include +# include + +# ifndef EXIT_SUCCESS /* missing from */ +# define EXIT_SUCCESS 0 /* exit function success */ +# define EXIT_FAILURE 1 /* exit function failure */ +# endif + +# include /* Xlib, Xutil, Xresource, Xfuncproto */ +# include "misc.h" + +typedef struct { + int internalBorder; /* Internal border size */ + short width, height; /* window size [pixels] */ + short fwidth, fheight; /* font width and height [pixels] */ + short fprop; /* font is proportional */ + short ncol, nrow; /* window size [characters] */ + short focus; /* window has focus */ + short saveLines; /* number of lines that fit in scrollback */ + short nscrolled; /* number of line actually scrolled */ + short view_start; /* scrollback view starts here */ + Window parent, vt; /* parent (main) and vt100 window */ + Window wm_parent, /* The parent assigned by the WM */ + wm_grandparent; /* The grandparent assigned by the WM */ + GC gc; /* GC for drawing text */ + XFontStruct * font; /* main font structure */ +# ifndef NO_BOLDFONT + XFontStruct * boldFont; /* bold font */ +# endif +# ifdef KANJI + XFontStruct * kanji; /* Kanji font structure */ +# endif +# ifdef PIXMAP_SUPPORT + Pixmap pixmap; +# ifdef PIXMAP_BUFFERING + Pixmap buf_pixmap; +# endif +# endif +} TermWin_t; + +extern TermWin_t TermWin; +extern Window root; +extern Display * Xdisplay; +extern char *def_colorName[]; +extern const char *def_fontName[]; +# ifdef KANJI +extern const char *def_kfontName[]; +# endif + +# define MAX_COLS 200 +# define MAX_ROWS 128 + +# ifndef min +# define min(a,b) (((a) < (b)) ? (a) : (b)) +# define max(a,b) (((a) > (b)) ? (a) : (b)) +# endif +# ifndef MIN +# define MIN(a,b) (((a) < (b)) ? (a) : (b)) +# endif +# ifndef MAX +# define MAX(a,b) (((a) > (b)) ? (a) : (b)) +# endif + +# define MAX_IT(current, other) if ((other) > (current)) (current) = (other) +# define MIN_IT(current, other) if ((other) < (current)) (current) = (other) +# define SWAP_IT(one, two, tmp) \ +do { \ +(tmp) = (one); (one) = (two); (two) = (tmp); \ +} while (0) + +/* width of scrollBar, menuBar shadow ... don't change! */ +# define SHADOW 2 + +/* convert pixel dimensions to row/column values */ +# define Pixel2Width(x) ((x) / TermWin.fwidth) +# define Pixel2Height(y) ((y) / TermWin.fheight) +# define Pixel2Col(x) Pixel2Width((x) - TermWin.internalBorder) +# define Pixel2Row(y) Pixel2Height((y) - TermWin.internalBorder) + +# define Width2Pixel(n) ((n) * TermWin.fwidth) +# define Height2Pixel(n) ((n) * TermWin.fheight) +# define Col2Pixel(col) (Width2Pixel(col) + TermWin.internalBorder) +# define Row2Pixel(row) (Height2Pixel(row) + TermWin.internalBorder) + +# define TermWin_TotalWidth() (TermWin.width + 2 * TermWin.internalBorder) +# define TermWin_TotalHeight() (TermWin.height + 2 * TermWin.internalBorder) + +# define Xscreen DefaultScreen(Xdisplay) +# define Xcmap DefaultColormap(Xdisplay,Xscreen) +# define Xdepth DefaultDepth(Xdisplay,Xscreen) +# define Xroot DefaultRootWindow(Xdisplay) +# ifdef DEBUG_DEPTH +# undef Xdepth +# define Xdepth DEBUG_DEPTH +# endif + +# define Opt_console (1LU << 0) +# define Opt_loginShell (1LU << 1) +# define Opt_iconic (1LU << 2) +# define Opt_visualBell (1LU << 3) +# define Opt_mapAlert (1LU << 4) +# define Opt_reverseVideo (1LU << 5) +# define Opt_utmpLogging (1LU << 6) +# define Opt_scrollBar (1LU << 7) +# define Opt_meta8 (1LU << 8) +# define Opt_pixmapScale (1LU << 9) +# define Opt_exec (1LU << 10) +# define Opt_homeOnEcho (1LU << 11) +# define Opt_homeOnRefresh (1LU << 12) +# define Opt_scrollBar_floating (1LU << 13) +# define Opt_scrollBar_right (1LU << 14) +# define Opt_borderless (1LU << 15) +# define Opt_pixmapTrans (1LU << 16) +# define Opt_saveUnder (1LU << 17) +# define Opt_noCursor (1LU << 18) +# define Opt_pause (1LU << 19) +# define Opt_watchDesktop (1LU << 20) +# define Opt_homeOnInput (1LU << 21) +# define Opt_menubar_move (1LU << 22) +# define Opt_xterm_select (1LU << 23) +# define Opt_select_whole_line (1LU << 24) +# define Opt_viewport_mode (1LU << 25) +# define Opt_scrollbar_popup (1LU << 26) +# define Opt_select_trailing_spaces (1LU << 24) + +/* place holder used for parsing command-line options */ +# define Opt_Boolean (1LU << 31) +extern unsigned long Options; + +extern const char *display_name; +extern char *rs_name; /* client instance (resource name) */ + +/* + * XTerm escape sequences: ESC ] Ps;Pt BEL + */ +# define XTerm_name 0 +# define XTerm_iconName 1 +# define XTerm_title 2 +# define XTerm_logfile 46 /* not implemented */ +# define XTerm_font 50 + +/* + * rxvt/Eterm extensions of XTerm escape sequences: ESC ] Ps;Pt BEL + */ +# define XTerm_Takeover 5 /* Steal keyboard focus and raise window */ +# define XTerm_EtermSeq 6 /* Eterm proprietary escape sequences */ +# define XTerm_Menu 10 /* set menu item */ +# define XTerm_Pixmap 20 /* new bg pixmap */ +# define XTerm_restoreFG 39 /* change default fg color */ +# define XTerm_restoreBG 49 /* change default bg color */ + +/*----------------------------------------------------------------------*/ + +# define restoreFG 39 /* restore default fg color */ +# define restoreBG 49 /* restore default bg color */ + +enum colour_list { + fgColor, + bgColor, + minColor, /* 2 */ + BlackColor = minColor, + Red3Color, + Green3Color, + Yellow3Color, + Blue3Color, + Magenta3Color, + Cyan3Color, + maxColor, /* minColor + 7 */ +# ifndef NO_BRIGHTCOLOR + AntiqueWhiteColor = maxColor, + minBright, /* maxColor + 1 */ + Grey25Color = minBright, + RedColor, + GreenColor, + YellowColor, + BlueColor, + MagentaColor, + CyanColor, + maxBright, /* minBright + 7 */ + WhiteColor = maxBright, +# else + WhiteColor = maxColor, +# endif +# ifndef NO_CURSORCOLOR + cursorColor, + cursorColor2, +# endif + pointerColor, + borderColor, +# ifndef NO_BOLDUNDERLINE + colorBD, + colorUL, +# endif + menuTextColor, +# if defined(KEEP_SCROLLCOLOR) + scrollColor, +# if defined(CHANGE_SCROLLCOLOR_ON_FOCUS) + unfocusedScrollColor, +# endif +# endif + NRS_COLORS, /* */ +# ifdef KEEP_SCROLLCOLOR + topShadowColor = NRS_COLORS, + bottomShadowColor, +# ifdef CHANGE_SCROLLCOLOR_ON_FOCUS + unfocusedTopShadowColor, + unfocusedBottomShadowColor, +# endif + TOTAL_COLORS /* */ +# else + TOTAL_COLORS = NRS_COLORS /* */ +# endif +}; + +# define NSHADOWCOLORS (TOTAL_COLORS - NRS_COLORS) + +# define DEFAULT_RSTYLE (RS_None | (fgColor<<8) | (bgColor<<16)) + +extern char * rs_color [NRS_COLORS]; +extern Pixel PixColors [NRS_COLORS + NSHADOWCOLORS]; + +# define NFONTS 5 +extern const char * rs_font [NFONTS]; +# ifdef KANJI +extern const char * rs_kfont [NFONTS]; +# endif +# ifndef NO_BOLDFONT +extern const char * rs_boldFont; +# endif + +# ifdef PRINTPIPE +extern char *rs_print_pipe; +# endif + +# ifdef CUTCHAR_OPTION +extern char * rs_cutchars; +# endif + +/* prototypes */ +_XFUNCPROTOBEGIN + +#ifndef GCC +extern void map_menuBar(int); +extern void map_scrollBar(int); +#else +extern inline void map_menuBar(int); +extern inline void map_scrollBar(int); +#endif +extern void xterm_seq(int, const char *); +extern void change_font(int, const char *); +extern void set_width(unsigned short); +extern void resize_window(void); + +/* special (internal) prefix for font commands */ +# define FONT_CMD '#' +# define FONT_DN "#-" +# define FONT_UP "#+" + +# ifdef USE_IMLIB +Pixmap ReadFileToPixmapViaImlib(Display *, char *, int *, int *); +# endif + +_XFUNCPROTOEND + +#endif /* whole file */ diff --git a/src/menubar.c b/src/menubar.c new file mode 100644 index 0000000..fef4447 --- /dev/null +++ b/src/menubar.c @@ -0,0 +1,2567 @@ +/*--------------------------------*-C-*---------------------------------* + * File: menubar.c + * + * Copyright 1996,97 + * mj olesen Queen's Univ at Kingston + * + * You can do what you like with this source code provided you don't make + * money from it and you include an unaltered copy of this message + * (including the copyright). As usual, the author accepts no + * responsibility for anything, nor does he guarantee anything whatsoever. + * + *----------------------------------------------------------------------*/ + +static const char cvs_ident[] = "$Id$"; + +#include "main.h" +#include + +#ifdef HAVE_SYS_SELECT_H +# include +#endif +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#include "menubar.h" +#include "command.h" +#include "debug.h" +#include "../libmej/debug.h" +#include "mem.h" +#include "misc.h" +#ifdef PIXMAP_MENUBAR +# include "pixmap.h" +# include "options.h" +#endif + +#ifdef KANJI +# ifdef NO_XLOCALE +# include +# else +# include +# endif +static XFontSet fontset = 0; + +#endif + +int delay_menu_drawing; + +extern XSetWindowAttributes Attributes; + +#ifdef PIXMAP_MENUBAR +pixmap_t mbPixmap, mb_selPixmap; + +# ifdef USE_IMLIB +imlib_t imlib_mb, imlib_ms; + +# endif +#endif + +#if (MENUBAR_MAX) +menuitem_t *menuitem_find(menu_t * menu, char *name); +void menuitem_free(menu_t * menu, menuitem_t * item); +int action_type(action_t * action, unsigned char *str); +int action_dispatch(action_t * action); +int menuarrow_find(char name); +void menuarrow_free(char name); +void menuarrow_add(char *string); +menuitem_t *menuitem_add(menu_t * menu, char *name, char *name2, char *action); +char *menu_find_base(menu_t ** menu, char *path); +menu_t *menu_delete(menu_t * menu); +menu_t *menu_add(menu_t * parent, char *path); +void drawbox_menubar(int x, int len, int state); +void drawtriangle(int x, int y, int state); +void drawbox_menuitem(int y, int state); +void print_menu_ancestors(menu_t * menu); +void print_menu_descendants(menu_t * menu); +void menu_show(void); +void menu_display(void (*update) (void)); +void menu_hide_all(void); +void menu_hide(void); +void menu_clear(menu_t * menu); +void menubar_clear(void); +bar_t *menubar_find(const char *name); +int menubar_push(const char *name); +void menubar_remove(const char *name); +void action_decode(FILE * fp, action_t * act); +void menu_dump(FILE * fp, menu_t * menu); +void menubar_dump(FILE * fp); +void menubar_read(const char *filename); +void menubar_dispatch(char *str); +void draw_Arrows(int name, int state); +void menubar_expose(void); +int menubar_mapping(int map); +int menu_select(XButtonEvent * ev); +void menubar_select(XButtonEvent * ev); +void menubar_control(XButtonEvent * ev); + +#define HSPACE 2 +#define MENU_MARGIN 2 +#define menu_height() (TermWin.fheight + 2 * MENU_MARGIN) + +#define MENU_DELAY_USEC 250000 /* 1/4 sec */ + +#define SEPARATOR_HALFHEIGHT (SHADOW + 1) +#define SEPARATOR_HEIGHT (2 * SEPARATOR_HALFHEIGHT) +#define isSeparator(name) ((name)[0] == '\0') + +#define SEPARATOR_NAME "-" +#define MENUITEM_BEG '{' +#define MENUITEM_END '}' +#define COMMENT_CHAR '#' + +#define DOT "." +#define DOTS ".." + +#define Menu_PixelWidth(menu) (2 * SHADOW + Width2Pixel ((menu)->width + 3 * HSPACE)) + +static GC topShadowGC, botShadowGC, neutralGC, menubarGC; + +struct menu_t; + +static int menu_readonly = 1; /* okay to alter menu? */ +static int Arrows_x = 0; + +static const struct { + char name; /* (l)eft, (u)p, (d)own, (r)ight */ + unsigned char *str; /* str[0] = strlen (str+1) */ +} Arrows[NARROWS] = { + + { + 'l', "\003\033[D" + }, + { + 'u', "\003\033[A" + }, + { + 'd', "\003\033[B" + }, + { + 'r', "\003\033[C" + } +}; + +#if (MENUBAR_MAX > 1) +static int Nbars = 0; +static bar_t *CurrentBar = NULL; + +#else /* (MENUBAR_MAX > 1) */ +static bar_t BarList; +static bar_t *CurrentBar = &BarList; + +#endif /* (MENUBAR_MAX > 1) */ + +#ifdef PIXMAP_MENUBAR +menu_t *ActiveMenu = NULL; /* currently active menu */ + +#else +static menu_t *ActiveMenu = NULL; /* currently active menu */ + +#endif + +#ifndef HAVE_MEMMOVE +/* Replacement for memmove() if it's not there -- mej */ +inline void * +memmove(void *s1, const void *s2, size_t size) +{ + + register char *tmp; + register char *dest = (char *) s1; + register const char *source = (const char *) s2; + + if ((tmp = (char *) malloc(size)) == NULL) { + fprintf(stderr, "memmove(): allocation failure for %lu bytes\n", + size); + exit(EXIT_FAILURE); + } + memcpy(tmp, source, size); + memcpy(dest, tmp, size); + free(tmp); + return (dest); +} +#endif /* HAVE_MEMMOVE */ + +/* + * find an item called NAME in MENU + */ +menuitem_t * +menuitem_find(menu_t * menu, char *name) +{ + + menuitem_t *item; + + assert(name != NULL); + assert(menu != NULL); + + D_MENUBAR(("menuitem_find(\"%s\", \"%s\")\n", menu->name, name)); +/* find the last item in the menu, this is good for separators */ + for (item = menu->tail; item != NULL; item = item->prev) { + if (item->entry.type == MenuSubMenu) { + if (!strcmp(name, (item->entry.submenu.menu)->name)) + break; + } else if ((isSeparator(name) && isSeparator(item->name)) || + !strcmp(name, item->name)) + break; + } + return item; +} + +/* + * unlink ITEM from its MENU and free its memory + */ +void +menuitem_free(menu_t * menu, menuitem_t * item) +{ + +/* disconnect */ + menuitem_t *prev, *next; + + assert(menu != NULL); + assert(item != NULL); + + D_MENUBAR(("menuitem_free(\"%s\", \"%s\")\n", menu->name, item->name)); + prev = item->prev; + next = item->next; + if (prev != NULL) + prev->next = next; + if (next != NULL) + next->prev = prev; + +/* new head, tail */ + if (menu->tail == item) + menu->tail = prev; + if (menu->head == item) + menu->head = next; + + switch (item->entry.type) { + case MenuAction: + case MenuTerminalAction: + FREE(item->entry.action.str); + break; + case MenuSubMenu: + menu_delete(item->entry.submenu.menu); + break; + } + if (item->name != NULL) + FREE(item->name); + if (item->name2 != NULL) + FREE(item->name2); + FREE(item); +} + +/* + * sort command vs. terminal actions and + * remove the first character of STR if it's '\0' + */ +int +action_type(action_t * action, unsigned char *str) +{ + + unsigned int len; + + len = parse_escaped_string(str); + D_MENUBAR(("New string is %u bytes\n", len)); + + ASSERT(action != NULL); + + if (!len) + return -1; + +/* sort command vs. terminal actions */ + action->type = MenuAction; + if (str[0] == '\0') { + /* the functional equivalent: memmove (str, str+1, len); */ + unsigned char *dst = (str); + unsigned char *src = (str + 1); + unsigned char *end = (str + len); + + while (src <= end) + *dst++ = *src++; + + len--; /* decrement length */ + if (str[0] != '\0') + action->type = MenuTerminalAction; + } + action->str = str; + action->len = len; + + return 0; +} + +int +action_dispatch(action_t * action) +{ + + assert(action != NULL); + D_MENUBAR(("action_dispatch(\"%s\")\n", action->str)); + + switch (action->type) { + case MenuTerminalAction: + cmd_write(action->str, action->len); + break; + + case MenuAction: + tt_write(action->str, action->len); + break; + + default: + return -1; + break; + } + return 0; +} + +/* return the arrow index corresponding to NAME */ +int +menuarrow_find(char name) +{ + + int i; + + D_MENUARROWS(("menuarrow_find(\'%c\')\n", name)); + + for (i = 0; i < NARROWS; i++) { + if (name == Arrows[i].name) + return (i); + } + return (-1); +} + +/* free the memory associated with arrow NAME of the current menubar */ +void +menuarrow_free(char name) +{ + + int i; + + D_MENUARROWS(("menuarrow_free(\'%c\')\n", name)); + + if (name) { + i = menuarrow_find(name); + if (i >= 0) { + action_t *act = &(CurrentBar->arrows[i]); + + switch (act->type) { + case MenuAction: + case MenuTerminalAction: + FREE(act->str); + act->str = NULL; + act->len = 0; + break; + } + act->type = MenuLabel; + } + } else { + for (i = 0; i < NARROWS; i++) + menuarrow_free(Arrows[i].name); + } +} + +void +menuarrow_add(char *string) +{ + + int i; + unsigned xtra_len; + char *p; + struct { + char *str; + int len; + } beg = { + NULL, 0 + }, end = { + NULL, 0 + }, *cur, parse[NARROWS]; + + D_MENUARROWS(("menuarrow_add(\"%s\")\n", string)); + + memset(parse, 0, sizeof(parse)); + + for (p = string; p != NULL && *p; string = p) { + p = (string + 3); + D_MENUARROWS(("parsing at %s\n", string)); + switch (string[1]) { + case 'b': + cur = &beg; + break; + case 'e': + cur = &end; + break; + default: + i = menuarrow_find(string[1]); + if (i >= 0) + cur = &(parse[i]); + else + continue; /* not found */ + break; + } + + string = p; + cur->str = string; + cur->len = 0; + + if (cur == &end) { + p = strchr(string, '\0'); + } else { + char *next = string; + + while (1) { + p = strchr(next, '<'); + if (p != NULL) { + if (p[1] && p[2] == '>') + break; + /* parsed */ + } else { + if (beg.str == NULL) /* no end needed */ + p = strchr(next, '\0'); + break; + } + next = (p + 1); + } + } + + if (p == NULL) + return; + cur->len = (p - string); + } + +#if DEBUG >= DEBUG_MENUARROWS + if (debug_level >= DEBUG_MENUARROWS) { + cur = &beg; + DPRINTF1(("(len %d) = %.*s\n", cur->len, cur->len, (cur->str ? cur->str : ""))); + for (i = 0; i < NARROWS; i++) { + cur = &(parse[i]); + DPRINTF1(("<%c>(len %d) = %.*s\n", Arrows[i].name, cur->len, cur->len, (cur->str ? cur->str : ""))); + } + cur = &end; + DPRINTF1(("(len %d) = %.*s\n", cur->len, cur->len, (cur->str ? cur->str : ""))); + } +#endif + + xtra_len = (beg.len + end.len); + for (i = 0; i < NARROWS; i++) { + if (xtra_len || parse[i].len) + menuarrow_free(Arrows[i].name); + } + + for (i = 0; i < NARROWS; i++) { + + unsigned char *str; + unsigned int len; + + if (!parse[i].len) + continue; + + str = MALLOC(parse[i].len + xtra_len + 1); + if (str == NULL) + continue; + + len = 0; + if (beg.len) { + strncpy(str + len, beg.str, beg.len); + len += beg.len; + } + strncpy(str + len, parse[i].str, parse[i].len); + len += parse[i].len; + + if (end.len) { + strncpy(str + len, end.str, end.len); + len += end.len; + } + str[len] = '\0'; + + D_MENUARROWS(("<%c>(len %d) = %s\n", Arrows[i].name, len, str)); + if (action_type(&(CurrentBar->arrows[i]), str) < 0) + FREE(str); + } +} + +menuitem_t * +menuitem_add(menu_t * menu, char *name, char *name2, char *action) +{ + + menuitem_t *item = NULL; + unsigned int len; + unsigned char found = 0; + + assert(name != NULL); + assert(action != NULL); + + if (menu == NULL) + return NULL; + + D_MENUBAR(("menuitem_add(\"%s\", \"%s\", \"%s\", \"%s\")\n", menu->name, name, (name2 ? name2 : ""), action)); + + if (isSeparator(name)) { + /* add separator, no action */ + name = ""; + action = ""; + } else { + /* + * add/replace existing menu item + */ + item = menuitem_find(menu, name); + if (item != NULL) { + if (item->name2 != NULL && name2 != NULL) { + FREE(item->name2); + item->len2 = 0; + item->name2 = NULL; + } + switch (item->entry.type) { + case MenuAction: + case MenuTerminalAction: + FREE(item->entry.action.str); + item->entry.action.str = NULL; + break; + } + found = 1; + } + } + + if (!found) { + + /* allocate a new itemect */ + if ((item = (menuitem_t *) MALLOC(sizeof(menuitem_t))) == NULL) + return NULL; + + item->len2 = 0; + item->name2 = NULL; + + len = strlen(name); + item->name = MALLOC(len + 1); + if (item->name != NULL) { + strcpy(item->name, name); + if (name[0] == '.' && name[1] != '.') + len = 0; /* hidden menu name */ + } else { + FREE(item); + return NULL; + } + item->len = len; + + /* add to tail of list */ + item->prev = menu->tail; + item->next = NULL; + + if (menu->tail != NULL) + (menu->tail)->next = item; + menu->tail = item; + /* fix head */ + if (menu->head == NULL) + menu->head = item; + } + /* + * add action + */ + if (name2 != NULL && item->name2 == NULL) { + len = strlen(name2); + if (len == 0 || (item->name2 = MALLOC(len + 1)) == NULL) { + len = 0; + item->name2 = NULL; + } else { + strcpy(item->name2, name2); + } + item->len2 = len; + } + item->entry.type = MenuLabel; + len = strlen(action); + + if (len == 0 && item->name2 != NULL) { + action = item->name2; + len = item->len2; + } + if (len) { + unsigned char *str = MALLOC(len + 1); + + if (str == NULL) { + menuitem_free(menu, item); + return NULL; + } + strcpy(str, action); + + if (action_type(&(item->entry.action), str) < 0) + FREE(str); + } + /* new item and a possible increase in width */ + if (menu->width < (item->len + item->len2)) + menu->width = (item->len + item->len2); + + return item; +} + +/* + * search for the base starting menu for NAME. + * return a pointer to the portion of NAME that remains + */ +char * +menu_find_base(menu_t ** menu, char *path) +{ + + menu_t *m = NULL; + menuitem_t *item; + + assert(menu != NULL); + assert(CurrentBar != NULL); + + D_MENUBAR(("menu_find_base(0x%08x, \"%s\")\n", menu, path)); + + if (path[0] == '\0') + return path; + + if (strchr(path, '/') != NULL) { + register char *p = path; + + while ((p = strchr(p, '/')) != NULL) { + p++; + if (*p == '/') + path = p; + } + if (path[0] == '/') { + path++; + *menu = NULL; + } + while ((p = strchr(path, '/')) != NULL) { + p[0] = '\0'; + if (path[0] == '\0') + return NULL; + if (!strcmp(path, DOT)) { + /* nothing to do */ + } else if (!strcmp(path, DOTS)) { + if (*menu != NULL) + *menu = (*menu)->parent; + } else { + path = menu_find_base(menu, path); + if (path[0] != '\0') { /* not found */ + p[0] = '/'; /* fix-up name again */ + return path; + } + } + + path = (p + 1); + } + } + if (!strcmp(path, DOTS)) { + path += strlen(DOTS); + if (*menu != NULL) + *menu = (*menu)->parent; + return path; + } + /* find this menu */ + if (*menu == NULL) { + for (m = CurrentBar->tail; m != NULL; m = m->prev) { + if (!strcmp(path, m->name)) + break; + } + } else { + /* find this menu */ + for (item = (*menu)->tail; item != NULL; item = item->prev) { + if (item->entry.type == MenuSubMenu && + !strcmp(path, (item->entry.submenu.menu)->name)) { + m = (item->entry.submenu.menu); + break; + } + } + } + if (m != NULL) { + *menu = m; + path += strlen(path); + } + return path; +} + +/* + * delete this entire menu + */ +menu_t * +menu_delete(menu_t * menu) +{ + + menu_t *parent = NULL, *prev, *next; + menuitem_t *item; + + assert(CurrentBar != NULL); + if (menu == NULL) + return NULL; + + D_MENUBAR(("menu_delete(\"%s\")\n", menu->name)); + +/* delete the entire menu */ + parent = menu->parent; + +/* unlink MENU */ + prev = menu->prev; + next = menu->next; + if (prev != NULL) + prev->next = next; + if (next != NULL) + next->prev = prev; + +/* fix the index */ + if (parent == NULL) { + const int len = (menu->len + HSPACE); + + if (CurrentBar->tail == menu) + CurrentBar->tail = prev; + if (CurrentBar->head == menu) + CurrentBar->head = next; + + for (next = menu->next; next != NULL; next = next->next) + next->x -= len; + } else { + for (item = parent->tail; item != NULL; item = item->prev) { + if (item->entry.type == MenuSubMenu && + item->entry.submenu.menu == menu) { + item->entry.submenu.menu = NULL; + menuitem_free(menu->parent, item); + break; + } + } + } + + item = menu->tail; + while (item != NULL) { + menuitem_t *p = item->prev; + + menuitem_free(menu, item); + item = p; + } + + if (menu->name != NULL) + FREE(menu->name); + FREE(menu); + + return parent; +} + +menu_t * +menu_add(menu_t * parent, char *path) +{ + + menu_t *menu; + + assert(CurrentBar != NULL); + + D_MENUBAR(("menu_add(\"%s\", \"%s\")\n", (parent ? parent->name : ""), path)); + + if (strchr(path, '/') != NULL) { + register char *p; + + if (path[0] == '/') { + /* shouldn't happen */ + path++; + parent = NULL; + } + while ((p = strchr(path, '/')) != NULL) { + p[0] = '\0'; + if (path[0] == '\0') + return NULL; + + parent = menu_add(parent, path); + path = (p + 1); + } + } + if (!strcmp(path, DOTS)) + return (parent != NULL ? parent->parent : parent); + + if (!strcmp(path, DOT) || path[0] == '\0') + return parent; + +/* allocate a new menu */ + if ((menu = (menu_t *) MALLOC(sizeof(menu_t))) == NULL) + return parent; + + menu->width = 0; + menu->parent = parent; + menu->len = strlen(path); + menu->name = MALLOC((menu->len + 1)); + if (menu->name == NULL) { + FREE(menu); + return parent; + } + strcpy(menu->name, path); + +/* initialize head/tail */ + menu->head = menu->tail = NULL; + menu->prev = menu->next = NULL; + + menu->win = None; + menu->x = menu->y = menu->w = menu->h = 0; + menu->item = NULL; + +/* add to tail of list */ + if (parent == NULL) { + menu->prev = CurrentBar->tail; + if (CurrentBar->tail != NULL) + CurrentBar->tail->next = menu; + CurrentBar->tail = menu; + if (CurrentBar->head == NULL) + CurrentBar->head = menu; /* fix head */ + if (menu->prev) + menu->x = (menu->prev->x + menu->prev->len + HSPACE); + } else { + menuitem_t *item; + + item = menuitem_add(parent, path, "", ""); + if (item == NULL) { + FREE(menu); + return parent; + } + assert(item->entry.type == MenuLabel); + item->entry.type = MenuSubMenu; + item->entry.submenu.menu = menu; + } + + return menu; +} + +void +drawbox_menubar(int x, int len, int state) +{ + + GC top = None, bot = None; + + x = Width2Pixel(x); + len = Width2Pixel(len + HSPACE); + if (x >= TermWin.width) + return; + else if (x + len >= TermWin.width) + len = (TermWin_TotalWidth() - x); + +#ifdef MENUBAR_SHADOW_IN + state = -state; +#endif + switch (state) { + case +1: + top = topShadowGC; + bot = botShadowGC; + break; /* SHADOW_OUT */ + case -1: + top = botShadowGC; + bot = topShadowGC; + break; /* SHADOW_IN */ + case 0: + top = bot = neutralGC; + break; /* neutral */ + } + + if (!(menubar_is_pixmapped())) + Draw_Shadow(menuBar.win, top, bot, + x, 0, len, menuBar_TotalHeight()); +} + +void +drawtriangle(int x, int y, int state) +{ + + GC top = None, bot = None; + int w; + +#ifdef MENUBAR_SHADOW_IN + state = -state; +#endif + switch (state) { + case +1: + top = topShadowGC; + bot = botShadowGC; + break; /* SHADOW_OUT */ + case -1: + top = botShadowGC; + bot = topShadowGC; + break; /* SHADOW_IN */ + case 0: + top = bot = neutralGC; + break; /* neutral */ + } + + w = menu_height() / 2; + + x -= (SHADOW + MENU_MARGIN) + (3 * w / 2); + y += (SHADOW + MENU_MARGIN) + (w / 2); + + Draw_Triangle(ActiveMenu->win, top, bot, x, y, w, 'r'); +} + +void +drawbox_menuitem(int y, int state) +{ + + GC top = None, bot = None; + +#ifdef MENU_SHADOW_IN + state = -state; +#endif + switch (state) { + case +1: + top = topShadowGC; + bot = botShadowGC; + break; /* SHADOW_OUT */ + case -1: + top = botShadowGC; + bot = topShadowGC; + break; /* SHADOW_IN */ + case 0: + top = bot = neutralGC; + break; /* neutral */ + } + + if (!(menubar_is_pixmapped())) + Draw_Shadow(ActiveMenu->win, top, bot, + SHADOW + 0, + SHADOW + y, + ActiveMenu->w - 2 * (SHADOW), + menu_height() + 2 * MENU_MARGIN); + XFlush(Xdisplay); +} + +#if DEBUG >= DEBUG_MENU_LAYOUT +void +print_menu_ancestors(menu_t * menu) +{ + + if (menu == NULL) { + D_MENU_LAYOUT(("Top Level menu\n")); + return; + } + D_MENU_LAYOUT(("menu %s ", menu->name)); + if (menu->parent != NULL) { + menuitem_t *item; + + for (item = menu->parent->head; item != NULL; item = item->next) { + if (item->entry.type == MenuSubMenu && + item->entry.submenu.menu == menu) { + break; + } + } + if (item == NULL) { + fprintf(stderr, "is an orphan!\n"); + return; + } + } + fprintf(stderr, "\n"); + print_menu_ancestors(menu->parent); +} + +void +print_menu_descendants(menu_t * menu) +{ + + menuitem_t *item; + menu_t *parent; + int i, level = 0; + + parent = menu; + do { + level++; + parent = parent->parent; + } + while (parent != NULL); + + for (i = 0; i < level; i++) + fprintf(stderr, ">"); + fprintf(stderr, "%s\n", menu->name); + + for (item = menu->head; item != NULL; item = item->next) { + if (item->entry.type == MenuSubMenu) { + if (item->entry.submenu.menu == NULL) + fprintf(stderr, "> %s == NULL\n", item->name); + else + print_menu_descendants(item->entry.submenu.menu); + } else { + for (i = 0; i < level; i++) + fprintf(stderr, "+"); + if (item->entry.type == MenuLabel) + fprintf(stderr, "label: "); + fprintf(stderr, "%s\n", item->name); + } + } + + for (i = 0; i < level; i++) + fprintf(stderr, "<"); + fprintf(stderr, "\n"); +} +#endif + +/* pop up/down the current menu and redraw the menuBar button */ +void +menu_show(void) +{ + + int x, y, newx, newy, xright; + menuitem_t *item; + XSetWindowAttributes attr = Attributes; + Window true_parent; + + if (ActiveMenu == NULL) + return; + + attr.override_redirect = TRUE; + x = ActiveMenu->x; + if (ActiveMenu->parent == NULL) { + register int h; + + drawbox_menubar(x, ActiveMenu->len, -1); + x = Width2Pixel(x); + + ActiveMenu->y = 1; + ActiveMenu->w = Menu_PixelWidth(ActiveMenu); + + /* find the height */ + for (h = 0, item = ActiveMenu->head; item != NULL; item = item->next) { + if (isSeparator(item->name)) + h += SEPARATOR_HEIGHT; + else + h += menu_height(); + } + ActiveMenu->h = h + 2 * (SHADOW + MENU_MARGIN); + } + if (ActiveMenu->win == None) { + XTranslateCoordinates(Xdisplay, TermWin.vt, Xroot, 0, 0, &newx, &newy, &true_parent); + if (x < newx) { + x += newx; + } + if (x + ActiveMenu->w >= (ScreenOfDisplay(Xdisplay, Xscreen))->width) { + register int dx = ((ActiveMenu->w + x) - (ScreenOfDisplay(Xdisplay, Xscreen))->width); + + x -= dx; + ActiveMenu->x -= dx; + } + y = ActiveMenu->y + newy; + if (y + ActiveMenu->h >= (ScreenOfDisplay(Xdisplay, Xscreen))->height) { + register int dy = ((ActiveMenu->h + y) - (ScreenOfDisplay(Xdisplay, Xscreen))->height); + + y -= dy; + ActiveMenu->y -= dy; + } + ActiveMenu->win = XCreateWindow(Xdisplay, Xroot, + x, + y, + ActiveMenu->w, + ActiveMenu->h, + 0, + Xdepth, InputOutput, + DefaultVisual(Xdisplay, Xscreen), + CWBackPixel | CWBorderPixel + | CWColormap | CWOverrideRedirect + | CWSaveUnder | CWBackingStore, + &attr + ); + + XMapWindow(Xdisplay, ActiveMenu->win); + } + if (!(menubar_is_pixmapped())) + Draw_Shadow(ActiveMenu->win, + topShadowGC, botShadowGC, + 0, 0, + ActiveMenu->w, ActiveMenu->h); + + /* determine the correct right-alignment */ + for (xright = 0, item = ActiveMenu->head; item != NULL; item = item->next) { + if (item->len2 > xright) { + xright = item->len2; + } + } + D_MENU_LAYOUT(("xright == %d\n", xright)); + + for (y = 0, item = ActiveMenu->head; item != NULL; item = item->next) { + + const int xoff = (SHADOW + Width2Pixel(HSPACE) / 2); + const int yoff = (SHADOW + MENU_MARGIN); + register int h; + GC gc = menubarGC; + + if (isSeparator(item->name)) { + if (!(menubar_is_pixmapped())) + Draw_Shadow(ActiveMenu->win, + topShadowGC, botShadowGC, + xoff, + yoff + y + SEPARATOR_HALFHEIGHT, + ActiveMenu->w - (2 * xoff), + 0); + h = SEPARATOR_HEIGHT; + } else { + char *name = item->name; + int len = item->len; + + if (item->entry.type == MenuLabel) { + gc = botShadowGC; + } else if (item->entry.type == MenuSubMenu) { + register int x1, y1; + menuitem_t *it; + menu_t *menu = item->entry.submenu.menu; + + drawtriangle(ActiveMenu->w, y, +1); + + name = menu->name; + len = menu->len; + + y1 = ActiveMenu->y + y; + + /* place sub-menu at midpoint of parent menu */ + menu->w = Menu_PixelWidth(menu); + x1 = ActiveMenu->w / 2; + + /* right-flush menu if it's too small */ + if (x1 > menu->w) + x1 += (x1 - menu->w); + x1 += x; + + /* find the height of this submenu */ + for (h = 0, it = menu->head; it != NULL; it = it->next) { + if (isSeparator(it->name)) + h += SEPARATOR_HEIGHT; + else + h += menu_height(); + } + menu->h = h + 2 * (SHADOW + MENU_MARGIN); + + menu->x = x1; + menu->y = y1; + } else if (item->name2 && !strcmp(name, item->name2)) + name = NULL; + + if (len && name) { + D_MENU_LAYOUT(("len == %d, name == %s\n", len, name)); +#ifdef KANJI + if (fontset) + XmbDrawString(Xdisplay, + ActiveMenu->win, fontset, gc, + xoff, + yoff + y + menu_height() - (MENU_MARGIN + TermWin.font->descent), + name, len); + else +#endif + XDrawString(Xdisplay, + ActiveMenu->win, gc, + xoff, + yoff + y + menu_height() - (MENU_MARGIN + TermWin.font->descent), + name, len); + } + len = item->len2; + name = item->name2; + if (len && name) { + D_MENU_LAYOUT(("len2 == %d, name2 == %s\n", len, name)); +#ifdef KANJI + if (fontset) + XmbDrawString(Xdisplay, + ActiveMenu->win, fontset, gc, + ActiveMenu->w - (xoff + Width2Pixel(xright)), + yoff + y + menu_height() - (MENU_MARGIN + TermWin.font->descent), + name, len); + else +#endif + XDrawString(Xdisplay, + ActiveMenu->win, gc, + ActiveMenu->w - (xoff + Width2Pixel(xright)), + yoff + y + menu_height() - (MENU_MARGIN + TermWin.font->descent), + name, len); + } + h = menu_height(); + } + y += h; + } +} +void +menu_display(void (*update) (void)) +{ + + D_MENUBAR(("menu_display(0x%08x)\n", update)); + + if (ActiveMenu == NULL) + return; + + if (ActiveMenu->win != None) { + XDestroyWindow(Xdisplay, ActiveMenu->win); + ActiveMenu->win = None; + } + ActiveMenu->item = NULL; + + if (ActiveMenu->parent == NULL) + drawbox_menubar(ActiveMenu->x, ActiveMenu->len, +1); + ActiveMenu = ActiveMenu->parent; + update(); +} + +void +menu_hide_all(void) +{ + + D_MENUBAR(("menu_hide_all()\n")); + menu_display(menu_hide_all); +} void +menu_hide(void) +{ + + D_MENUBAR(("menu_hide()\n")); + menu_display(menu_show); +} void + +menu_clear(menu_t * menu) +{ + + D_MENUBAR(("menu_clear(\"%s\")\n", (menu ? menu->name : ""))); + + if (menu != NULL) { + menuitem_t *item = menu->tail; + + while (item != NULL) { + menuitem_free(menu, item); + /* it didn't get freed ... why? */ + if (item == menu->tail) + return; + item = menu->tail; + } + menu->width = 0; + } +} + +void +menubar_clear(void) +{ + + if (CurrentBar != NULL) { + menu_t *menu = CurrentBar->tail; + + while (menu != NULL) { + menu_t *prev = menu->prev; + + menu_delete(menu); + menu = prev; + } + CurrentBar->head = CurrentBar->tail = ActiveMenu = NULL; + + if (CurrentBar->title) { + FREE(CurrentBar->title); + CurrentBar->title = NULL; + } + menuarrow_free(0); /* remove all arrow functions */ + } + ActiveMenu = NULL; +} + +#if (MENUBAR_MAX > 1) +/* find if menu already exists */ +bar_t * +menubar_find(const char *name) +{ + + bar_t *bar = CurrentBar; + + D_MENUBAR_STACKING(("looking for [menu:%s]...\n", name ? name : "(nil)")); + if (bar == NULL || name == NULL) + return NULL; + + if (strlen(name) && strcmp(name, "*")) { + do { + if (!strcmp(bar->name, name)) { + D_MENUBAR_STACKING(("Found!\n")); + return bar; + } + bar = bar->next; + } + while (bar != CurrentBar); + bar = NULL; + } + D_MENUBAR_STACKING(("%s found!\n", (bar ? "" : " NOT"))); + return bar; +} + +int +menubar_push(const char *name) +{ + + int ret = 1; + bar_t *bar; + + if (CurrentBar == NULL) { + /* allocate first one */ + bar = (bar_t *) MALLOC(sizeof(bar_t)); + + if (bar == NULL) + return 0; + + memset(bar, 0, sizeof(bar_t)); + /* circular linked-list */ + bar->next = bar->prev = bar; + bar->head = bar->tail = NULL; + bar->title = NULL; + CurrentBar = bar; + Nbars++; + + menubar_clear(); + } else { + /* find if menu already exists */ + bar = menubar_find(name); + if (bar != NULL) { + /* found it, use it */ + CurrentBar = bar; + } else { + /* create if needed, or reuse the existing empty menubar */ + if (CurrentBar->head != NULL) { + /* need to malloc another one */ + if (Nbars < MENUBAR_MAX) + bar = (bar_t *) MALLOC(sizeof(bar_t)); + else + bar = NULL; + + /* malloc failed or too many menubars, reuse another */ + if (bar == NULL) { + bar = CurrentBar->next; + ret = -1; + } else { + bar->head = bar->tail = NULL; + bar->title = NULL; + + bar->next = CurrentBar->next; + CurrentBar->next = bar; + bar->prev = CurrentBar; + bar->next->prev = bar; + + Nbars++; + } + CurrentBar = bar; + + } + menubar_clear(); + } + } + +/* give menubar this name */ + strncpy(CurrentBar->name, name, MAXNAME); + CurrentBar->name[MAXNAME - 1] = '\0'; + + return ret; +} + +/* switch to a menu called NAME and remove it */ +void +menubar_remove(const char *name) +{ + + bar_t *bar; + + if ((bar = menubar_find(name)) == NULL) + return; + CurrentBar = bar; + + do { + menubar_clear(); + /* + * pop a menubar, clean it up first + */ + if (CurrentBar != NULL) { + bar_t *prev = CurrentBar->prev; + bar_t *next = CurrentBar->next; + + if (prev == next && prev == CurrentBar) { /* only 1 left */ + prev = NULL; + Nbars = 0; /* safety */ + } else { + next->prev = prev; + prev->next = next; + Nbars--; + } + + FREE(CurrentBar); + CurrentBar = prev; + } + } + while (CurrentBar && !strcmp(name, "*")); +} + +void +action_decode(FILE * fp, action_t * act) +{ + + unsigned char *str; + short len; + + if (act == NULL || (len = act->len) == 0 || (str = act->str) == NULL) + return; + + if (act->type == MenuTerminalAction) { + fprintf(fp, "^@"); + /* can strip trailing ^G from XTerm sequence */ + if (str[0] == 033 && str[1] == ']' && str[len - 1] == 007) + len--; + } else if (str[0] == 033) { + switch (str[1]) { + case '[': + case ']': + break; + + case 'x': + /* can strip trailing '\r' from M-x sequence */ + if (str[len - 1] == '\r') + len--; + /* drop */ + + default: + fprintf(fp, "M-"); /* meta prefix */ + str++; + len--; + break; + } + } +/* + * control character form is preferred, since backslash-escaping + * can be really ugly looking when the backslashes themselves also + * have to be escaped to avoid Shell (or whatever scripting + * language) interpretation + */ + while (len > 0) { + unsigned char ch = *str++; + + switch (ch) { + case 033: + fprintf(fp, "\\e"); + break; /* escape */ + case '\r': + fprintf(fp, "\\r"); + break; /* carriage-return */ + case '\\': + fprintf(fp, "\\\\"); + break; /* backslash */ + case '^': + fprintf(fp, "\\^"); + break; /* caret */ + case 127: + fprintf(fp, "^?"); + default: + if (ch <= 31) + fprintf(fp, "^%c", ('@' + ch)); + else if (ch > 127) + fprintf(fp, "\\%o", ch); + else + fprintf(fp, "%c", ch); + break; + } + len--; + } + fprintf(fp, "\n"); +} + +void +menu_dump(FILE * fp, menu_t * menu) +{ + + menuitem_t *item; + +/* create a new menu and clear it */ + fprintf(fp, (menu->parent ? "./%s/*\n" : "/%s/*\n"), menu->name); + + for (item = menu->head; item != NULL; item = item->next) { + switch (item->entry.type) { + case MenuSubMenu: + if (item->entry.submenu.menu == NULL) + fprintf(fp, "> %s == NULL\n", item->name); + else + menu_dump(fp, item->entry.submenu.menu); + break; + + case MenuLabel: + fprintf(fp, "{%s}\n", + (strlen(item->name) ? item->name : "-")); + break; + + case MenuTerminalAction: + case MenuAction: + fprintf(fp, "{%s}", item->name); + if (item->name2 != NULL && strlen(item->name2)) + fprintf(fp, "{%s}", item->name2); + fprintf(fp, "\t"); + action_decode(fp, &(item->entry.action)); + break; + } + } + fprintf(fp, (menu->parent ? "../\n" : "/\n\n")); +} + +void +menubar_dump(FILE * fp) +{ + + bar_t *bar = CurrentBar; + time_t t; + + if (bar == NULL || fp == NULL) + return; + time(&t); + + fprintf(fp, + "# " APL_NAME " (%s) Pid: %u\n# Date: %s\n\n", + rs_name, (unsigned int) getpid(), ctime(&t)); + +/* dump in reverse order */ + bar = CurrentBar->prev; + do { + menu_t *menu; + int i; + + fprintf(fp, "[menu:%s]\n", bar->name); + + if (bar->title != NULL) + fprintf(fp, "[title:%s]\n", bar->title); + + for (i = 0; i < NARROWS; i++) { + switch (bar->arrows[i].type) { + case MenuTerminalAction: + case MenuAction: + fprintf(fp, "<%c>", Arrows[i].name); + action_decode(fp, &(bar->arrows[i])); + break; + } + } + fprintf(fp, "\n"); + + for (menu = bar->head; menu != NULL; menu = menu->next) + menu_dump(fp, menu); + + fprintf(fp, "\n[done:%s]\n\n", bar->name); + bar = bar->prev; + } + while (bar != CurrentBar->prev); +} +#endif /* (MENUBAR_MAX > 1) */ + +/* + * read in menubar commands from FILENAME + * ignore all input before the tag line [menu] or [menu:???] + * + * Note that since File_find () is used, FILENAME can be semi-colon + * delimited such that the second part can refer to a tag + * so that a large `database' of menus can be collected together + * + * FILENAME = "file" + * FILENAME = "file;" + * read `file' starting with first [menu] or [menu:???] line + * + * FILENAME = "file;tag" + * read `file' starting with [menu:tag] + */ +void +menubar_read(const char *filename) +{ + +/* read in a menu from a file */ + FILE *fp; + char buffer[256]; + char *p, *tag = NULL; + const char *file; + + if (!filename || !strlen(filename)) + return; + + file = find_file(filename, ".menu"); + if (file == NULL || (fp = fopen(file, "rb")) == NULL) { + return; + } +#if (MENUBAR_MAX > 1) + /* semi-colon delimited */ + if ((tag = strchr(filename, ';')) != NULL) { + tag++; + if (*tag == '\0') { + tag = NULL; + } + } +#endif /* (MENUBAR_MAX > 1) */ + + D_MENUBAR(("looking for [menu:%s]\n", tag ? tag : "(nil)")); + + while ((p = fgets(buffer, sizeof(buffer), fp)) != NULL) { + + int n; + + D_MENUBAR(("Got \"%s\"\n", p)); + + if ((n = str_leading_match(p, "[menu")) != 0) { + if (tag) { + /* looking for [menu:tag] */ + if (p[n] == ':' && p[n + 1] != ']') { + n++; + n += str_leading_match(p + n, tag); + if (p[n] == ']') { + D_MENUBAR(("[menu:%s]\n", tag)); + break; + } + } + } else if (p[n] == ':' || p[n] == ']') + break; + } + } + +/* found [menu], [menu:???] tag */ + while (p != NULL) { + + int n; + + D_MENUBAR(("read line = %s\n", p)); + + /* looking for [done:tag] or [done:] */ + if ((n = str_leading_match(p, "[done")) != 0) { + if (p[n] == ']') { + menu_readonly = 1; + break; + } else if (p[n] == ':') { + n++; + if (p[n] == ']') { + menu_readonly = 1; + break; + } else if (tag) { + n += str_leading_match(p + n, tag); + if (p[n] == ']') { + D_MENUBAR(("[done:%s]\n", tag)); + menu_readonly = 1; + break; + } + } else { + /* what? ... skip this line */ + p[0] = COMMENT_CHAR; + } + } + } + /* + * remove leading/trailing space + * and strip-off leading/trailing quotes + * skip blank or comment lines + */ + p = str_trim(p); + if (p != NULL && *p && *p != COMMENT_CHAR) { + menu_readonly = 0; /* if case we read another file */ + menubar_dispatch(p); + } + /* get another line */ + p = fgets(buffer, sizeof(buffer), fp); + } + + fclose(fp); +} + +/* + * user interface for building/deleting and otherwise managing menus + */ +void +menubar_dispatch(char *str) +{ + + static menu_t *BuildMenu = NULL; /* the menu currently being built */ + int n, cmd; + char *path, *name, *name2; + + D_MENUBAR(("menubar_dispatch(%s) called\n", str)); + + if (menubar_visible() && ActiveMenu != NULL) + menubar_expose(); + else + ActiveMenu = NULL; + + cmd = *str; + switch (cmd) { + case '.': + case '/': /* absolute & relative path */ + case MENUITEM_BEG: /* menuitem */ + /* add `+' prefix for these cases */ + cmd = '+'; + break; + + case '+': + case '-': + str++; /* skip cmd character */ + break; + + case '<': +#if (MENUBAR_MAX > 1) + if (CurrentBar == NULL) + break; +#endif /* (MENUBAR_MAX > 1) */ + if (str[1] && str[2] == '>') /* arrow commands */ + menuarrow_add(str); + break; + + case '=': + D_MENUBAR(("Setting title\n")); + str++; + if (CurrentBar != NULL && !menu_readonly) { + if (*str) { + name = REALLOC(CurrentBar->title, strlen(str) + 1); + if (name != NULL) { + strcpy(name, str); + CurrentBar->title = name; + } + menubar_expose(); + } else { + FREE(CurrentBar->title); + CurrentBar->title = NULL; + } + } + break; + + case '[': /* extended command */ + while (str[0] == '[') { + char *next = (++str); /* skip leading '[' */ + + if (str[0] == ':') { /* [:command:] */ + do { + next++; + if ((next = strchr(next, ':')) == NULL) + return; /* parse error */ + } while (next[1] != ']'); + + /* remove and skip ':]' */ + *next = '\0'; + next += 2; + } else { + if ((next = strchr(next, ']')) == NULL) + return; /* parse error */ + /* remove and skip ']' */ + *next = '\0'; + next++; + } + + if (str[0] == ':') { + int saved; + + /* try and dispatch it, regardless of read/write status */ + D_MENUBAR(("Ignoring read-only status to parse command %s\n", str + 1)); + saved = menu_readonly; + menu_readonly = 0; + menubar_dispatch(str + 1); + menu_readonly = saved; + } + /* these ones don't require menu stacking */ + else if (!strcmp(str, "clear")) { + D_MENUBAR(("Extended command \"clear\"\n")); + menubar_clear(); + } else if (!strcmp(str, "done") || str_leading_match(str, "done:")) { + D_MENUBAR(("Extended command \"done\"\n")); + menu_readonly = 1; + } else if (!strcmp(str, "show")) { + D_MENUBAR(("Extended command \"show\"\n")); + map_menuBar(1); + menu_readonly = 1; + } else if (!strcmp(str, "hide")) { + D_MENUBAR(("Extended command \"hide\"\n")); + map_menuBar(0); + menu_readonly = 1; + } else if ((n = str_leading_match(str, "read:")) != 0) { + /* read in a menu from a file */ + D_MENUBAR(("Extended command \"read\"\n")); + str += n; + menubar_read(str); + } else if ((n = str_leading_match(str, "echo:")) != 0) { + D_MENUBAR(("Extended command \"echo\"\n")); + str += n; + tt_write(str, strlen(str)); + tt_write("\r", 1); + } else if ((n = str_leading_match(str, "apptitle:")) != 0) { + D_MENUBAR(("Extended command \"apptitle\"\n")); + str += n; + xterm_seq(XTerm_title, str); + } else if ((n = str_leading_match(str, "title:")) != 0) { + D_MENUBAR(("Extended command \"title\"\n")); + str += n; + if (CurrentBar != NULL && !menu_readonly) { + if (*str) { + name = REALLOC(CurrentBar->title, strlen(str) + 1); + if (name != NULL) { + strcpy(name, str); + CurrentBar->title = name; + } + menubar_expose(); + } else { + FREE(CurrentBar->title); + CurrentBar->title = NULL; + } + } + } else if ((n = str_leading_match(str, "pixmap:")) != 0) { + D_MENUBAR(("Extended command \"pixmap\"\n")); + str += n; + xterm_seq(XTerm_Pixmap, str); + } +#if (MENUBAR_MAX > 1) + else if ((n = str_leading_match(str, "rm")) != 0) { + D_MENUBAR(("Extended command \"rm\"\n")); + str += n; + switch (str[0]) { + case ':': + str++; + menubar_remove(str); + break; + + case '\0': + menubar_remove(str); + break; + + case '*': + menubar_remove(str); + break; + } + menu_readonly = 1; + } else if ((n = str_leading_match(str, "menu")) != 0) { + D_MENUBAR(("Extended command \"menu\"\n")); + str += n; + switch (str[0]) { + case ':': + str++; + /* add/access menuBar */ + if (*str != '\0' && *str != '*') + menubar_push(str); + break; + default: + if (CurrentBar == NULL) { + menubar_push("default"); + } + } + + + if (CurrentBar != NULL) + menu_readonly = 0; /* allow menu build commands */ + } else if (!strcmp(str, "dump")) { + /* dump current menubars to a file */ + FILE *fp; + + /* enough space to hold the results */ + char buffer[32]; + + D_MENUBAR(("Extended command \"dump\"\n")); + sprintf(buffer, "/tmp/" APL_NAME "-%u", + (unsigned int) getpid()); + + if ((fp = fopen(buffer, "wb")) != NULL) { + xterm_seq(XTerm_title, buffer); + menubar_dump(fp); + fclose(fp); + } + } else if (!strcmp(str, "next")) { + if (CurrentBar) { + CurrentBar = CurrentBar->next; + menu_readonly = 1; + } + } else if (!strcmp(str, "prev")) { + if (CurrentBar) { + CurrentBar = CurrentBar->prev; + menu_readonly = 1; + } + } else if (!strcmp(str, "swap")) { + /* swap the top 2 menus */ + if (CurrentBar) { + bar_t *prev = CurrentBar->prev; + bar_t *next = CurrentBar->next; + + prev->next = next; + next->prev = prev; + + CurrentBar->next = prev; + CurrentBar->prev = prev->prev; + + prev->prev->next = CurrentBar; + prev->prev = CurrentBar; + + CurrentBar = prev; + menu_readonly = 1; + } + } +#endif /* (MENUBAR_MAX > 1) */ + str = next; + + BuildMenu = ActiveMenu = NULL; + menubar_expose(); + D_MENUBAR_STACKING(("menus are read%s\n", menu_readonly ? "only" : "/write")); + } + return; + break; + } + +#if (MENUBAR_MAX > 1) + if (CurrentBar == NULL) + return; + if (menu_readonly) { + D_MENUBAR_STACKING(("menus are read%s\n", menu_readonly ? "only" : "/write")); + return; + } +#endif /* (MENUBAR_MAX > 1) */ + + switch (cmd) { + case '+': + case '-': + path = name = str; + + name2 = NULL; + /* parse STR, allow spaces inside (name) */ + if (path[0] != '\0') { + name = strchr(path, MENUITEM_BEG); + str = strchr(path, MENUITEM_END); + if (name != NULL || str != NULL) { + if (name == NULL || str == NULL || str <= (name + 1) + || (name > path && name[-1] != '/')) { + print_error("menu error <%s>\n", path); + break; + } + if (str[1] == MENUITEM_BEG) { + name2 = (str + 2); + str = strchr(name2, MENUITEM_END); + + if (str == NULL) { + print_error("menu error <%s>\n", path); + break; + } + name2[-2] = '\0'; /* remove prev MENUITEM_END */ + } + if (name > path && name[-1] == '/') + name[-1] = '\0'; + + *name++ = '\0'; /* delimit */ + *str++ = '\0'; /* delimit */ + + while (isspace(*str)) + str++; /* skip space */ + } + D_MENUBAR(("`%c' path = <%s>, name = <%s>, name2 = <%s>, action = <%s>\n", cmd, + (path ? path : "(nil)"), (name ? name : "(nil)"), (name2 ? name2 : "(nil)"), + (str ? str : "(nil)"))); + } + /* process the different commands */ + switch (cmd) { + case '+': /* add/replace existing menu or menuitem */ + if (path[0] != '\0') { + int len; + + path = menu_find_base(&BuildMenu, path); + len = strlen(path); + + /* don't allow menus called `*' */ + if (path[0] == '*') { + menu_clear(BuildMenu); + break; + } else if (len >= 2 && !strcmp((path + len - 2), "/*")) { + path[len - 2] = '\0'; + } + if (path[0] != '\0') + BuildMenu = menu_add(BuildMenu, path); + } + if (name != NULL && name[0] != '\0') { + if (!strcmp(name, SEPARATOR_NAME)) + name = ""; + menuitem_add(BuildMenu, name, name2, str); + } + break; + + case '-': /* delete menu entry */ + if (!strcmp(path, "/*") && (name == NULL || name[0] == '\0')) { + menubar_clear(); + BuildMenu = NULL; + menubar_expose(); + break; + } else if (path[0] != '\0') { + int len; + menu_t *menu = BuildMenu; + + path = menu_find_base(&menu, path); + len = strlen(path); + + /* submenu called `*' clears all menu items */ + if (path[0] == '*') { + menu_clear(menu); + break; /* done */ + } else if (len >= 2 && !strcmp(&path[len - 2], "/*")) { + /* done */ + break; + } else if (path[0] != '\0') { + BuildMenu = NULL; + break; + } else { + BuildMenu = menu; + } + } + if (BuildMenu != NULL) { + if (name == NULL || name[0] == '\0') { + BuildMenu = menu_delete(BuildMenu); + } else { + menuitem_t *item; + + if (!strcmp(name, SEPARATOR_NAME)) + name = ""; + item = menuitem_find(BuildMenu, name); + + if (item != NULL && item->entry.type != MenuSubMenu) { + menuitem_free(BuildMenu, item); + + /* fix up the width */ + BuildMenu->width = 0; + for (item = BuildMenu->head; + item != NULL; + item = item->next) { + if (BuildMenu->width < (item->len + item->len2)) + BuildMenu->width = (item->len + item->len2); + } + } + } + menubar_expose(); + } + break; + } + break; + } +} + +void +draw_Arrows(int name, int state) +{ + + GC top = None, bot = None; + + int i; + +#ifdef MENU_SHADOW_IN + state = -state; +#endif + switch (state) { + case +1: + top = topShadowGC; + bot = botShadowGC; + break; /* SHADOW_OUT */ + case -1: + top = botShadowGC; + bot = topShadowGC; + break; /* SHADOW_IN */ + case 0: + top = bot = neutralGC; + break; /* neutral */ + } + if (!Arrows_x) + return; + + for (i = 0; i < NARROWS; i++) { + const int w = Width2Pixel(1); + const int y = (menuBar_TotalHeight() - w) / 2; + int x = Arrows_x + (5 * Width2Pixel(i)) / 4; + + if (!name || name == Arrows[i].name) + Draw_Triangle(menuBar.win, top, bot, x, y, w, + Arrows[i].name); + } + XFlush(Xdisplay); +} + +void +menubar_expose(void) +{ + + menu_t *menu; + int x; + +# ifdef CHANGE_SCROLLCOLOR_ON_FOCUS + static int focus = -1; + +# endif +# ifdef KANJI + static int fsTry = 0; + +# endif + + if (delay_menu_drawing || !menubar_visible()) + return; + +#ifdef KANJI + if (!fontset && !fsTry) { + char *fontname = malloc(strlen(rs_font[0]) + strlen(rs_kfont[0]) + 2); + int i, mc; + char **ml, *ds; + + fsTry = 1; + if (fontname) { + setlocale(LC_ALL, ""); + strcpy(fontname, rs_font[0]); + strcat(fontname, ","); + strcat(fontname, rs_kfont[0]); + fontset = XCreateFontSet(Xdisplay, fontname, &ml, &mc, &ds); + free(fontname); + if (mc) { + XFreeStringList(ml); + fontset = 0; + return; + } + } + } +#endif /* KANJI */ + + if (menubarGC == None) { + /* Create the graphics context */ + XGCValues gcvalue; + + gcvalue.font = TermWin.font->fid; + + gcvalue.foreground = (Xdepth <= 2 ? + PixColors[fgColor] : + PixColors[menuTextColor]); + menubarGC = XCreateGC(Xdisplay, menuBar.win, + GCForeground | GCFont, + &gcvalue); + +#ifdef KEEP_SCROLLCOLOR + gcvalue.foreground = PixColors[scrollColor]; +#endif + neutralGC = XCreateGC(Xdisplay, menuBar.win, + GCForeground, + &gcvalue); + +#ifdef KEEP_SCROLLCOLOR + gcvalue.foreground = PixColors[bottomShadowColor]; +#endif + botShadowGC = XCreateGC(Xdisplay, menuBar.win, + GCForeground | GCFont, + &gcvalue); + +#ifdef KEEP_SCROLLCOLOR + gcvalue.foreground = PixColors[topShadowColor]; +#endif + topShadowGC = XCreateGC(Xdisplay, menuBar.win, + GCForeground, + &gcvalue); + } +# ifdef CHANGE_SCROLLCOLOR_ON_FOCUS + /* Update colors on focus change */ + if (focus != TermWin.focus) { + XGCValues gcvalue; + + focus = TermWin.focus; + + gcvalue.foreground = PixColors[fgColor]; + +# ifdef KEEP_SCROLLCOLOR + if (Xdepth > 2) + gcvalue.foreground = PixColors[focus ? scrollColor : unfocusedScrollColor]; +# endif + + XChangeGC(Xdisplay, neutralGC, GCForeground, + &gcvalue); + + gcvalue.background = gcvalue.foreground; + XChangeGC(Xdisplay, menubarGC, GCBackground, + &gcvalue); + XChangeGC(Xdisplay, neutralGC, GCForeground, + &gcvalue); + + XSetWindowBackground(Xdisplay, menuBar.win, gcvalue.foreground); + + gcvalue.foreground = PixColors[bgColor]; + +# ifdef KEEP_SCROLLCOLOR + gcvalue.foreground = PixColors[focus ? topShadowColor : unfocusedTopShadowColor]; +# endif + XChangeGC(Xdisplay, topShadowGC, + GCForeground, + &gcvalue); + +# ifdef KEEP_SCROLLCOLOR + gcvalue.foreground = PixColors[focus ? bottomShadowColor : unfocusedBottomShadowColor]; +# endif + XChangeGC(Xdisplay, botShadowGC, + GCForeground, + &gcvalue); + + } +#endif + + /* make sure the font is correct */ + XSetFont(Xdisplay, menubarGC, TermWin.font->fid); + XSetFont(Xdisplay, botShadowGC, TermWin.font->fid); + XClearWindow(Xdisplay, menuBar.win); + + menu_hide_all(); + + x = 0; + if (CurrentBar != NULL) { + for (menu = CurrentBar->head; menu != NULL; menu = menu->next) { + int len = menu->len; + + x = (menu->x + menu->len + HSPACE); + +#if DEBUG >= DEBUG_MENU_LAYOUT + if (debug_level >= DEBUG_MENU_LAYOUT) { + print_menu_descendants(menu); + } +#endif + + if (x >= TermWin.ncol) + len = (TermWin.ncol - (menu->x + HSPACE)); + + drawbox_menubar(menu->x, len, +1); + +#ifdef KANJI + if (fontset) + XmbDrawString(Xdisplay, menuBar.win, fontset, menubarGC, (Width2Pixel(menu->x) + Width2Pixel(HSPACE) / 2), + menuBar_height() - (TermWin.font->descent) + 1, menu->name, len); + else +#endif + XDrawString(Xdisplay, menuBar.win, menubarGC, (Width2Pixel(menu->x) + Width2Pixel(HSPACE) / 2), + menuBar_height() - (TermWin.font->descent) + 1, menu->name, len); + if (x >= TermWin.ncol) + break; + } + } + drawbox_menubar(x, TermWin.ncol, 1); + + /* add the menuBar title, if it exists and there's plenty of room */ + Arrows_x = 0; + if (x < TermWin.ncol) { + char *str, title[256]; + int len, ncol = TermWin.ncol; + + if (x < (ncol - (NARROWS + 1))) { + ncol -= (NARROWS + 1); + Arrows_x = menuBar_TotalWidth() - (2 * SHADOW + ((5 * Width2Pixel(1)) / 4 * NARROWS) + HSPACE); + } + draw_Arrows(0, -1); + + str = (CurrentBar && CurrentBar->title ? CurrentBar->title : "%n"); + for (len = 0; str[0] && len < sizeof(title) - 1; str++) { + const char *s = NULL; + + switch (str[0]) { + case '%': + str++; + switch (str[0]) { + case 'n': + s = rs_name; + break; /* resource name */ + case 'v': + s = VERSION; + break; /* version number */ + case '%': + s = "%"; + break; /* literal '%' */ + } + if (s != NULL) + while (*s && len < sizeof(title) - 1) + title[len++] = *s++; + break; + + default: + title[len++] = str[0]; + break; + } + } + title[len] = '\0'; + + ncol = Pixel2Width(Arrows_x - Width2Pixel(x) - Width2Pixel(len) - Width2Pixel(4)); +#ifdef KANJI + if (fontset) { + if (len > 0 && ncol >= 0) + XmbDrawString(Xdisplay, menuBar.win, fontset, menubarGC, + Width2Pixel(x) + ((Arrows_x - Width2Pixel(x)) / 2 - (Width2Pixel(len) / 2)), + menuBar_height() - (TermWin.font->descent) + 1, title, len); + } else +#endif + if (len > 0 && ncol >= 0) + XDrawString(Xdisplay, menuBar.win, menubarGC, + Width2Pixel(x) + ((Arrows_x - Width2Pixel(x + len + 1)) / 2), + menuBar_height() - (TermWin.font->descent) + 1, title, len); + } +} + +int +menubar_mapping(int map) +{ + + int change = 0; + + if (map && !menubar_visible()) { + menuBar.state = 1; + XMapWindow(Xdisplay, menuBar.win); + change = 1; + } else if (!map && menubar_visible()) { + menubar_expose(); + menuBar.state = 0; + XUnmapWindow(Xdisplay, menuBar.win); + change = 1; + } else + menubar_expose(); + + return change; +} + +int +menu_select(XButtonEvent * ev) +{ + + menuitem_t *thisitem, *item = NULL; + int this_y = 0, y = 0; + + Window unused_root, unused_child; + int unused_root_x, unused_root_y; + unsigned int unused_mask; + + if (ActiveMenu == NULL) + return 0; + + D_MENUBAR(("menu_select()\n")); + XQueryPointer(Xdisplay, ActiveMenu->win, + &unused_root, &unused_child, + &unused_root_x, &unused_root_y, + &(ev->x), &(ev->y), + &unused_mask); + + if (ActiveMenu->parent != NULL && (ev->x < 0 || ev->y < 0 || (ev->y > menu_height() && ev->x < 0))) { + menu_hide(); + return 1; + } + + /* determine the menu item corresponding to the Y index */ + if (ev->x >= 0 && ev->x <= (ActiveMenu->w - SHADOW)) { + for (y = 0, item = ActiveMenu->head; item != NULL; item = item->next) { + int h = menu_height(); + + if (isSeparator(item->name)) { + h = SEPARATOR_HEIGHT; + } else if (ev->y >= y && ev->y < (y + h)) { + break; + } + y += h; + } + } + if (item == NULL && ev->type == ButtonRelease) { + menu_hide_all(); + return 0; + } + thisitem = item; + this_y = y; + +/* erase the last item */ + if (ActiveMenu->item != NULL) { + if (ActiveMenu->item != thisitem) { + for (y = 0, item = ActiveMenu->head; item != NULL; item = item->next) { + + int h = menu_height(); + + if (isSeparator(item->name)) { + h = SEPARATOR_HEIGHT; + } else if (item == ActiveMenu->item) { + /* erase old menuitem */ + drawbox_menuitem(y, 0); /* No Shadow */ + if (item->entry.type == MenuSubMenu) + drawtriangle(ActiveMenu->w, y, +1); + break; + } + y += h; + } + } else { + if (ev->type == ButtonRelease) { + switch (item->entry.type) { + case MenuLabel: + case MenuSubMenu: + menu_hide_all(); + break; + + case MenuAction: + case MenuTerminalAction: + drawbox_menuitem(this_y, -1); + +#if MENU_DELAY_USEC > 0 + /* use select for timing */ + { + struct itimerval tv; + + tv.it_value.tv_sec = 0; + tv.it_value.tv_usec = MENU_DELAY_USEC; + + select(0, NULL, NULL, NULL, &tv.it_value); + } +#endif + menu_hide_all(); /* remove menu before sending keys to the application */ + D_MENUBAR(("%s: %s\n", item->name, item->entry.action.str)); + action_dispatch(&(item->entry.action)); + break; + } + return 0; + } else if (item->entry.type != MenuSubMenu) { + return 0; + } + } + } + ActiveMenu->item = thisitem; + y = this_y; + if (thisitem != NULL) { + item = ActiveMenu->item; + if (item->entry.type != MenuLabel) + drawbox_menuitem(y, +1); + if (item->entry.type == MenuSubMenu) { + drawtriangle(ActiveMenu->w, y, -1); + if ((ev->x > ActiveMenu->w / 2) && (ev->y > 0) && (Menu_PixelWidth(item->entry.submenu.menu) + ev->x >= ActiveMenu->w)) { + ActiveMenu = item->entry.submenu.menu; + menu_show(); + return 1; + } + } + } + return 0; +} + +void +menubar_select(XButtonEvent * ev) +{ + + menu_t *menu = NULL; + static int last_mouse_x = 0, last_mouse_y = 0, last_win_x = 0, last_win_y = 0; + int mouse_x, mouse_y, win_x, win_y, dx, dy, unused; + Window unused_window; + +/* determine the pulldown menu corresponding to the X index */ + D_MENUBAR(("menubar_select():\n")); + if (ev->y >= 0 && ev->y <= menuBar_height() && CurrentBar != NULL) { + for (menu = CurrentBar->head; menu != NULL; menu = menu->next) { + int x = Width2Pixel(menu->x); + int w = Width2Pixel(menu->len + HSPACE); + + if ((ev->x >= x && ev->x < x + w)) + break; + } + } + switch (ev->type) { + case ButtonRelease: + D_MENUBAR((" menubar_select(ButtonRelease)\n")); + menu_hide_all(); + break; + + case ButtonPress: + D_MENUBAR((" menubar_select(ButtonPress)\n")); + if (menu == NULL && Arrows_x && ev->x >= Arrows_x) { + int i; + + for (i = 0; i < NARROWS; i++) { + if ((ev->x >= (Arrows_x + (Width2Pixel(4 * i + i)) / 4)) && (ev->x < (Arrows_x + (Width2Pixel(4 * i + i + 4)) / 4))) { + + draw_Arrows(Arrows[i].name, +1); + +#if MENU_DELAY_USEC > 0 + /* + * use select for timing + */ + { + struct itimerval tv; + + tv.it_value.tv_sec = 0; + tv.it_value.tv_usec = MENU_DELAY_USEC; + + select(0, NULL, NULL, NULL, &tv.it_value); + } +#endif + + draw_Arrows(Arrows[i].name, -1); +#if DEBUG >= DEBUG_MENUARROWS + if (debug_level >= DEBUG_MENUARROWS) { + fprintf(stderr, "'%c': ", Arrows[i].name); + + if (CurrentBar == NULL || + (CurrentBar->arrows[i].type != MenuAction && + CurrentBar->arrows[i].type != MenuTerminalAction)) { + if (Arrows[i].str != NULL && Arrows[i].str[0]) + fprintf(stderr, "(default) \\033%s\n", + &(Arrows[i].str[2])); + } else { + fprintf(stderr, "%s\n", CurrentBar->arrows[i].str); + } + } else { +#endif + if (CurrentBar == NULL || + action_dispatch(&(CurrentBar->arrows[i]))) { + if (Arrows[i].str != NULL && + Arrows[i].str[0] != 0) + tt_write((Arrows[i].str + 1), + Arrows[i].str[0]); + } +#if DEBUG >= DEBUG_MENUARROWS + } +#endif /* DEBUG_MENUARROWS */ + return; + } + } + } else if (menu == NULL && ActiveMenu == NULL && Options & Opt_menubar_move) { + XTranslateCoordinates(Xdisplay, TermWin.parent, Xroot, + 0, 0, &last_win_x, &last_win_y, &unused_window); + XQueryPointer(Xdisplay, TermWin.parent, &unused_window, &unused_window, &unused, &unused, + &last_mouse_x, &last_mouse_y, &unused); + D_MENUBAR(("Initial data: last_mouse == %d,%d last_win == %d,%d\n", + last_mouse_x, last_mouse_y, last_win_x, last_win_y)); + break; + } + /*drop */ + case MotionNotify: + if (menu == NULL && ActiveMenu == NULL && Options & Opt_menubar_move) { + XQueryPointer(Xdisplay, TermWin.parent, &unused_window, &unused_window, &unused, &unused, + &mouse_x, &mouse_y, &unused); + if (mouse_x != last_mouse_x || mouse_y != last_mouse_y) { + dx = mouse_x - last_mouse_x; + dy = mouse_y - last_mouse_y; + D_MENUBAR((" -> last_mouse == %d,%d mouse == %d,%d rel == %d,%d move %d,%d to %d,%d\n", + last_mouse_x, last_mouse_y, mouse_x, mouse_y, dx, dy, last_win_x, last_win_y, last_win_x + dx, last_win_y + dy)); + XMoveWindow(Xdisplay, TermWin.parent, last_win_x + dx, last_win_y + dy); + last_win_x += dx; + last_win_y += dy; + } + break; + } + /* drop */ + default: + /* + * press menubar or move to a new entry + */ + D_MENUBAR((" menubar_select(default)\n")); + if (menu != NULL && menu != ActiveMenu) { + menu_hide_all(); /* pop down old menu */ + ActiveMenu = menu; + menu_show(); /* pop up new menu */ + } + break; + } +} + +/* + * general dispatch routine, + * it would be nice to have `sticky' menus + */ +void +menubar_control(XButtonEvent * ev) +{ + + switch (ev->type) { + case ButtonPress: + D_MENUBAR(("menubar_control(ButtonPress)\n")); + if (ev->button == Button1) + menubar_select(ev); + break; + + case ButtonRelease: + D_MENUBAR(("menubar_control(ButtonRelease)\n")); + if (ev->button == Button1) + menu_select(ev); + break; + + case MotionNotify: + D_MENUBAR(("menubar_control(MotionNotify)\n")); + while (XCheckTypedWindowEvent(Xdisplay, TermWin.parent, MotionNotify, (XEvent *) ev)); + + if (ActiveMenu) + while (menu_select(ev)); + else + ev->y = -1; + if (ev->y < 0) { + + Window unused_root, unused_child; + int unused_root_x, unused_root_y; + unsigned int unused_mask; + + XQueryPointer(Xdisplay, menuBar.win, &unused_root, &unused_child, &unused_root_x, &unused_root_y, + &(ev->x), &(ev->y), &unused_mask); + menubar_select(ev); + } + break; + } +} +#endif /* MENUBAR_MAX */ diff --git a/src/menubar.h b/src/menubar.h new file mode 100644 index 0000000..ac19d45 --- /dev/null +++ b/src/menubar.h @@ -0,0 +1,126 @@ +/*--------------------------------*-C-*---------------------------------* + * File: menubar.h + * + * Copyright 1996,97 + * mj olesen Queen's Univ at Kingston + * + * You can do what you like with this source code provided you don't make + * money from it and you include an unaltered copy of this message + * (including the copyright). As usual, the author accepts no + * responsibility for anything, nor does he guarantee anything whatsoever. + *----------------------------------------------------------------------*/ +#ifndef _MENUBAR_H +# define _MENUBAR_H +# include /* Xlib, Xutil, Xresource, Xfuncproto */ +# include + +typedef struct { + short state; + Window win; +} menuBar_t; + +typedef struct { + short type; /* must not be changed; first element */ + short len; /* strlen (str) */ + unsigned char *str; /* action to take */ +} action_t; + +typedef struct { + short type; /* must not be changed; first element */ + struct menu_t *menu; /* sub-menu */ +} submenu_t; + +typedef struct menuitem_t { + struct menuitem_t *prev; /* prev menu-item */ + struct menuitem_t *next; /* next menu-item */ + char *name; /* character string displayed */ + char *name2; /* character string displayed (right) */ + short len; /* strlen (name) */ + short len2; /* strlen (name) */ + union { + short type; /* must not be changed; first element */ + action_t action; + submenu_t submenu; + } entry; +} menuitem_t; + +enum menuitem_t_action { + MenuLabel, + MenuAction, + MenuTerminalAction, + MenuSubMenu +}; + +typedef struct menu_t { + struct menu_t *parent; /* parent menu */ + struct menu_t *prev; /* prev menu */ + struct menu_t *next; /* next menu */ + menuitem_t *head; /* double-linked list */ + menuitem_t *tail; /* double-linked list */ + menuitem_t *item; /* current item */ + char *name; /* menu name */ + short len; /* strlen (name) */ + short width; /* maximum menu width [chars] */ + Window win; /* window of the menu */ + short x; /* x location [pixels] (chars if parent == NULL) */ + short y; /* y location [pixels] */ + short w, h; /* window width, height [pixels] */ +} menu_t; + +typedef struct bar_t { + menu_t *head, *tail; /* double-linked list of menus */ + char *title; /* title to put in the empty menuBar */ +# if (MENUBAR_MAX > 1) +# define MAXNAME 16 + char name[MAXNAME]; /* name to use to refer to menubar */ + struct bar_t *next, *prev; /* circular linked-list */ +# endif /* (MENUBAR_MAX > 1) */ +# define NARROWS 4 + action_t arrows[NARROWS]; +} bar_t; + +extern menuBar_t menuBar; +extern int delay_menu_drawing; + +# define menuBar_margin 2 /* margin below text */ +# ifdef PIXMAP_MENUBAR +# define menubar_is_pixmapped() (0) +# else +# define menubar_is_pixmapped() (0) +# endif +/* macros */ +#define menubar_visible() (menuBar.state) +#define menuBar_height() (TermWin.fheight + SHADOW) +#define menuBar_TotalHeight() (menuBar_height() + SHADOW + menuBar_margin) +#define menuBar_TotalWidth() (2 * TermWin.internalBorder + TermWin.width) +#define isMenuBarWindow(w) ((w) == menuBar.win) + +_XFUNCPROTOBEGIN + +extern void +menubar_control (XButtonEvent * /* ev */); + +extern void +menubar_dispatch (char * /* str */); + +extern void +menubar_expose (void); + +extern int +menubar_mapping (int /* map */); + +_XFUNCPROTOEND + +#if !(MENUBAR_MAX) +# define menubar_dispatch(str) ((void)0) +# define menubar_expose() ((void)0) +# define menubar_control(ev) ((void)0) +# define menubar_mapping(map) (0) +# undef menubar_visible +# define menubar_visible() (0) +# undef isMenuBarWindow +# define isMenuBarWindow(w) (0) +#endif + +#endif /* _MENUBAR_H */ +/*----------------------- end-of-file (C header) -----------------------*/ diff --git a/src/misc.c b/src/misc.c new file mode 100644 index 0000000..c75a99b --- /dev/null +++ b/src/misc.c @@ -0,0 +1,379 @@ +/*--------------------------------*-C-*---------------------------------* + * File: misc.c + * + * miscellaneous service routines + * + * Copyright 1996,97 + * mj olesen Queen's Univ at Kingston + * + * You can do what you like with this source code provided you don't make + * money from it and you include an unaltered copy of this message + * (including the copyright). As usual, the author accepts no + * responsibility for anything, nor does he guarantee anything whatsoever. + *----------------------------------------------------------------------*/ + +static const char cvs_ident[] = "$Id$"; + +#include +#include +#include +#include +#include + +#include "command.h" +#include "main.h" +#include "misc.h" +#include "debug.h" +#include "../libmej/debug.h" +#include "../libmej/strings.h" +#include "mem.h" +#include "options.h" + +/*----------------------------------------------------------------------*/ +const char * +my_basename(const char *str) +{ + + const char *base = strrchr(str, '/'); + + return (base ? base + 1 : str); + +} + +/* Print a non-terminal error message */ +void +print_error(const char *fmt,...) +{ + + va_list arg_ptr; + + va_start(arg_ptr, fmt); + fprintf(stderr, APL_NAME ": "); + vfprintf(stderr, fmt, arg_ptr); + fprintf(stderr, "\n"); + va_end(arg_ptr); +} + +/* Print a simple warning. */ +void +print_warning(const char *fmt,...) +{ + + va_list arg_ptr; + + va_start(arg_ptr, fmt); + fprintf(stderr, APL_NAME ": warning: "); + vfprintf(stderr, fmt, arg_ptr); + fprintf(stderr, "\n"); + va_end(arg_ptr); +} + +/* Print a fatal error message and terminate */ +void +fatal_error(const char *fmt,...) +{ + + va_list arg_ptr; + + va_start(arg_ptr, fmt); + fprintf(stderr, APL_NAME ": FATAL: "); + vfprintf(stderr, fmt, arg_ptr); + fprintf(stderr, "\n"); + va_end(arg_ptr); + exit(-1); +} + +/* + * Compares the first n characters of s1 and s2, where n is strlen(s2) + * Returns strlen(s2) if they match, 0 if not. + */ +unsigned long +str_leading_match(register const char *s1, register const char *s2) +{ + + register unsigned long n; + + if (!s1 || !s2) { + return (0); + } + for (n = 0; *s2; n++, s1++, s2++) { + if (*s1 != *s2) { + return 0; + } + } + + return n; +} + +/* Strip leading and trailing whitespace and quotes from a string */ +char * +str_trim(char *str) +{ + + register char *tmp = str; + size_t n; + + if (str && *str) { + + chomp(str); + n = strlen(str); + + if (!n) { + *str = 0; + return str; + } + /* strip leading/trailing quotes */ + if (*tmp == '"') { + tmp++; + n--; + if (!n) { + *str = 0; + return str; + } else if (tmp[n - 1] == '"') { + tmp[--n] = '\0'; + } + } + if (tmp != str) { + memmove(str, tmp, (strlen(tmp)) + 1); + } + } + return str; +} + +/* + * in-place interpretation of string: + * + * backslash-escaped: "\a\b\E\e\n\r\t", "\octal" + * Ctrl chars: ^@ .. ^_, ^? + * + * Emacs-style: "M-" prefix + * + * Also, + * "M-x" prefixed strings, append "\r" if needed + * "\E]" prefixed strings (XTerm escape sequence) append "\a" if needed + * + * returns the converted string length + */ + +#define MAKE_CTRL_CHAR(c) ((c) == '?' ? 127 : ((toupper(c)) - '@')) + +int +parse_escaped_string(char *str) +{ + + register char *pold, *pnew; + unsigned char i; + + D_MENUBAR(("parse_escaped_string(\"%s\")\n", str)); + + for (pold = pnew = str; *pold; pold++, pnew++) { + D_MENUBAR(("Looking at \"%s\"\n", pold)); + if (!BEG_STRCASECMP(pold, "m-")) { + *pold = '\\'; + *(pold + 1) = 'e'; + } else if (!BEG_STRCASECMP(pold, "c-")) { + *(++pold) = '^'; + } + D_MENUBAR(("Operating on \'%c\'\n", *pold)); + switch (*pold) { + case '\\': + D_MENUBAR(("Backslash + %c\n", *(pold + 1))); + switch (tolower(*(++pold))) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + for (i = 0; *pold >= '0' && *pold <= '7'; pold++) { + i = (i * 8) + (*pold - '0'); + } + pold--; + D_MENUBAR(("Octal number evaluates to %d\n", i)); + *pnew = i; + break; + case 'n': + *pnew = '\n'; + break; + case 'r': + *pnew = '\r'; + break; + case 't': + *pnew = '\t'; + break; + case 'b': + *pnew = '\b'; + break; + case 'f': + *pnew = '\f'; + break; + case 'a': + *pnew = '\a'; + break; + case 'v': + *pnew = '\v'; + break; + case 'e': + *pnew = '\033'; + break; + case 'c': + pold++; + *pnew = MAKE_CTRL_CHAR(*pold); + break; + default: + *pnew = *pold; + break; + } + break; + case '^': + D_MENUBAR(("Caret + %c\n", *(pold + 1))); + pold++; + *pnew = MAKE_CTRL_CHAR(*pold); + break; + default: + *pnew = *pold; + } + } + + if (!BEG_STRCASECMP(str, "\033x") && *(pnew - 1) != '\r') { + D_MENUBAR(("Adding carriage return\n")); + *(pnew++) = '\r'; + } else if (!BEG_STRCASECMP(str, "\0\e]") && *(pnew - 1) != '\a') { + D_MENUBAR(("Adding bell character\n")); + *(pnew++) = '\a'; + } + *pnew = 0; + +#if DEBUG >= DEBUG_MENU + if (debug_level >= DEBUG_MENU) { + D_MENUBAR(("New value is:\n\n")); + HexDump(str, (size_t) (pnew - str)); + } +#endif + + return (pnew - str); +} + +const char * +find_file(const char *file, const char *ext) +{ + + const char *f; + +#if defined(PIXMAP_SUPPORT) || (MENUBAR_MAX) + if ((f = search_path(rs_path, file, ext)) != NULL) { + return (f); + } else +# ifdef PATH_ENV + if ((f = search_path(getenv(PATH_ENV), file, ext)) != NULL) { + return (f); + } else +# endif + if ((f = search_path(getenv("PATH"), file, ext)) != NULL) { + return (f); + } else { + return (search_path(initial_dir, file, ext)); + } +#else + return ((const char *) NULL); +#endif + +} + +/*----------------------------------------------------------------------* + * miscellaneous drawing routines + */ + +/* + * draw bottomShadow/highlight along top/left sides of the window + */ +void +Draw_tl(Window win, GC gc, int x, int y, int w, int h) +{ + + int shadow = SHADOW; + + if (w == 0 || h == 0) { + shadow = 1; + } + w += (x - 1); + h += (y - 1); + + for (; shadow > 0; shadow--, x++, y++, w--, h--) { + XDrawLine(Xdisplay, win, gc, x, y, w, y); + XDrawLine(Xdisplay, win, gc, x, y, x, h); + } +} + +/* + * draw bottomShadow/highlight along the bottom/right sides of the window + */ +void +Draw_br(Window win, GC gc, int x, int y, int w, int h) +{ + + int shadow = SHADOW; + + if (w == 0 || h == 0) { + shadow = 1; + } + w += (x - 1); + h += (y - 1); + x++; + y++; + + for (; shadow > 0; shadow--, x++, y++, w--, h--) { + XDrawLine(Xdisplay, win, gc, w, h, w, y); + XDrawLine(Xdisplay, win, gc, w, h, x, h); + } +} + +void +Draw_Shadow(Window win, GC topShadow, GC botShadow, int x, int y, int w, int h) +{ + + Draw_tl(win, topShadow, x, y, w, h); + Draw_br(win, botShadow, x, y, w, h); +} + +/* button shapes */ +void +Draw_Triangle(Window win, GC topShadow, GC botShadow, int x, int y, int w, int type) +{ + switch (type) { + case 'r': /* right triangle */ + XDrawLine(Xdisplay, win, topShadow, x, y, x, y + w); + XDrawLine(Xdisplay, win, topShadow, x, y, x + w, y + w / 2); + XDrawLine(Xdisplay, win, botShadow, x, y + w, x + w, y + w / 2); + break; + + case 'l': /* left triangle */ + XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x + w, y); + XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x, y + w / 2); + XDrawLine(Xdisplay, win, topShadow, x, y + w / 2, x + w, y); + break; + + case 'd': /* down triangle */ + XDrawLine(Xdisplay, win, topShadow, x, y, x + w / 2, y + w); + XDrawLine(Xdisplay, win, topShadow, x, y, x + w, y); + XDrawLine(Xdisplay, win, botShadow, x + w, y, x + w / 2, y + w); + break; + + case 'u': /* up triangle */ + XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x + w / 2, y); + XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x, y + w); + XDrawLine(Xdisplay, win, topShadow, x, y + w, x + w / 2, y); + break; +#if 0 + case 's': /* square */ + XDrawLine(Xdisplay, win, topShadow, x + w, y, x, y); + XDrawLine(Xdisplay, win, topShadow, x, y, x, y + w); + XDrawLine(Xdisplay, win, botShadow, x, y + w, x + w, y + w); + XDrawLine(Xdisplay, win, botShadow, x + w, y + w, x + w, y); + break; +#endif + } +} +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/misc.h b/src/misc.h new file mode 100644 index 0000000..fb58a3f --- /dev/null +++ b/src/misc.h @@ -0,0 +1,38 @@ +/*--------------------------------*-C-*---------------------------------* + * File: misc.h + * + * miscellaneous service routines + * + * Copyright 1996,97 + * mj olesen Queen's Univ at Kingston + * + * You can do what you like with this source code provided you don't make + * money from it and you include an unaltered copy of this message + * (including the copyright). As usual, the author accepts no + * responsibility for anything, nor does he guarantee anything whatsoever. + *----------------------------------------------------------------------*/ + +#ifndef _MISC_H_ +#define _MISC_H_ +#include + +/* prototypes */ +_XFUNCPROTOBEGIN + +const char *my_basename(const char *str); +void print_error(const char *fmt,...); +void print_warning(const char *fmt,...); +void fatal_error(const char *fmt,...); +unsigned long str_leading_match(register const char *, register const char *); +char *str_trim(char *str); +int parse_escaped_string(char *str); +const char *search_path(const char *pathlist, const char *file, const char *ext); +const char *find_file(const char *file, const char *ext); +void Draw_tl(Window win, GC gc, int x, int y, int w, int h); +void Draw_br(Window win, GC gc, int x, int y, int w, int h); +void Draw_Shadow(Window win, GC topShadow, GC botShadow, int x, int y, int w, int h); +void Draw_Triangle(Window win, GC topShadow, GC botShadow, int x, int y, int w, int type); + +_XFUNCPROTOEND + +#endif /* whole file */ diff --git a/src/netdisp.c b/src/netdisp.c new file mode 100644 index 0000000..a3a8d18 --- /dev/null +++ b/src/netdisp.c @@ -0,0 +1,148 @@ +/*--------------------------------*-C-*---------------------------------* + * File: netdisp.c + */ +/*{{{ notes: */ +/*----------------------------------------------------------------------* + * support for resolving the actual IP number of the host for remote + * DISPLAYs. When the display is local (i.e. :0), we add support for + * sending the first non-loopback interface IP number as the DISPLAY + * instead of just sending the incorrect ":0". This way telnet/rlogin + * shells can actually get the correct information into DISPLAY for + * xclients. + * + * Copyright 1996 Chuck Blake + * ++ * Cleaned up somewhat by mj olesen ++ * + * You can do what you like with this source code as long as you don't try + * to make money out of it and you include an unaltered copy of this + * message (including the copyright). + * + * As usual, the author accepts no responsibility for anything, nor does + * he guarantee anything whatsoever. + *----------------------------------------------------------------------*/ + +static const char cvs_ident[] = "$Id$"; + +#include "config.h" +#include "feature.h" +#include "main.h" + +/* Put in a dummy routine if this is disabled, inline it if possible */ +#ifndef DISPLAY_IS_IP +inline const char * +network_display(const char *display) +{ + return (display); +} +#else +/*{{{ includes */ +#include +#include +#include +#include +#include +#ifdef HAVE_FCNTL_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +/* On Solaris link with -lsocket and -lnsl */ +#include +#include + +/* these next two are probably only on Sun (not Solaris) */ +#ifdef HAVE_SYS_SOCKIO_H +# include +#endif +#ifdef HAVE_SYS_BYTEORDER_H +# include +#endif + +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#ifdef HAVE_SYS_IOCTL_H +# include +#endif + +#include +#include +#include +#include + +/*----------------------------------------------------------------------*/ +/* return a pointer to a static buffer */ +char * +network_display(const char *display) +{ + + static char ipaddress[32] = ""; + char buffer[1024], *rval = NULL; + struct ifconf ifc; + struct ifreq *ifr; + int i, skfd; + + if (display[0] != ':' && strncmp(display, "unix:", 5)) + return display; /* nothing to do */ + + ifc.ifc_len = sizeof(buffer); /* Get names of all ifaces */ + ifc.ifc_buf = buffer; + + if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + return NULL; + } + if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) { + perror("SIOCGIFCONF"); + close(skfd); + return NULL; + } + for (i = 0, ifr = ifc.ifc_req; i < (ifc.ifc_len / sizeof(struct ifreq)); i++, ifr++) { + + struct ifreq ifr2; + + strcpy(ifr2.ifr_name, ifr->ifr_name); + if (ioctl(skfd, SIOCGIFADDR, &ifr2) >= 0) { + unsigned long addr; + struct sockaddr_in *p_addr; + + p_addr = (struct sockaddr_in *) &(ifr2.ifr_addr); + addr = htonl((unsigned long) p_addr->sin_addr.s_addr); + + /* + * not "0.0.0.0" or "127.0.0.1" - so format the address + */ + if (addr && addr != 0x7F000001) { + char *colon = strchr(display, ':'); + + if (colon == NULL) + colon = ":0.0"; + + sprintf(ipaddress, "%d.%d.%d.%d%s", + (int) ((addr >> 030) & 0xFF), + (int) ((addr >> 020) & 0xFF), + (int) ((addr >> 010) & 0xFF), + (int) (addr & 0xFF), colon); + + rval = ipaddress; + break; + } + } + } + + close(skfd); + return rval; +} +#endif /* DISPLAY_IS_IP */ +/*----------------------- end-of-file (C source) -----------------------*/ diff --git a/src/options.c b/src/options.c new file mode 100644 index 0000000..96cfa2c --- /dev/null +++ b/src/options.c @@ -0,0 +1,3637 @@ +/* options.c -- Eterm options module + * -- 25 July 1997, mej + * + * This file is original work by Michael Jennings and + * Tuomo Venalainen . This file, and any other file + * bearing this same message or a similar one, is distributed under + * the GNU Public License (GPL) as outlined in the COPYING file. + * + * Copyright (C) 1997, Michael Jennings and Tuomo Venalainen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +static const char cvs_ident[] = "$Id$"; + +#include "main.h" +#include "feature.h" + +#include +#include +#include +#include +#include +#include +#include +#include "../libmej/debug.h" +#include "../libmej/strings.h" +#include "debug.h" +#include "mem.h" +#include "strings.h" +#include "command.h" +#include "grkelot.h" +#include "menubar.h" +#include "options.h" +#include "pixmap.h" +#include "scrollbar.h" +#include "screen.h" +#include "system.h" + +#if PATH_MAX < 1024 +# undef PATH_MAX +# define PATH_MAX 1024 +#endif + +const char *true_vals[] = +{"1", "on", "true", "yes"}; +const char *false_vals[] = +{"0", "off", "false", "no"}; + +char **rs_execArgs = NULL; /* Args to exec (-e or --exec) */ +char *rs_title = NULL; /* Window title */ +char *rs_iconName = NULL; /* Icon name */ +char *rs_geometry = NULL; /* Geometry string */ +int rs_desktop = -1; +char *rs_path = NULL; +int rs_saveLines = SAVELINES; /* Lines in the scrollback buffer */ + +#ifdef KEYSYM_ATTRIBUTE +unsigned char *KeySym_map[256]; /* probably mostly empty */ + +#endif +#if defined (HOTKEY_CTRL) || defined (HOTKEY_META) +/* recognized when combined with HOTKEY */ +KeySym ks_bigfont = XK_greater; +KeySym ks_smallfont = XK_less; + +#endif +#ifdef PIXMAP_SUPPORT +char *rs_pixmapScale = NULL; +const char *rs_saveUnder = NULL; +char *rs_icon = NULL; + +# ifdef BACKGROUND_CYCLING_SUPPORT +char *rs_anim_pixmap_list = NULL; +char **rs_anim_pixmaps = NULL; +time_t rs_anim_delay = 0; + +# endif +# ifdef PIXMAP_OFFSET +char *rs_viewport_mode = NULL; +const char *rs_pixmapTrans = NULL; +unsigned long rs_tintMask = 0xffffff; +unsigned int rs_shadePct = 0; + +# ifdef WATCH_DESKTOP_OPTION +const char *rs_watchDesktop = NULL; + +# endif +# endif +char *rs_pixmaps[11] = +{NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL}; + +#endif +char *rs_noCursor = NULL; + +#ifdef USE_THEMES +char *rs_theme = NULL; +char *rs_config_file = NULL; + +#endif + +/* local functions referenced */ +char *chomp(char *); +void parse_main(char *); +void parse_color(char *); +void parse_attributes(char *); +void parse_toggles(char *); +void parse_keyboard(char *); +void parse_misc(char *); +void parse_pixmaps(char *); +void parse_kanji(char *); +void parse_undef(char *); +char *builtin_random(char *); +char *builtin_exec(char *); +char *builtin_version(char *); +char *builtin_appname(char *); + +/* local variables */ +const char *rs_loginShell = NULL; +const char *rs_utmpLogging = NULL; +const char *rs_scrollBar = NULL; + +#if (MENUBAR_MAX) +const char *rs_menubar = NULL; + +#endif +const char *rs_app_keypad = NULL; +const char *rs_app_cursor = NULL; +const char *rs_homeOnEcho = NULL; +const char *rs_homeOnInput = NULL; +const char *rs_homeOnRefresh = NULL; +const char *rs_scrollBar_right = NULL; +const char *rs_scrollBar_floating = NULL; +const char *rs_scrollbar_popup = NULL; +const char *rs_borderless = NULL; +const char *rs_pause = NULL; +const char *rs_xterm_select = NULL; +const char *rs_select_whole_line = NULL; +const char *rs_select_trailing_spaces = NULL; +unsigned short rs_min_anchor_size = 0; + +char *rs_scrollbar_type = NULL; +unsigned long rs_scrollbar_width = 0; +const char *rs_term_name = NULL; + +#if MENUBAR_MAX +const char *rs_menubar_move = NULL; +const char *rs_menu = NULL; + +#endif + +#if defined (HOTKEY_CTRL) || defined (HOTKEY_META) +static char *rs_bigfont_key = NULL; +static char *rs_smallfont_key = NULL; + +#endif + +#ifndef NO_MAPALERT +# ifdef MAPALERT_OPTION +static const char *rs_mapAlert = NULL; + +# endif +#endif +static const char *rs_visualBell = NULL; +static const char *rs_reverseVideo = NULL; + +#ifdef META8_OPTION +static const char *rs_meta8 = NULL; + +#endif +#ifdef KANJI +static char *rs_kanji_encoding = NULL; + +#endif +#ifdef GREEK_SUPPORT +static char *rs_greek_keyboard = NULL; + +#endif + +extern char initial_dir[PATH_MAX + 1]; + +/* Options structure */ + +#define OPT_BOOLEAN 0x0001 +#define OPT_INTEGER 0x0002 +#define OPT_STRING 0x0004 +#define OPT_ARGUMENT 0x0008 + +#define OPT_STR(s, l, d, p) { s, l, "(str) " d, OPT_STRING, (const char **) p, 0, 0 } +#define OPT_INT(s, l, d, p) { s, l, "(int) " d, OPT_INTEGER, (const int *) p, 0, 0 } +#define OPT_BOOL(s, l, d, p, v, m) { s, l, "(bool) " d, OPT_BOOLEAN, (const int *) p, v, m } +#define OPT_LONG(l, d, p) { 0, l, "(str) " d, OPT_STRING, (const char **) p, 0, 0 } +#define OPT_ARGS(s, l, d, p) { s, l, "(str) " d, OPT_ARGUMENT, (const char ***) p, 0, 0 } +#define OPT_BLONG(l, d, p, v, m) { 0, l, "(bool) " d, OPT_BOOLEAN, (const int *) p, v, m } +#define OPT_ILONG(l, d, p) { 0, l, "(int) " d, OPT_INTEGER, (const int *) p, 0, 0 } +#define optList_numoptions() (sizeof(optList)/sizeof(optList[0])) + +static const struct { + char short_opt; + char *long_opt; + const char *const description; + unsigned short flag; + const void *pval; + unsigned long *maskvar; + int mask; +} optList[] = { + +#ifdef USE_THEMES /* These two MUST be first! */ + OPT_STR('t', "theme", "select a theme", &rs_theme), + OPT_STR('X', "config-file", "choose an alternate config file", &rs_config_file), +#endif /* USE_THEMES */ + OPT_BOOL('h', "help", "display usage information", NULL, NULL, 0), + OPT_BLONG("version", "display version and configuration information", NULL, NULL, 0), +#if DEBUG <= 0 + OPT_ILONG("debug", "level of debugging information to show (support not compiled in)", &debug_level), +#elif DEBUG == 1 + OPT_ILONG("debug", "level of debugging information to show (0-1)", &debug_level), +#elif DEBUG == 2 + OPT_ILONG("debug", "level of debugging information to show (0-2)", &debug_level), +#elif DEBUG == 3 + OPT_ILONG("debug", "level of debugging information to show (0-3)", &debug_level), +#elif DEBUG == 4 + OPT_ILONG("debug", "level of debugging information to show (0-4)", &debug_level), +#else + OPT_ILONG("debug", "level of debugging information to show (0-5)", &debug_level), +#endif + +/* =======[ Color options ]======= */ + OPT_BOOL('r', "reverse-video", "reverse video", &rs_reverseVideo, &Options, Opt_reverseVideo), + OPT_STR('b', "background-color", "background color", &rs_color[bgColor]), + OPT_STR('f', "foreground-color", "foreground color", &rs_color[fgColor]), + OPT_LONG("color0", "color 0", &rs_color[minColor]), + OPT_LONG("color1", "color 1", &rs_color[minColor + 1]), + OPT_LONG("color2", "color 2", &rs_color[minColor + 2]), + OPT_LONG("color3", "color 3", &rs_color[minColor + 3]), + OPT_LONG("color4", "color 4", &rs_color[minColor + 4]), + OPT_LONG("color5", "color 5", &rs_color[minColor + 5]), + OPT_LONG("color6", "color 6", &rs_color[minColor + 6]), + OPT_LONG("color7", "color 7", &rs_color[minColor + 7]), +#ifndef NO_BRIGHTCOLOR + OPT_LONG("color8", "color 8", &rs_color[minBright]), + OPT_LONG("color9", "color 9", &rs_color[minBright + 1]), + OPT_LONG("color10", "color 10", &rs_color[minBright + 2]), + OPT_LONG("color11", "color 11", &rs_color[minBright + 3]), + OPT_LONG("color12", "color 12", &rs_color[minBright + 4]), + OPT_LONG("color13", "color 13", &rs_color[minBright + 5]), + OPT_LONG("color14", "color 14", &rs_color[minBright + 6]), + OPT_LONG("color15", "color 15", &rs_color[minBright + 7]), +#endif /* NO_BRIGHTCOLOR */ +#ifndef NO_BOLDUNDERLINE + OPT_LONG("colorBD", "bold color", &rs_color[colorBD]), + OPT_LONG("colorUL", "underline color", &rs_color[colorUL]), +#endif /* NO_BOLDUNDERLINE */ + OPT_LONG("menu-text-color", "menu text color", &rs_color[menuTextColor]), +#ifdef KEEP_SCROLLCOLOR + OPT_STR('S', "scrollbar-color", "scrollbar color", &rs_color[scrollColor]), +# ifdef CHANGE_SCROLLCOLOR_ON_FOCUS + OPT_LONG("unfocused-scrollbar-color", "unfocused scrollbar color", &rs_color[unfocusedScrollColor]), +# endif +#endif /* KEEP_SCROLLCOLOR */ + OPT_LONG("pointer-color", "mouse pointer color", &rs_color[pointerColor]), +#ifndef NO_CURSORCOLOR + OPT_STR('c', "cursor-color", "cursor color", &rs_color[cursorColor]), + OPT_LONG("cursor-text-color", "cursor text color", &rs_color[cursorColor2]), +#endif /* NO_CURSORCOLOR */ + +/* =======[ X11 options ]======= */ + OPT_STR('d', "display", "X server to connect to", &display_name), + OPT_STR('g', "geometry", "WxH+X+Y = size and position", &rs_geometry), + OPT_BOOL('i', "iconic", "start iconified", NULL, &Options, Opt_iconic), + OPT_STR('n', "name", "client instance, icon, and title strings", &rs_name), + OPT_STR('T', "title", "title string", &rs_title), + OPT_LONG("icon-name", "icon name", &rs_iconName), + OPT_STR('B', "scrollbar-type", "choose the scrollbar type (motif, next, xterm)", &rs_scrollbar_type), + OPT_ILONG("scrollbar-width", "choose the width (in pixels) of the scrollbar", &rs_scrollbar_width), + OPT_INT('D', "desktop", "desktop to start on (requires GNOME-compliant window manager)", &rs_desktop), +#ifndef NO_BOLDFONT + OPT_LONG("bold-font", "bold text font", &rs_boldFont), +#endif + OPT_STR('F', "font", "normal text font", &rs_font[0]), + OPT_LONG("font1", "font 1", &rs_font[1]), + OPT_LONG("font2", "font 2", &rs_font[2]), + OPT_LONG("font3", "font 3", &rs_font[3]), + OPT_LONG("font4", "font 4", &rs_font[4]), + +/* =======[ Pixmap options ]======= */ +#ifdef PIXMAP_SUPPORT + OPT_STR('P', "background-pixmap", "background pixmap [scaling optional]", &rs_pixmaps[pixmap_bg]), + OPT_STR('I', "icon", "icon pixmap", &rs_icon), + OPT_LONG("up-arrow-pixmap", "up arrow pixmap [scaling optional]", &rs_pixmaps[pixmap_up]), + OPT_LONG("down-arrow-pixmap", "down arrow pixmap [scaling optional]", &rs_pixmaps[pixmap_dn]), + OPT_LONG("trough-pixmap", "scrollbar background (trough) pixmap [scaling optional]", &rs_pixmaps[pixmap_sb]), + OPT_LONG("anchor-pixmap", "scrollbar anchor pixmap [scaling optional]", &rs_pixmaps[pixmap_sa]), + OPT_BOOL('@', "scale", "scale rather than tile", &rs_pixmapScale, &Options, Opt_pixmapScale), +# ifdef PIXMAP_OFFSET +# ifdef WATCH_DESKTOP_OPTION + OPT_BOOL('W', "watch-desktop", "watch the desktop background image for changes", &rs_watchDesktop, &Options, Opt_watchDesktop), +# endif + OPT_BOOL('O', "trans", "creates a pseudo-transparent Eterm", &rs_pixmapTrans, &Options, Opt_pixmapTrans), + OPT_ILONG("shade", "percentage to shade the background in a pseudo-transparent Eterm", &rs_shadePct), + OPT_ILONG("tint", "RGB brightness mask for color tinting in a pseudo-transparent Eterm", &rs_tintMask), +# endif + OPT_STR('p', "path", "pixmap file search path", &rs_path), +# ifdef BACKGROUND_CYCLING_SUPPORT + OPT_STR('N', "anim", "a delay and list of pixmaps for cycling", &rs_anim_pixmap_list), +# endif /* BACKGROUND_CYCLING_SUPPORT */ +#endif /* PIXMAP_SUPPORT */ + +/* =======[ Kanji options ]======= */ +#ifdef KANJI + OPT_STR('K', "kanji-font", "normal text kanji font", &rs_kfont[0]), + OPT_LONG("kanji-font1", "kanji font 1", &rs_kfont[1]), + OPT_LONG("kanji-font2", "kanji font 2", &rs_kfont[2]), + OPT_LONG("kanji-font3", "kanji font 3", &rs_kfont[3]), + OPT_LONG("kanji-font4", "kanji font 4", &rs_kfont[4]), + OPT_LONG("kanji-encoding", "kanji encoding mode (eucj or sjis)", &rs_kanji_encoding), +#endif /* KANJI */ + +/* =======[ Toggles ]======= */ + OPT_BOOL('l', "login-shell", "login shell, prepend - to shell name", &rs_loginShell, &Options, Opt_loginShell), + OPT_BOOL('s', "scrollbar", "display scrollbar", &rs_scrollBar, &Options, Opt_scrollBar), + OPT_BLONG("menubar", "display menubar", &rs_menubar, NULL, 0), + OPT_BOOL('u', "utmp-logging", "make a utmp entry", &rs_utmpLogging, &Options, Opt_utmpLogging), + OPT_BOOL('v', "visual-bell", "visual bell", &rs_visualBell, &Options, Opt_visualBell), + OPT_BOOL('H', "home-on-echo", "jump to bottom on output", &rs_homeOnEcho, &Options, Opt_homeOnEcho), + OPT_BLONG("home-on-input", "jump to bottom on input", &rs_homeOnInput, &Options, Opt_homeOnInput), + OPT_BOOL('E', "home-on-refresh", "jump to bottom on refresh (^L)", &rs_homeOnRefresh, &Options, Opt_homeOnRefresh), + OPT_BLONG("scrollbar-right", "display the scrollbar on the right", &rs_scrollBar_right, &Options, Opt_scrollBar_right), + OPT_BLONG("scrollbar-floating", "display the scrollbar with no trough", &rs_scrollBar_floating, &Options, Opt_scrollBar_floating), + OPT_BLONG("scrollbar-popup", "popup the scrollbar only when focused", &rs_scrollbar_popup, &Options, Opt_scrollbar_popup), + OPT_BOOL('x', "borderless", "force Eterm to have no borders", &rs_borderless, &Options, Opt_borderless), +#ifndef NO_MAPALERT +# ifdef MAPALERT_OPTION + OPT_BOOL('m', "map-alert", "uniconify on beep", &rs_mapAlert, &Options, Opt_mapAlert), +# endif +#endif +#ifdef META8_OPTION + OPT_BOOL('8', "meta-8", "Meta key toggles 8-bit", &rs_meta8, &Options, Opt_meta8), +#endif +#ifdef BACKING_STORE + OPT_BLONG("save-under", "use backing store", &rs_saveUnder, &Options, Opt_saveUnder), +#endif + OPT_BLONG("no-cursor", "disable the text cursor", &rs_noCursor, &Options, Opt_noCursor), +#if MENUBAR_MAX + OPT_BOOL('V', "menubar-move", "dragging the menubar will move the window", &rs_menubar_move, &Options, Opt_menubar_move), +#endif + OPT_BLONG("pause", "pause for a keypress after the child process exits", &rs_pause, &Options, Opt_pause), + OPT_BLONG("xterm-select", "duplicate xterm's broken selection behavior", &rs_xterm_select, &Options, Opt_xterm_select), + OPT_BLONG("select-line", "triple-click selects whole line", &rs_select_whole_line, &Options, Opt_select_whole_line), + OPT_BLONG("select-trailing-spaces", "do not skip trailing spaces when selecting", &rs_select_trailing_spaces, &Options, Opt_select_trailing_spaces), +#ifdef PIXMAP_OFFSET + OPT_BLONG("viewport-mode", "use viewport mode for the background image", &rs_viewport_mode, &Options, Opt_viewport_mode), +#endif + +/* =======[ Keyboard options ]======= */ +#if defined (HOTKEY_CTRL) || defined (HOTKEY_META) + OPT_LONG("big-font-key", "keysym for font size increase", &rs_bigfont_key), + OPT_LONG("small-font-key", "keysym for font size decrease", &rs_smallfont_key), +#endif +#ifdef GREEK_SUPPORT + OPT_LONG("greek-keyboard", "greek keyboard mapping (iso or ibm)", &rs_greek_keyboard), +#endif + OPT_BLONG("app-keypad", "application keypad mode", &rs_app_keypad, &PrivateModes, PrivMode_aplKP), + OPT_BLONG("app-cursor", "application cursor key mode", &rs_app_cursor, &PrivateModes, PrivMode_aplCUR), + +/* =======[ Misc options ]======= */ + OPT_INT('L', "save-lines", "lines to save in scrollback buffer", &rs_saveLines), + OPT_INT('a', "min-anchor-size", "minimum size of the scrollbar anchor", &rs_min_anchor_size), +#ifdef BORDER_WIDTH_OPTION + OPT_INT('w', "border-width", "term window border width", &(TermWin.internalBorder)), +#endif +#ifdef PRINTPIPE + OPT_LONG("print-pipe", "print command", &rs_print_pipe), +#endif +#ifdef CUTCHAR_OPTION + OPT_LONG("cut-chars", "seperators for double-click selection", &rs_cutchars), +#endif /* CUTCHAR_OPTION */ +#if MENUBAR_MAX + OPT_STR('M', "menu", "Default menubar file", &rs_menu), +#endif + OPT_LONG("term-name", "value to use for setting $TERM", &rs_term_name), + OPT_BOOL('C', "console", "grab console messages", NULL, &Options, Opt_console), + OPT_ARGS('e', "exec", "execute a command rather than a shell", &rs_execArgs) +}; + +/* Print usage information */ +#define INDENT "5" +static void +usage(void) +{ + + int i, col; + + printf("Eterm Enlightened Terminal Emulator for X Windows\n"); + printf("Copyright (c) 1997-1999, Tuomo Venalainen and Michael Jennings\n\n"); + printf("Usage for " APL_NAME " " VERSION ":\n\n"); + printf("%7s %17s %40s\n", "POSIX", "GNU", "Description"); + printf("%8s %10s %41s\n", "=======", "===============================", + "========================================="); + for (i = 0; i < optList_numoptions(); i++) { + printf("%" INDENT "s", " "); + if (optList[i].short_opt) { + printf("-%c, ", optList[i].short_opt); + } else { + printf(" "); + } + printf("--%s", optList[i].long_opt); + for (col = strlen(optList[i].long_opt); col < 30; col++) { + printf(" "); + } + printf("%s\n", optList[i].description); + } + printf("\nOption types:\n"); + printf(" (bool) -- Boolean option ('1', 'on', 'yes', or 'true' to activate, '0', 'off', 'no', or 'false' to deactivate)\n"); + printf(" (int) -- Integer option (any signed number of reasonable value, usually in decimal/octal/hex)\n"); + printf(" (str) -- String option (be sure to quote strings if needed to avoid shell expansion)\n\n"); + + printf("NOTE: Long options can be separated from their values by an equal sign ('='), or you can\n"); + printf(" pass the value as the following argument on the command line (e.g., '--scrollbar 0'\n"); + printf(" or '--scrollbar=0'). Short options must have their values passed after them on the\n"); + printf(" command line, and in the case of boolean short options, cannot have values (they\n"); + printf(" default to true) (e.g., '-F shine' or '-s').\n"); + + printf("\nPlease consult the Eterm(1) man page for more detailed\n"); + printf("information on command line options.\n\n"); + exit(EXIT_FAILURE); +} + +/* Print version and configuration information */ +static void +version(void) +{ + + int i, col; + + printf("Eterm " VERSION "\n"); + printf("Copyright (c) 1997-1999, Tuomo Venalainen and Michael Jennings\n\n"); + + printf("Debugging configuration: "); +#ifdef DEBUG + printf("DEBUG=%d", DEBUG); +#else + printf("-DEBUG"); +#endif + +#if DEBUG >= DEBUG_SCREEN + printf(" +DEBUG_SCREEN"); +#endif +#if DEBUG >= DEBUG_CMD + printf(" +DEBUG_CMD"); +#endif +#if DEBUG >= DEBUG_TTY + printf(" +DEBUG_TTY"); +#endif +#if DEBUG >= DEBUG_SELECTION + printf(" +DEBUG_SELECTION"); +#endif +#if DEBUG >= DEBUG_UTMP + printf(" +DEBUG_UTMP"); +#endif +#if DEBUG >= DEBUG_OPTIONS + printf(" +DEBUG_OPTIONS"); +#endif +#if DEBUG >= DEBUG_IMLIB + printf(" +DEBUG_IMLIB"); +#endif +#if DEBUG >= DEBUG_PIXMAP + printf(" +DEBUG_PIXMAP"); +#endif +#if DEBUG >= DEBUG_EVENTS + printf(" +DEBUG_EVENTS"); +#endif +#if DEBUG >= DEBUG_MALLOC + printf(" +DEBUG_MALLOC"); +#endif +#if DEBUG >= DEBUG_X11 + printf(" +DEBUG_X11"); +#endif +#if DEBUG >= DEBUG_SCROLLBAR + printf(" +DEBUG_SCROLLBAR"); +#endif +#if DEBUG >= DEBUG_THREADS + printf(" +DEBUG_THREADS"); +#endif +#if DEBUG >= DEBUG_TAGS + printf(" +DEBUG_TAGS"); +#endif +#if DEBUG >= DEBUG_MENU + printf(" +DEBUG_MENU"); +#endif +#if DEBUG >= DEBUG_TTYMODE + printf(" +DEBUG_TTYMODE"); +#endif +#if DEBUG >= DEBUG_COLORS + printf(" +DEBUG_COLORS"); +#endif +#if DEBUG >= DEBUG_MENUARROWS + printf(" +DEBUG_MENUARROWS"); +#endif +#if DEBUG >= DEBUG_MENU_LAYOUT + printf(" +DEBUG_MENU_LAYOUT"); +#endif +#if DEBUG >= DEBUG_MENUBAR_STACKING + printf(" +DEBUG_MENUBAR_STACKING"); +#endif +#if DEBUG >= DEBUG_X + printf(" +DEBUG_X"); +#endif + + printf("\n\nCompile-time toggles: "); + +#ifdef PROFILE + printf(" +PROFILE"); +#else + printf(" -PROFILE"); +#endif +#ifdef PROFILE_SCREEN + printf(" +PROFILE_SCREEN"); +#else + printf(" -PROFILE_SCREEN"); +#endif +#ifdef PROFILE_X_EVENTS + printf(" +PROFILE_X_EVENTS"); +#else + printf(" -PROFILE_X_EVENTS"); +#endif +#ifdef COUNT_X_EVENTS + printf(" +COUNT_X_EVENTS"); +#else + printf(" -COUNT_X_EVENTS"); +#endif +#ifdef USE_ACTIVE_TAGS + printf(" +USE_ACTIVE_TAGS"); +#else + printf(" -USE_ACTIVE_TAGS"); +#endif +#ifdef OPTIMIZE_HACKS + printf(" +OPTIMIZE_HACKS"); +#else + printf(" -OPTIMIZE_HACKS"); +#endif +#ifdef PIXMAP_SUPPORT + printf(" +PIXMAP_SUPPORT"); +#else + printf(" -PIXMAP_SUPPORT"); +#endif +#ifdef USE_POSIX_THREADS + printf(" +USE_POSIX_THREADS"); +#else + printf(" -USE_POSIX_THREADS"); +#endif +#ifdef MUTEX_SYNCH + printf(" +MUTEX_SYNCH"); +#else + printf(" -MUTEX_SYNCH"); +#endif +#ifdef PIXMAP_OFFSET + printf(" +PIXMAP_OFFSET"); +#else + printf(" -PIXMAP_OFFSET"); +#endif +#ifdef IMLIB_TRANS + printf(" +IMLIB_TRANS"); +#else + printf(" -IMLIB_TRANS"); +#endif +#ifdef BACKGROUND_CYCLING_SUPPORT + printf(" +BACKGROUND_CYCLING_SUPPORT"); +#else + printf(" -BACKGROUND_CYCLING_SUPPORT"); +#endif +#ifdef PIXMAP_SCROLLBAR + printf(" +PIXMAP_SCROLLBAR"); +#else + printf(" -PIXMAP_SCROLLBAR"); +#endif +#ifdef PIXMAP_MENUBAR + printf(" +PIXMAP_MENUBAR"); +#else + printf(" -PIXMAP_MENUBAR"); +#endif +#ifdef BACKING_STORE + printf(" +BACKING_STORE"); +#else + printf(" -BACKING_STORE"); +#endif +#ifdef USE_IMLIB +# ifdef OLD_IMLIB + printf(" +USE_IMLIB (OLD_IMLIB)"); +# elif defined(NEW_IMLIB) + printf(" +USE_IMLIB (NEW_IMLIB)"); +# endif +#else + printf(" -USE_IMLIB"); +#endif +#ifdef USE_THEMES + printf(" +USE_THEMES"); +#else + printf(" -USE_THEMES"); +#endif +#ifdef USE_EFFECTS + printf(" +USE_EFFECTS"); +#else + printf(" -USE_EFFECTS"); +#endif +#ifdef WATCH_DESKTOP_OPTION + printf(" +WATCH_DESKTOP_OPTION"); +#else + printf(" -WATCH_DESKTOP_OPTION"); +#endif +#ifdef NO_CURSORCOLOR + printf(" +NO_CURSORCOLOR"); +#else + printf(" -NO_CURSORCOLOR"); +#endif +#ifdef NO_BRIGHTCOLOR + printf(" +NO_BRIGHTCOLOR"); +#else + printf(" -NO_BRIGHTCOLOR"); +#endif +#ifdef NO_BOLDUNDERLINE + printf(" +NO_BOLDUNDERLINE"); +#else + printf(" -NO_BOLDUNDERLINE"); +#endif +#ifdef NO_BOLDOVERSTRIKE + printf(" +NO_BOLDOVERSTRIKE"); +#else + printf(" -NO_BOLDOVERSTRIKE"); +#endif +#ifdef NO_BOLDFONT + printf(" +NO_BOLDFONT"); +#else + printf(" -NO_BOLDFONT"); +#endif +#ifdef NO_SECONDARY_SCREEN + printf(" +NO_SECONDARY_SCREEN"); +#else + printf(" -NO_SECONDARY_SCREEN"); +#endif +#ifdef FORCE_CLEAR_CHARS + printf(" +FORCE_CLEAR_CHARS"); +#else + printf(" -FORCE_CLEAR_CHARS"); +#endif +#ifdef RXVT_GRAPHICS + printf(" +RXVT_GRAPHICS"); +#else + printf(" -RXVT_GRAPHICS"); +#endif +#ifdef PREFER_24BIT + printf(" +PREFER_24BIT"); +#else + printf(" -PREFER_24BIT"); +#endif +#ifdef OFFIX_DND + printf(" +OFFIX_DND"); +#else + printf(" -OFFIX_DND"); +#endif +#ifdef BORDER_WIDTH_OPTION + printf(" +BORDER_WIDTH_OPTION"); +#else + printf(" -BORDER_WIDTH_OPTION"); +#endif +#ifdef NO_DELETE_KEY + printf(" +NO_DELETE_KEY"); +#else + printf(" -NO_DELETE_KEY"); +#endif +#ifdef FORCE_BACKSPACE + printf(" +FORCE_BACKSPACE"); +#else + printf(" -FORCE_BACKSPACE"); +#endif +#ifdef FORCE_DELETE + printf(" +FORCE_DELETE"); +#else + printf(" -FORCE_DELETE"); +#endif +#ifdef HOTKEY_CTRL + printf(" +HOTKEY_CTRL"); +#else + printf(" -HOTKEY_CTRL"); +#endif +#ifdef HOTKEY_META + printf(" +HOTKEY_META"); +#else + printf(" -HOTKEY_META"); +#endif +#ifdef LINUX_KEYS + printf(" +LINUX_KEYS"); +#else + printf(" -LINUX_KEYS"); +#endif +#ifdef KEYSYM_ATTRIBUTE + printf(" +KEYSYM_ATTRIBUTE"); +#else + printf(" -KEYSYM_ATTRIBUTE"); +#endif +#ifdef NO_XLOCALE + printf(" +NO_XLOCALE"); +#else + printf(" -NO_XLOCALE"); +#endif +#ifdef UNSHIFTED_SCROLLKEYS + printf(" +UNSHIFTED_SCROLLKEYS"); +#else + printf(" -UNSHIFTED_SCROLLKEYS"); +#endif +#ifdef NO_SCROLLBAR_REPORT + printf(" +NO_SCROLLBAR_REPORT"); +#else + printf(" -NO_SCROLLBAR_REPORT"); +#endif +#ifdef CUTCHAR_OPTION + printf(" +CUTCHAR_OPTION"); +#else + printf(" -CUTCHAR_OPTION"); +#endif +#ifdef MOUSE_REPORT_DOUBLECLICK + printf(" +MOUSE_REPORT_DOUBLECLICK"); +#else + printf(" -MOUSE_REPORT_DOUBLECLICK"); +#endif +#ifdef XTERM_SCROLLBAR + printf(" +XTERM_SCROLLBAR"); +#else + printf(" -XTERM_SCROLLBAR"); +#endif +#ifdef MOTIF_SCROLLBAR + printf(" +MOTIF_SCROLLBAR"); +#else + printf(" -MOTIF_SCROLLBAR"); +#endif +#ifdef NEXT_SCROLLBAR + printf(" +NEXT_SCROLLBAR"); +#else + printf(" -NEXT_SCROLLBAR"); +#endif +#ifdef KEEP_SCROLLCOLOR + printf(" +KEEP_SCROLLCOLOR"); +#else + printf(" -KEEP_SCROLLCOLOR"); +#endif +#ifdef CHANGE_SCROLLCOLOR_ON_FOCUS + printf(" +CHANGE_SCROLLCOLOR_ON_FOCUS"); +#else + printf(" -CHANGE_SCROLLCOLOR_ON_FOCUS"); +#endif +#ifdef SCROLLBAR_BUTTON_CONTINUAL_SCROLLING + printf(" +SCROLLBAR_BUTTON_CONTINUAL_SCROLLING"); +#else + printf(" -SCROLLBAR_BUTTON_CONTINUAL_SCROLLING"); +#endif +#ifdef USE_SMOOTH_REFRESH + printf(" +USE_SMOOTH_REFRESH"); +#else + printf(" -USE_SMOOTH_REFRESH"); +#endif +#ifdef MENUBAR_SHADOW_IN + printf(" +MENUBAR_SHADOW_IN"); +#else + printf(" -MENUBAR_SHADOW_IN"); +#endif +#ifdef MENU_SHADOW_IN + printf(" +MENU_SHADOW_IN"); +#else + printf(" -MENU_SHADOW_IN"); +#endif +#ifdef MENU_TEXT_FLOATING + printf(" +MENU_TEXT_FLOATING"); +#else + printf(" -MENU_TEXT_FLOATING"); +#endif +#ifdef CTRL_CLICK_RAISE + printf(" +CTRL_CLICK_RAISE"); +#else + printf(" -CTRL_CLICK_RAISE"); +#endif +#ifdef META8_OPTION + printf(" +META8_OPTION"); +#else + printf(" -META8_OPTION"); +#endif +#ifdef GREEK_SUPPORT + printf(" +GREEK_SUPPORT"); +#else + printf(" -GREEK_SUPPORT"); +#endif +#ifdef KANJI + printf(" +KANJI"); +#else + printf(" -KANJI"); +#endif +#ifdef DISPLAY_IS_IP + printf(" +DISPLAY_IS_IP"); +#else + printf(" -DISPLAY_IS_IP"); +#endif +#ifdef ENABLE_DISPLAY_ANSWER + printf(" +ENABLE_DISPLAY_ANSWER"); +#else + printf(" -ENABLE_DISPLAY_ANSWER"); +#endif +#ifdef NO_VT100_ANS + printf(" +NO_VT100_ANS"); +#else + printf(" -NO_VT100_ANS"); +#endif +#ifdef SMART_WINDOW_TITLE + printf(" +SMART_WINDOW_TITLE"); +#else + printf(" -SMART_WINDOW_TITLE"); +#endif +#ifdef XTERM_COLOR_CHANGE + printf(" +XTERM_COLOR_CHANGE"); +#else + printf(" -XTERM_COLOR_CHANGE"); +#endif +#ifdef DEFINE_XTERM_COLOR + printf(" +DEFINE_XTERM_COLOR"); +#else + printf(" -DEFINE_XTERM_COLOR"); +#endif +#ifdef NO_MAPALERT + printf(" +NO_MAPALERT"); +#else + printf(" -NO_MAPALERT"); +#endif +#ifdef MAPALERT_OPTION + printf(" +MAPALERT_OPTION"); +#else + printf(" -MAPALERT_OPTION"); +#endif +#ifdef ENABLE_CORE_DUMPS + printf(" +ENABLE_CORE_DUMPS"); +#else + printf(" -ENABLE_CORE_DUMPS"); +#endif +#ifdef UTMP_SUPPORT + printf(" +UTMP_SUPPORT"); +#else + printf(" -UTMP_SUPPORT"); +#endif +#ifdef HAVE_SAVED_UIDS + printf(" +HAVE_SAVED_UIDS"); +#else + printf(" -HAVE_SAVED_UIDS"); +#endif +#ifdef USE_GETGRNAME + printf(" +USE_GETGRNAME"); +#else + printf(" -USE_GETGRNAME"); +#endif +#ifdef ALLOW_BACKQUOTE_EXEC + printf(" +ALLOW_BACKQUOTE_EXEC"); +#else + printf(" -ALLOW_BACKQUOTE_EXEC"); +#endif +#ifdef WARN_OLDER + printf(" +WARN_OLDER"); +#else + printf(" -WARN_OLDER"); +#endif + + printf("\n\nCompile-time definitions:\n"); + +#ifdef PATH_ENV + printf(" PATH_ENV=\"%s\"\n", PATH_ENV); +#else + printf(" -PATH_ENV\n"); +#endif +#ifdef REFRESH_PERIOD + printf(" REFRESH_PERIOD=%d\n", REFRESH_PERIOD); +#else + printf(" -REFRESH_PERIOD\n"); +#endif +#ifdef PRINTPIPE + printf(" PRINTPIPE=\"%s\"\n", PRINTPIPE); +#else + printf(" -PRINTPIPE\n"); +#endif +#ifdef KS_DELETE + printf(" KS_DELETE=\"%s\"\n", KS_DELETE); +#else + printf(" -KS_DELETE\n"); +#endif +#ifdef SAVELINES + printf(" SAVELINES=%d\n", SAVELINES); +#else + printf(" -SAVELINES\n"); +#endif +#ifdef CUTCHARS + printf(" CUTCHARS=\"%s\"\n", CUTCHARS); +#else + printf(" -CUTCHARS\n"); +#endif +#ifdef MULTICLICK_TIME + printf(" MULTICLICK_TIME=%d\n", MULTICLICK_TIME); +#else + printf(" -MULTICLICK_TIME\n"); +#endif +#ifdef SCROLLBAR_DEFAULT_TYPE + printf(" SCROLLBAR_DEFAULT_TYPE=%d\n", SCROLLBAR_DEFAULT_TYPE); +#else + printf(" -SCROLLBAR_DEFAULT_TYPE\n"); +#endif +#ifdef SB_WIDTH + printf(" SB_WIDTH=%d\n", SB_WIDTH); +#else + printf(" -SB_WIDTH\n"); +#endif +#ifdef SCROLLBAR_INITIAL_DELAY + printf(" SCROLLBAR_INITIAL_DELAY=%d\n", SCROLLBAR_INITIAL_DELAY); +#else + printf(" -SCROLLBAR_INITIAL_DELAY\n"); +#endif +#ifdef SCROLLBAR_CONTINUOUS_DELAY + printf(" SCROLLBAR_CONTINUOUS_DELAY=%d\n", SCROLLBAR_CONTINUOUS_DELAY); +#else + printf(" -SCROLLBAR_CONTINUOUS_DELAY\n"); +#endif +#ifdef MENUBAR_MAX + printf(" MENUBAR_MAX=%d\n", MENUBAR_MAX); +#else + printf(" -MENUBAR_MAX\n"); +#endif +#ifdef ESCZ_ANSWER + printf(" ESCZ_ANSWER=\"%s\"\n", ESCZ_ANSWER); +#else + printf(" -ESCZ_ANSWER\n"); +#endif +#ifdef TTY_GRP_NAME + printf(" TTY_GRP_NAME=\"%s\"\n", TTY_GRP_NAME); +#else + printf(" -TTY_GRP_NAME\n"); +#endif +#ifdef CONFIG_SEARCH_PATH + printf(" CONFIG_SEARCH_PATH=\"%s\"\n", CONFIG_SEARCH_PATH); +#else + printf(" -CONFIG_SEARCH_PATH\n"); +#endif +#ifdef CONFIG_FILE_NAME + printf(" CONFIG_FILE_NAME=\"%s\"\n", CONFIG_FILE_NAME); +#else + printf(" -CONFIG_FILE_NAME\n"); +#endif + + printf("\n"); + exit(EXIT_SUCCESS); +} + +/* This defines how many mistakes to allow before giving up + and printing the usage -- mej */ +#define BAD_THRESHOLD 3 +#define CHECK_BAD() do { \ + if (++bad_opts >= BAD_THRESHOLD) { \ + print_error("error threshold exceeded, giving up"); \ + usage(); \ + } else { \ + print_error("attempting to continue, but performance may be unpredictable"); \ + } \ + } while(0) + +void +get_options(int argc, char *argv[]) +{ + + register unsigned long i, j, l; + unsigned char bad_opts = 0; + + for (i = 1; i < argc; i++) { + + register char *opt = argv[i]; + char *val_ptr = NULL; + unsigned char islong = 0, hasequal = 0; + + D_OPTIONS(("argv[%d] == \"%s\"\n", i, argv[i])); + + if (*opt != '-') { + print_error("unexpected argument %s -- expected option", opt); + CHECK_BAD(); + continue; + } + if (*(opt + 1) == '-') { + islong = 1; + D_OPTIONS(("Long option detected\n")); + } + if (islong) { + opt += 2; + for (j = 0; j < optList_numoptions(); j++) { + if (!strncasecmp(optList[j].long_opt, opt, (l = strlen(optList[j].long_opt))) && + (opt[l] == '=' || !opt[l])) { + D_OPTIONS(("Match found at %d: %s == %s\n", j, optList[j].long_opt, opt)); + break; + } + } + if (j == optList_numoptions()) { + print_error("unrecognized long option --%s", opt); + CHECK_BAD(); + continue; + } + /* Put option-specific warnings here -- mej */ +#if 0 /* No longer needed, since it works :) */ + if (optList[j].short_opt == 'w') { + print_error("warning: Use of the -w / --border-width option is discouraged and unsupported."); + } +#endif + + if ((val_ptr = strchr(opt, '=')) != NULL) { + *val_ptr = 0; + val_ptr++; + hasequal = 1; + } else { + if (argv[i + 1]) { + if (*argv[i + 1] != '-' || StrCaseStr(optList[j].long_opt, "font")) { + val_ptr = argv[++i]; + } + } + } + D_OPTIONS(("hasequal == %d val_ptr == %10.8p \"%s\"\n", hasequal, val_ptr, (val_ptr ? val_ptr : "(nil)"))); + if (j == 0 || j == 1) { + continue; + } + if (!(optList[j].flag & OPT_BOOLEAN) && (val_ptr == NULL)) { + print_error("long option --%s requires a%s value", opt, + (optList[j].flag & OPT_INTEGER ? "n integer" : " string")); + CHECK_BAD(); + continue; + } + if (!strcasecmp(opt, "exec")) { + D_OPTIONS(("--exec option detected\n")); + Options |= Opt_exec; + if (!hasequal) { + + register unsigned short k, len = argc - i; + + rs_execArgs = (char **) malloc(sizeof(char *) * (argc - i + 1)); + + for (k = 0; k < len; k++) { + rs_execArgs[k] = strdup(argv[k + i]); + D_OPTIONS(("rs_execArgs[%d] == %s\n", k, rs_execArgs[k])); + } + rs_execArgs[k] = (char *) NULL; + return; + } else { + + register unsigned short k; + + rs_execArgs = (char **) malloc(sizeof(char *) * (NumWords(val_ptr) + 1)); + + for (k = 0; val_ptr; k++) { + rs_execArgs[k] = Word(1, val_ptr); + val_ptr = PWord(2, val_ptr); + D_OPTIONS(("rs_execArgs[%d] == %s\n", k, rs_execArgs[k])); + } + rs_execArgs[k] = (char *) NULL; + } + } else if (!strcasecmp(opt, "help")) { + usage(); + } else if (!strcasecmp(opt, "version")) { + version(); + } else { /* It's not --exec */ + if (optList[j].flag & OPT_BOOLEAN) { /* Boolean value */ + D_OPTIONS(("Boolean option detected\n")); + if (val_ptr) { + if (BOOL_OPT_ISTRUE(val_ptr)) { + D_OPTIONS(("\"%s\" == TRUE\n", val_ptr)); + if (optList[j].maskvar) { + *(optList[j].maskvar) |= optList[j].mask; + } + if (optList[j].pval) { + *((const char **) optList[j].pval) = *true_vals; + } + } else if (BOOL_OPT_ISFALSE(val_ptr)) { + D_OPTIONS(("\"%s\" == FALSE\n", val_ptr)); + if (optList[j].maskvar) { + *(optList[j].maskvar) &= ~(optList[j].mask); + } + if (optList[j].pval) { + *((const char **) optList[j].pval) = *false_vals; + } + } else { + print_error("unrecognized boolean value \"%s\" for option --%s", + val_ptr, optList[j].long_opt); + CHECK_BAD(); + } + } else { /* No value, so force it on */ + D_OPTIONS(("Forcing option --%s to TRUE\n", opt)); + if (optList[j].maskvar) { + *(optList[j].maskvar) |= optList[j].mask; + } + if (optList[j].pval) { + *((const char **) optList[j].pval) = *true_vals; + } + } + } else if (optList[j].flag & OPT_INTEGER) { /* Integer value */ + D_OPTIONS(("Integer option detected\n")); + *((int *) optList[j].pval) = strtol(val_ptr, (char **) NULL, 0); + } else { /* String value */ + D_OPTIONS(("String option detected\n")); + if (val_ptr && optList[j].pval) { + *((const char **) optList[j].pval) = strdup(val_ptr); + } + } + } + } else { /* It's a POSIX option */ + + register unsigned short pos; + unsigned char done = 0; + + for (pos = 1; opt[pos] && !done; pos++) { + for (j = 0; j < optList_numoptions(); j++) { + if (optList[j].short_opt == opt[pos]) { + D_OPTIONS(("Match found at %d: %c == %c\n", j, optList[j].short_opt, opt[pos])); + break; + } + } + if (j == optList_numoptions()) { + print_error("unrecognized option -%c", opt[pos]); + CHECK_BAD(); + continue; + } + /* Put option-specific warnings here -- mej */ +#if 0 /* No longer needed, since it works :) */ + if (optList[j].short_opt == 'w') { + print_error("warning: Use of the -w / --border-width option is discouraged and unsupported."); + } +#endif + + if (!(optList[j].flag & OPT_BOOLEAN)) { + if (opt[pos + 1]) { + val_ptr = opt + pos + 1; + done = 1; + } else if ((val_ptr = argv[++i]) != NULL) { + done = 1; + } + D_OPTIONS(("val_ptr == %s done == %d\n", val_ptr, done)); + if (j == 0 || j == 1) { + continue; + } + if ((val_ptr == NULL) || ((*val_ptr == '-') && (optList[j].short_opt != 'F'))) { + print_error("option -%c requires a%s value", opt[pos], + (optList[j].flag & OPT_INTEGER ? "n integer" : " string")); + CHECK_BAD(); + if (val_ptr) { /* If the "arg" was actually an option, don't skip it */ + i--; + } + continue; + } + } + if (opt[pos] == 'e') { /* It's an exec */ + + register unsigned short k, len; + + D_OPTIONS(("-e option detected\n")); + Options |= Opt_exec; + + if (opt[pos + 1]) { + len = argc - i + 2; + k = i; + } else { + len = argc - i + 1; + k = i + 1; + } + D_OPTIONS(("len == %d k == %d\n", len, k)); + rs_execArgs = (char **) malloc(sizeof(char *) * len); + + if (k == i) { + rs_execArgs[0] = strdup((char *) (val_ptr)); + D_OPTIONS(("rs_execArgs[0] == %s\n", rs_execArgs[0])); + k++; + } else { + rs_execArgs[0] = strdup(argv[k - 1]); + D_OPTIONS(("rs_execArgs[0] == %s\n", rs_execArgs[0])); + } + for (; k < argc; k++) { + rs_execArgs[k - i] = strdup(argv[k]); + D_OPTIONS(("rs_execArgs[%d] == %s\n", k - i, rs_execArgs[k - i])); + } + rs_execArgs[len - 1] = (char *) NULL; + return; + } else if (opt[pos] == 'h') { + usage(); + + } else { + if (optList[j].flag & OPT_BOOLEAN) { /* Boolean value */ + D_OPTIONS(("Boolean option detected\n")); + if (optList[j].maskvar) { + *(optList[j].maskvar) |= optList[j].mask; + } + if (optList[j].pval) { + *((const char **) optList[j].pval) = *true_vals; + } + } else if (optList[j].flag & OPT_INTEGER) { /* Integer value */ + D_OPTIONS(("Integer option detected\n")); + *((int *) optList[j].pval) = strtol(val_ptr, (char **) NULL, 0); + D_OPTIONS(("Got value %d\n", *((int *) optList[j].pval))); + } else { /* String value */ + D_OPTIONS(("String option detected\n")); + if (optList[j].pval) { + *((const char **) optList[j].pval) = strdup(val_ptr); + } + } /* End if value type */ + } /* End if option type */ + } /* End if (exec or help or other) */ + } /* End if (islong) */ + } /* End main for loop */ +} + +#ifdef USE_THEMES +void +get_initial_options(int argc, char *argv[]) +{ + + register unsigned long i, j; + + for (i = 1; i < argc; i++) { + + register char *opt = argv[i]; + char *val_ptr = NULL; + unsigned char islong = 0, hasequal = 0; + + D_OPTIONS(("argv[%d] == \"%s\"\n", i, argv[i])); + + if (*opt != '-') { + continue; + } + if (*(opt + 1) == '-') { + islong = 1; + D_OPTIONS(("Long option detected\n")); + } + if (islong) { + opt += 2; + if (!BEG_STRCASECMP(opt, "theme")) { + j = 0; + } else if (!BEG_STRCASECMP(opt, "config-file")) { + j = 1; + } else + continue; + + if ((val_ptr = strchr(opt, '=')) != NULL) { + *val_ptr = 0; + val_ptr++; + hasequal = 1; + } else { + if (argv[i + 1]) { + if (*argv[i + 1] != '-') { + val_ptr = argv[++i]; + } + } + } + D_OPTIONS(("hasequal == %d val_ptr == %10.8p \"%s\"\n", hasequal, val_ptr, val_ptr)); + if (val_ptr == NULL) { + print_error("long option --%s requires a string value", opt); + continue; + } + D_OPTIONS(("String option detected\n")); + if (val_ptr && optList[j].pval) { + *((const char **) optList[j].pval) = strdup(val_ptr); + } + } else { /* It's a POSIX option */ + + register unsigned short pos; + unsigned char done = 0; + + for (pos = 1; opt[pos] && !done; pos++) { + if (opt[pos] == 't') { + j = 0; + } else if (opt[pos] == 'X') { + j = 1; + } else + continue; + + if (opt[pos + 1]) { + val_ptr = opt + pos + 1; + done = 1; + } else if ((val_ptr = argv[++i]) != NULL) { + done = 1; + } + D_OPTIONS(("val_ptr == %s done == %d\n", val_ptr, done)); + if ((val_ptr == NULL) || (*val_ptr == '-')) { + print_error("option -%c requires a string value", opt[pos]); + if (val_ptr) { /* If the "arg" was actually an option, don't skip it */ + i--; + } + continue; + } + D_OPTIONS(("String option detected\n")); + if (optList[j].pval) { + *((const char **) optList[j].pval) = strdup(val_ptr); + } + } /* End for loop */ + } /* End if (islong) */ + } /* End main for loop */ +} + +#endif + +/***** The Config File Section *****/ + +/* Max length of a line in the config file */ +#define CONFIG_BUFF 20480 + +/* The context identifier. This tells us what section of the config file + we're in, for syntax checking purposes and the like. -- mej */ + +#define CTX_NULL 0 +#define CTX_MAIN 1 +#define CTX_COLOR 2 +#define CTX_ATTRIBUTES 3 +#define CTX_TOGGLES 4 +#define CTX_KEYBOARD 5 +#define CTX_MISC 6 +#define CTX_PIXMAPS 7 +#define CTX_KANJI 8 +#define CTX_UNDEF ((unsigned char) -1) +#define CTX_MAX 8 + +/* This structure defines a context and its attributes */ + +struct context_struct { + + const unsigned char id; + const char *description; + void (*ctx_handler) (char *); + const unsigned char valid_sub_contexts[CTX_MAX]; + +} contexts[] = { + + { + CTX_NULL, "none", NULL, { + CTX_MAIN, 0, 0, 0, 0, 0, 0, 0 + } + }, + { + CTX_MAIN, "main", parse_main, { + CTX_COLOR, CTX_ATTRIBUTES, CTX_TOGGLES, + CTX_KEYBOARD, CTX_MISC, CTX_PIXMAPS, + CTX_KANJI, 0 + } + }, + { + CTX_COLOR, "color", parse_color, { + 0, 0, 0, 0, 0, 0, 0, 0 + } + }, + { + CTX_ATTRIBUTES, "attributes", parse_attributes, { + 0, 0, 0, 0, 0, 0, 0, 0 + } + }, + { + CTX_TOGGLES, "toggles", parse_toggles, { + 0, 0, 0, 0, 0, 0, 0, 0 + } + }, + { + CTX_KEYBOARD, "keyboard", parse_keyboard, { + 0, 0, 0, 0, 0, 0, 0, 0 + } + }, + { + CTX_MISC, "misc", parse_misc, { + 0, 0, 0, 0, 0, 0, 0, 0 + } + }, + { + CTX_PIXMAPS, "pixmaps", parse_pixmaps, { + 0, 0, 0, 0, 0, 0, 0, 0 + } + }, + { + CTX_KANJI, "kanji", parse_kanji, { + 0, 0, 0, 0, 0, 0, 0, 0 + } + }, + { + CTX_UNDEF, NULL, parse_undef, { + 0, 0, 0, 0, 0, 0, 0, 0 + } + } + +}; + +#define ctx_name_to_id(the_id, n, i) do { \ + for ((i)=0; (i) <= CTX_MAX; (i)++) { \ + if (!strcasecmp((n), contexts[(i)].description)) { \ + (the_id) = contexts[(i)].id; \ + break; \ + } \ + } \ + if ((i) > CTX_MAX) (the_id) = CTX_UNDEF; \ + } while (0) + +#define ctx_id_to_name(id) (contexts[(id)].description) +#define ctx_id_to_func(id) (contexts[(id)].ctx_handler) + +/* The context stack. This keeps track of the current context and each + previous one. You MUST define MAX_CTX_DEPTH to the absolute maximum + number of context levels deep your contexts go, or the results can be + Very Bad. I recommend erring on the side of caution. -- mej */ + +#define MAX_CTX_DEPTH 10 +#define ctx_push(ctx) id_stack[++cur_ctx] = (ctx) +#define ctx_pop() (id_stack[cur_ctx--]) +#define ctx_peek() (id_stack[cur_ctx]) + +unsigned char id_stack[MAX_CTX_DEPTH]; +unsigned short cur_ctx = 0; + +/* The file state stack. This keeps track of the file currently being + parsed. This allows for %include directives. -- mej */ + +typedef struct file_state_struct { + + FILE *fp; + char *path; + unsigned long line; + unsigned char skip_to_end; + +} file_state; + +#define MAX_FILE_DEPTH 10 +#define file_push(fs) do { \ + cur_file++; \ + file_stack[cur_file].fp = (fs).fp; \ + file_stack[cur_file].path = (fs).path; \ + file_stack[cur_file].line = (fs).line; \ + file_stack[cur_file].skip_to_end = (fs).skip_to_end; \ + } while (0) + +#define file_pop() (cur_file--) +#define file_peek(fs) do { \ + (fs).fp = file_stack[cur_file].fp; \ + (fs).path = file_stack[cur_file].path; \ + (fs).line = file_stack[cur_file].line; \ + (fs).skip_to_end = file_stack[cur_file].skip_to_end; \ + } while (0) +#define file_peek_fp() (file_stack[cur_file].fp) +#define file_peek_path() (file_stack[cur_file].path) +#define file_peek_line() (file_stack[cur_file].line) +#define file_peek_skip() (file_stack[cur_file].skip_to_end) + +#define file_poke_fp(f) ((file_stack[cur_file].fp) = (f)) +#define file_poke_path(p) ((file_stack[cur_file].path) = (p)) +#define file_poke_line(l) ((file_stack[cur_file].line) = (l)) +#define file_poke_skip(s) ((file_stack[cur_file].skip_to_end) = (s)) + +#define file_inc_line() (file_stack[cur_file].line++) + +file_state file_stack[MAX_FILE_DEPTH]; +short cur_file = -1; + +/* The function structures */ + +typedef char *(*eterm_function_ptr) (char *); +typedef struct eterm_function_struct { + + char *name; + eterm_function_ptr ptr; + int params; + +} eterm_func; + +eterm_func builtins[] = +{ + {"random", builtin_random, -1}, + {"exec", builtin_exec, -1}, + {"version", builtin_version, 0}, + {"appname", builtin_appname, 0}, + {(char *) NULL, (eterm_function_ptr) NULL, 0} +}; + +char * +builtin_random(char *param) +{ + + unsigned long n, index; + static unsigned int rseed = 0; + + D_OPTIONS(("builtin_random(%s) called\n", param)); + + if (rseed == 0) { + rseed = (unsigned int) (getpid() * time(NULL) % ((unsigned int) -1)); + srand(rseed); + } + n = NumWords(param); + index = (int) (n * ((float) rand()) / (RAND_MAX + 1.0)) + 1; + D_OPTIONS(("random index == %lu\n", index)); + + return (Word(index, param)); +} + +char * +builtin_exec(char *param) +{ + + D_OPTIONS(("builtin_exec(%s) called\n", param)); + + return (param); +} + +char * +builtin_version(char *param) +{ + + D_OPTIONS(("builtin_version(%s) called\n", param)); + + return (Word(1, VERSION)); +} + +char * +builtin_appname(char *param) +{ + + D_OPTIONS(("builtin_appname(%s) called\n", param)); + + return (Word(1, APL_NAME "-" VERSION)); +} + +/* chomp() removes leading and trailing whitespace/quotes from a string */ +char * +chomp(char *s) +{ + + register char *front, *back; + + for (front = s; *front && isspace(*front); front++); + /* + if (*front == '\"') front++; + */ + for (back = s + strlen(s) - 1; *back && isspace(*back) && back > front; back--); + /* + if (*back == '\"') back--; + */ + + *(++back) = 0; + if (front != s) + memmove(s, front, back - front + 1); + return (s); +} + +/* shell_expand() takes care of shell variable expansion, quote conventions, + calling of built-in functions, etc. -- mej */ +char * +shell_expand(char *s) +{ + + register char *tmp; + register char *new; + register char *pbuff = s, *tmp1; + register unsigned long j, k, l; + unsigned char eval_escape = 1, eval_var = 1, eval_exec = 1, eval_func = 1, in_single = 0, in_double = 0; + unsigned long fsize; + char *Command, *Output, *EnvVar, *OutFile; + FILE *fp; + + ASSERT(s != NULL); + if (!s) + return ((char *) NULL); + + new = (char *) MALLOC(CONFIG_BUFF); + + for (j = 0; *pbuff && j < CONFIG_BUFF; pbuff++, j++) { + switch (*pbuff) { + case '~': + D_OPTIONS(("Tilde detected.\n")); + if (eval_var) { + strncpy(new + j, getenv("HOME"), CONFIG_BUFF - j); + j += strlen(getenv("HOME")) - 1; + } else { + new[j] = *pbuff; + } + break; + case '\\': + D_OPTIONS(("Escape sequence detected.\n")); + if (eval_escape || (in_single && *(pbuff + 1) == '\'')) { + switch (tolower(*(++pbuff))) { + case 'n': + new[j] = '\n'; + break; + case 'r': + new[j] = '\r'; + break; + case 't': + new[j] = '\t'; + break; + case 'b': + j -= 2; + break; + case 'f': + new[j] = '\f'; + break; + case 'a': + new[j] = '\a'; + break; + case 'v': + new[j] = '\v'; + break; + case 'e': + new[j] = '\033'; + break; + default: + new[j] = *pbuff; + break; + } + } else { + new[j++] = *(pbuff++); + new[j] = *pbuff; + } + break; + case '%': + D_OPTIONS(("%% detected.\n")); + for (k = 0, pbuff++; builtins[k].name != NULL; k++) { + D_OPTIONS(("Checking for function %%%s, pbuff == \"%s\"\n", builtins[k].name, pbuff)); + l = strlen(builtins[k].name); + if (!strncasecmp(builtins[k].name, pbuff, l) && + ((pbuff[l] == '(') || (pbuff[l] == ' ' && pbuff[l + 1] == ')'))) { + break; + } + } + if (builtins[k].name == NULL) { + new[j] = *pbuff; + } else { + D_OPTIONS(("Call to built-in function %s detected.\n", builtins[k].name)); + Command = (char *) MALLOC(CONFIG_BUFF); + pbuff += l; + if (*pbuff != '(') + pbuff++; + for (tmp1 = Command, pbuff++, l = 1; l && *pbuff; pbuff++, tmp1++) { + switch (*pbuff) { + case '(': + l++; + *tmp1 = *pbuff; + break; + case ')': + l--; + default: + *tmp1 = *pbuff; + break; + } + } + *(--tmp1) = 0; + if (l) { + print_error("parse error in file %s, line %lu: Mismatched parentheses", + file_peek_path(), file_peek_line()); + return ((char *) NULL); + } + Command = shell_expand(Command); + Output = (builtins[k].ptr) (Command); + FREE(Command); + if (Output && *Output) { + l = strlen(Output) - 1; + strncpy(new + j, Output, CONFIG_BUFF - j); + j += l; + FREE(Output); + } else { + j--; + } + pbuff--; + } + break; + case '`': +#ifdef ALLOW_BACKQUOTE_EXEC + D_OPTIONS(("Backquotes detected. Evaluating expression.\n")); + if (eval_exec) { + Command = (char *) MALLOC(CONFIG_BUFF); + l = 0; + for (pbuff++; *pbuff && *pbuff != '`' && l < CONFIG_BUFF; pbuff++, l++) { + switch (*pbuff) { + case '$': + D_OPTIONS(("Environment variable detected. Evaluating.\n")); + EnvVar = (char *) MALLOC(128); + switch (*(++pbuff)) { + case '{': + for (pbuff++, k = 0; *pbuff != '}' && k < 127; k++, pbuff++) + EnvVar[k] = *pbuff; + break; + case '(': + for (pbuff++, k = 0; *pbuff != ')' && k < 127; k++, pbuff++) + EnvVar[k] = *pbuff; + break; + default: + for (k = 0; (isalnum(*pbuff) || *pbuff == '_') && k < 127; k++, pbuff++) + EnvVar[k] = *pbuff; + break; + } + EnvVar[k] = 0; + if ((tmp = getenv(EnvVar))) { + strncpy(Command + l, tmp, CONFIG_BUFF - l); + l = strlen(Command) - 1; + } + pbuff--; + break; + default: + Command[l] = *pbuff; + } + } + Command[l] = 0; + OutFile = tmpnam(NULL); + if (l + strlen(OutFile) + 8 > CONFIG_BUFF) { + print_error("parse error in file %s, line %lu: Cannot execute command, line too long", + file_peek_path(), file_peek_line()); + return ((char *) NULL); + } + strcat(Command, " >"); + strcat(Command, OutFile); + system(Command); + if ((fp = fopen(OutFile, "rb")) >= 0) { + fseek(fp, 0, SEEK_END); + fsize = ftell(fp); + rewind(fp); + if (fsize) { + Output = (char *) MALLOC(fsize + 1); + fread(Output, fsize, 1, fp); + Output[fsize] = 0; + D_OPTIONS(("Command returned \"%s\"\n", Output)); + fclose(fp); + remove(OutFile); + Output = CondenseWhitespace(Output); + strncpy(new + j, Output, CONFIG_BUFF - j); + j += strlen(Output) - 1; + FREE(Output); + } else { + print_warning("Command at line %lu of file %s returned no output.", file_peek_line(), file_peek_path()); + } + } else { + print_warning("Output file %s could not be created. (line %lu of file %s)", (OutFile ? OutFile : "(null)"), + file_peek_line(), file_peek_path()); + } + FREE(Command); + } else { + new[j] = *pbuff; + } +#else + print_error("warning: backquote execution support not compiled in, ignoring"); + new[j] = *pbuff; +#endif + break; + case '$': + D_OPTIONS(("Environment variable detected. Evaluating.\n")); + if (eval_var) { + EnvVar = (char *) MALLOC(128); + switch (*(++pbuff)) { + case '{': + for (pbuff++, k = 0; *pbuff != '}' && k < 127; k++, pbuff++) + EnvVar[k] = *pbuff; + break; + case '(': + for (pbuff++, k = 0; *pbuff != ')' && k < 127; k++, pbuff++) + EnvVar[k] = *pbuff; + break; + default: + for (k = 0; (isalnum(*pbuff) || *pbuff == '_') && k < 127; k++, pbuff++) + EnvVar[k] = *pbuff; + break; + } + EnvVar[k] = 0; + if ((tmp = getenv(EnvVar))) { + strncpy(new, tmp, CONFIG_BUFF - j); + j += strlen(tmp) - 1; + } + pbuff--; + } else { + new[j] = *pbuff; + } + break; + case '\"': + D_OPTIONS(("Double quotes detected.\n")); + if (!in_single) { + if (in_double) { + in_double = 0; + } else { + in_double = 1; + } + } + new[j] = *pbuff; + break; + + case '\'': + D_OPTIONS(("Single quotes detected.\n")); + if (in_single) { + eval_var = 1; + eval_exec = 1; + eval_func = 1; + eval_escape = 1; + in_single = 0; + } else { + eval_var = 0; + eval_exec = 0; + eval_func = 0; + eval_escape = 0; + in_single = 1; + } + new[j] = *pbuff; + break; + + default: + new[j] = *pbuff; + } + } + new[j] = 0; + + D_OPTIONS(("shell_expand(%s) returning \"%s\"\n", s, new)); + + strcpy(s, new); + FREE(new); + return (s); +} + +/* The config file parsers. Each function handles a given context. */ + +void +parse_main(char *buff) +{ + + ASSERT(buff != NULL); + + print_error("parse error in file %s, line %lu: Attribute " + "\"%s\" is not valid within context main\n", + file_peek_path(), file_peek_line(), buff); +} + +void +parse_color(char *buff) +{ + + ASSERT(buff != NULL); + + if (!BEG_STRCASECMP(buff, "foreground ")) { + rs_color[fgColor] = Word(2, buff); + } else if (!BEG_STRCASECMP(buff, "background ")) { + rs_color[bgColor] = Word(2, buff); + + } else if (!BEG_STRCASECMP(buff, "tint ")) { +#ifdef PIXMAP_OFFSET + rs_tintMask = strtoul(buff + 5, (char **) NULL, 0); +#else + print_error("warning: support for the tint attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "shade ")) { +#ifdef PIXMAP_OFFSET + rs_shadePct = strtoul(buff + 5, (char **) NULL, 0); +#else + print_error("warning: support for the shade attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "cursor ")) { + +#ifndef NO_CURSORCOLOR + rs_color[cursorColor] = Word(2, buff); +#else + print_error("warning: support for the cursor attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "cursor_text ")) { +#ifndef NO_CURSORCOLOR + rs_color[cursorColor2] = Word(2, buff); +#else + print_error("warning: support for the cursor_text attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "menu_text ")) { + rs_color[menuTextColor] = Word(2, buff); + + } else if (!BEG_STRCASECMP(buff, "scrollbar ")) { +#if defined(KEEP_SCROLLCOLOR) + rs_color[scrollColor] = Word(2, buff); +#else + print_error("warning: support for the scrollbar color attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "unfocusedscrollbar ")) { +#if defined(KEEP_SCROLLCOLOR) && defined(CHANGE_SCROLLCOLOR_ON_FOCUS) + rs_color[unfocusedScrollColor] = Word(2, buff); +#else + print_error("warning: support for the unfocusedscrollbar color attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "pointer ")) { + rs_color[pointerColor] = Word(2, buff); + + } else if (!BEG_STRCASECMP(buff, "video ")) { + + char *tmp = PWord(2, buff); + + if (!BEG_STRCASECMP(tmp, "reverse")) { + Options |= Opt_reverseVideo; + rs_reverseVideo = *true_vals; + } else if (BEG_STRCASECMP(tmp, "normal")) { + print_error("parse error in file %s, line %lu: Invalid value \"%s\" for attribute video", + file_peek_path(), file_peek_line(), tmp); + } + } else if (!BEG_STRCASECMP(buff, "color ")) { + + char *tmp = 0, *r1, *g1, *b1; + unsigned int n, r, g, b, index = 0; + + n = NumWords(buff); + if (n < 3) { + print_error("parse error in file %s, line %lu: Invalid parameter list \"%s\" for " + "attribute color", file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + return; + } + tmp = PWord(2, buff); + r1 = PWord(3, buff); + if (!isdigit(*r1)) { + if (isdigit(*tmp)) { + n = strtoul(tmp, (char **) NULL, 0); + if (n >= 0 && n <= 7) { + index = minColor + n; + } else if (n >= 8 && n <= 15) { + index = minBright + n - 8; + } + rs_color[index] = Word(1, r1); + return; + } else { + if (!BEG_STRCASECMP(tmp, "bd ")) { +#ifndef NO_BOLDUNDERLINE + rs_color[colorBD] = Word(1, r1); +#else + print_error("warning: support for the color bd attribute was not compiled in, ignoring"); +#endif + return; + } else if (!BEG_STRCASECMP(tmp, "ul ")) { +#ifndef NO_BOLDUNDERLINE + rs_color[colorUL] = Word(1, r1); +#else + print_error("warning: support for the color ul attribute was not compiled in, ignoring"); +#endif + return; + } else { + tmp = Word(1, tmp); + print_error("parse error in file %s, line %lu: Invalid color index \"%s\"", + file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + free(tmp); + } + } + } + if (n != 5) { + print_error("parse error in file %s, line %lu: Invalid parameter list \"%s\" for " + "attribute color", file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + return; + } + g1 = PWord(4, buff); + b1 = PWord(5, buff); + if (isdigit(*tmp)) { + n = strtoul(tmp, (char **) NULL, 0); + r = strtoul(r1, (char **) NULL, 0); + g = strtoul(g1, (char **) NULL, 0); + b = strtoul(b1, (char **) NULL, 0); + if (n >= 0 && n <= 7) { + index = minColor + n; + rs_color[index] = MALLOC(14); + sprintf(rs_color[index], "#%02x%02x%02x", r, g, b); + } else if (n >= 8 && n <= 15) { + index = minBright + n - 8; + rs_color[index] = MALLOC(14); + sprintf(rs_color[index], "#%02x%02x%02x", r, g, b); + } else { + print_error("parse error in file %s, line %lu: Invalid color index %lu", + file_peek_path(), file_peek_line(), n); + } + + } else if (!BEG_STRCASECMP(tmp, "bd ")) { +#ifndef NO_BOLDUNDERLINE + rs_color[colorBD] = MALLOC(14); + r = strtoul(r1, (char **) NULL, 0); + g = strtoul(g1, (char **) NULL, 0); + b = strtoul(b1, (char **) NULL, 0); + sprintf(rs_color[colorBD], "#%02x%02x%02x", r, g, b); +#else + print_error("warning: support for the color bd attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(tmp, "ul ")) { +#ifndef NO_BOLDUNDERLINE + rs_color[colorUL] = MALLOC(14); + r = strtoul(r1, (char **) NULL, 0); + g = strtoul(g1, (char **) NULL, 0); + b = strtoul(b1, (char **) NULL, 0); + sprintf(rs_color[colorUL], "#%02x%02x%02x", r, g, b); +#else + print_error("warning: support for the color ul attribute was not compiled in, ignoring"); +#endif + + } else { + tmp = Word(1, tmp); + print_error("parse error in file %s, line %lu: Invalid color index \"%s\"", + file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + free(tmp); + } + } else { + print_error("parse error in file %s, line %lu: Attribute \"%s\" is not valid " + "within context color", file_peek_path(), file_peek_line(), buff); + } +} + +void +parse_attributes(char *buff) +{ + + ASSERT(buff != NULL); + + if (!BEG_STRCASECMP(buff, "geometry ")) { + rs_geometry = Word(2, buff); + + } else if (!BEG_STRCASECMP(buff, "title ")) { + rs_title = Word(2, buff); + + } else if (!BEG_STRCASECMP(buff, "name ")) { + rs_name = Word(2, buff); + + } else if (!BEG_STRCASECMP(buff, "iconname ")) { + rs_iconName = Word(2, buff); + + } else if (!BEG_STRCASECMP(buff, "desktop ")) { + rs_desktop = (int) strtol(buff, (char **) NULL, 0); + + } else if (!BEG_STRCASECMP(buff, "scrollbar_type ")) { + rs_scrollbar_type = Word(2, buff); + + } else if (!BEG_STRCASECMP(buff, "scrollbar_width ")) { + rs_scrollbar_width = strtoul(PWord(2, buff), (char **) NULL, 0); + + } else if (!BEG_STRCASECMP(buff, "font ")) { + + char *tmp = PWord(2, buff); + unsigned char n; + + if (NumWords(buff) != 3) { + print_error("parse error in file %s, line %lu: Invalid parameter list \"%s\" for " + "attribute font", file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + return; + } + if (isdigit(*tmp)) { + n = (unsigned char) strtoul(tmp, (char **) NULL, 0); + if (n <= 4) { + rs_font[n] = Word(2, tmp); + } else { + print_error("parse error in file %s, line %lu: Invalid font index %d", + file_peek_path(), file_peek_line(), n); + } + } else if (!BEG_STRCASECMP(tmp, "bold ")) { +#ifndef NO_BOLDFONT + rs_boldFont = Word(2, tmp); +#else + print_error("warning: support for the bold font attribute was not compiled in, ignoring"); +#endif + + } else { + tmp = Word(1, tmp); + print_error("parse error in file %s, line %lu: Invalid font index \"%s\"", + file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + free(tmp); + } + + } else { + print_error("parse error in file %s, line %lu: Attribute \"%s\" is not valid " + "within context attributes", file_peek_path(), file_peek_line(), (buff ? buff : "")); + } +} + +void +parse_toggles(char *buff) +{ + + char *tmp = PWord(2, buff); + unsigned char bool_val; + + ASSERT(buff != NULL); + + if (!tmp) { + print_error("parse error in file %s, line %lu: Missing boolean value in context toggles", file_peek_path(), file_peek_line()); + return; + } + if (BOOL_OPT_ISTRUE(tmp)) { + bool_val = 1; + } else if (BOOL_OPT_ISFALSE(tmp)) { + bool_val = 0; + } else { + print_error("parse error in file %s, line %lu: Invalid boolean value \"%s\" in context toggles", + file_peek_path(), file_peek_line(), tmp); + return; + } + + if (!BEG_STRCASECMP(buff, "map_alert ")) { +#if !defined(NO_MAPALERT) && defined(MAPALERT_OPTION) + if (bool_val) { + Options |= Opt_mapAlert; + rs_mapAlert = *true_vals; + } else { + Options &= ~(Opt_mapAlert); + rs_mapAlert = *false_vals; + } +#else + print_error("warning: support for the map_alert attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "visual_bell ")) { + if (bool_val) { + Options |= Opt_visualBell; + rs_visualBell = *true_vals; + } else { + Options &= ~(Opt_visualBell); + rs_visualBell = *false_vals; + } + } else if (!BEG_STRCASECMP(buff, "login_shell ")) { + if (bool_val) { + Options |= Opt_loginShell; + rs_loginShell = *true_vals; + } else { + Options &= ~(Opt_loginShell); + rs_loginShell = *false_vals; + } + } else if (!BEG_STRCASECMP(buff, "scrollbar ")) { + if (bool_val) { + Options |= Opt_scrollBar; + rs_scrollBar = *true_vals; + } else { + Options &= ~(Opt_scrollBar); + rs_scrollBar = *false_vals; + } + } else if (!BEG_STRCASECMP(buff, "menubar ")) { +#if (MENUBAR_MAX) + if (bool_val) { + rs_menubar = *true_vals; + } else { + rs_menubar = *false_vals; + } +#else + print_error("warning: support for the menubar attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "utmp_logging ")) { +#ifdef UTMP_SUPPORT + if (bool_val) { + Options |= Opt_utmpLogging; + rs_utmpLogging = *true_vals; + } else { + Options &= ~(Opt_utmpLogging); + rs_utmpLogging = *false_vals; + } +#else + print_error("warning: support for the utmp_logging attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "meta8 ")) { +#ifdef META8_OPTION + if (bool_val) { + Options |= Opt_meta8; + rs_meta8 = *true_vals; + } else { + Options &= ~(Opt_meta8); + rs_meta8 = *false_vals; + } +#else + print_error("warning: support for the meta8 attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "iconic ")) { + if (bool_val) { + Options |= Opt_iconic; + } else { + Options &= ~(Opt_iconic); + } + + } else if (!BEG_STRCASECMP(buff, "home_on_echo ")) { + if (bool_val) { + Options |= Opt_homeOnEcho; + rs_homeOnEcho = *true_vals; + } else { + Options &= ~(Opt_homeOnEcho); + rs_homeOnEcho = *false_vals; + } + + } else if (!BEG_STRCASECMP(buff, "home_on_input ")) { + if (bool_val) { + Options |= Opt_homeOnInput; + rs_homeOnInput = *true_vals; + } else { + Options &= ~(Opt_homeOnInput); + rs_homeOnInput = *false_vals; + } + + } else if (!BEG_STRCASECMP(buff, "home_on_refresh ")) { + if (bool_val) { + Options |= Opt_homeOnRefresh; + rs_homeOnRefresh = *true_vals; + } else { + Options &= ~(Opt_homeOnRefresh); + rs_homeOnRefresh = *false_vals; + } + + } else if (!BEG_STRCASECMP(buff, "scrollbar_floating ")) { + if (bool_val) { + Options |= Opt_scrollBar_floating; + rs_scrollBar_floating = *true_vals; + } else { + Options &= ~(Opt_scrollBar_floating); + rs_scrollBar_floating = *false_vals; + } + + } else if (!BEG_STRCASECMP(buff, "scrollbar_right ")) { + if (bool_val) { + Options |= Opt_scrollBar_right; + rs_scrollBar_right = *true_vals; + } else { + Options &= ~(Opt_scrollBar_right); + rs_scrollBar_right = *false_vals; + } + } else if (!BEG_STRCASECMP(buff, "scrollbar_popup ")) { + if (bool_val) { + Options |= Opt_scrollbar_popup; + rs_scrollbar_popup = *true_vals; + } else { + Options &= ~(Opt_scrollbar_popup); + rs_scrollbar_popup = *false_vals; + } + } else if (!BEG_STRCASECMP(buff, "borderless ")) { + if (bool_val) { + Options |= Opt_borderless; + rs_borderless = *true_vals; + } else { + Options &= ~(Opt_borderless); + rs_borderless = *false_vals; + } + } else if (!BEG_STRCASECMP(buff, "save_under ")) { +#ifdef BACKING_STORE + if (bool_val) { + Options |= Opt_saveUnder; + rs_saveUnder = *true_vals; + } else { + Options &= ~(Opt_saveUnder); + rs_saveUnder = *false_vals; + } +#else + print_error("warning: support for the save_under attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "trans ")) { +#ifdef PIXMAP_OFFSET + if (bool_val) { + Options |= Opt_pixmapTrans; + rs_pixmapTrans = *true_vals; + } else { + Options &= ~(Opt_pixmapTrans); + rs_pixmapTrans = *false_vals; + } +#else + print_error("warning: support for the trans attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "watch_desktop ")) { +#ifdef WATCH_DESKTOP_OPTION + if (bool_val) { + Options |= Opt_watchDesktop; + rs_watchDesktop = *true_vals; + } else { + Options &= ~(Opt_watchDesktop); + rs_watchDesktop = *false_vals; + } +#else + print_error("warning: support for the watch_desktop attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "no_cursor ")) { + if (bool_val) { + Options |= Opt_noCursor; + rs_noCursor = (char *) true_vals; + } else { + Options &= ~(Opt_noCursor); + rs_noCursor = (char *) false_vals; + } + + } else if (!BEG_STRCASECMP(buff, "menubar_move ")) { +#if MENUBAR_MAX + if (bool_val) { + Options |= Opt_menubar_move; + rs_menubar_move = (char *) true_vals; + } else { + Options &= ~(Opt_menubar_move); + rs_menubar_move = (char *) false_vals; + } +#else + print_error("warning: support for the menubar_move attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "pause ")) { + if (bool_val) { + Options |= Opt_pause; + rs_pause = (char *) true_vals; + } else { + Options &= ~(Opt_pause); + rs_pause = (char *) false_vals; + } + + } else if (!BEG_STRCASECMP(buff, "xterm_select ")) { + if (bool_val) { + Options |= Opt_xterm_select; + rs_xterm_select = (char *) true_vals; + } else { + Options &= ~(Opt_xterm_select); + rs_xterm_select = (char *) false_vals; + } + + } else if (!BEG_STRCASECMP(buff, "select_line ")) { + if (bool_val) { + Options |= Opt_select_whole_line; + rs_select_whole_line = (char *) true_vals; + } else { + Options &= ~(Opt_select_whole_line); + rs_select_whole_line = (char *) false_vals; + } + + } else if (!BEG_STRCASECMP(buff, "select_trailing_spaces ")) { + if (bool_val) { + Options |= Opt_select_trailing_spaces; + rs_select_trailing_spaces = (char *) true_vals; + } else { + Options &= ~(Opt_select_trailing_spaces); + rs_select_trailing_spaces = (char *) false_vals; + } + + } else if (!BEG_STRCASECMP(buff, "viewport_mode ")) { +#ifdef PIXMAP_OFFSET + if (bool_val) { + Options |= Opt_viewport_mode; + rs_viewport_mode = (char *) true_vals; + } else { + Options &= ~(Opt_viewport_mode); + rs_viewport_mode = (char *) false_vals; + } +#else + print_error("warning: support for the viewport_mode attribute was not compiled in, ignoring"); +#endif + + } else { + print_error("parse error in file %s, line %lu: Attribute \"%s\" is not valid within context toggles", file_peek_path(), file_peek_line(), buff); + } +} + +#define to_keysym(p,s) do { KeySym sym; \ +if (s && ((sym = XStringToKeysym(s)) != 0)) *p = sym; \ + } while (0) + +void +parse_keyboard(char *buff) +{ + + ASSERT(buff != NULL); + + if (!BEG_STRCASECMP(buff, "smallfont_key ")) { +#if defined (HOTKEY_CTRL) || defined (HOTKEY_META) + rs_smallfont_key = Word(2, buff); + to_keysym(&ks_smallfont, rs_smallfont_key); +#else + print_error("warning: support for the smallfont_key attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "bigfont_key ")) { +#if defined (HOTKEY_CTRL) || defined (HOTKEY_META) + rs_bigfont_key = Word(2, buff); + to_keysym(&ks_bigfont, rs_bigfont_key); +#else + print_error("warning: support for the bigfont_key attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "keysym ")) { +#ifdef KEYSYM_ATTRIBUTE + + int sym, len; + char *str = buff + 7; + + sym = (int) strtol(str, (char **) NULL, 0); + if (sym != (int) 2147483647L) { + + if (sym >= 0xff00) + sym -= 0xff00; + if (sym < 0 || sym > 0xff) { + print_error("parse error in file %s, line %lu: Keysym 0x%x out of range 0xff00-0xffff", + file_peek_path(), file_peek_line(), sym + 0xff00); + return; + } + str = Word(3, buff); + chomp(str); + len = parse_escaped_string(str); + if (len > 255) + len = 255; /* We can only handle lengths that will fit in a char */ + if (len && KeySym_map[sym] == NULL) { + + char *p = malloc(len + 1); + + *p = len; + strncpy(p + 1, str, len); + KeySym_map[sym] = p; + } + } +#else + print_error("warning: support for the keysym attributes was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "greek ")) { +#ifdef GREEK_SUPPORT + + char *tmp = PWord(2, buff); + + if (!tmp) { + print_error("parse error in file %s, line %lu: Missing boolean value for attribute greek", + file_peek_path(), file_peek_line()); + return; + } + if (BOOL_OPT_ISTRUE(tmp)) { + rs_greek_keyboard = Word(3, buff); + if (BEG_STRCASECMP(rs_greek_keyboard, "iso")) { + greek_setmode(GREEK_ELOT928); + } else if (BEG_STRCASECMP(rs_greek_keyboard, "ibm")) { + greek_setmode(GREEK_IBM437); + } else { + print_error("parse error in file %s, line %lu: Invalid greek keyboard mode \"%s\"", + file_peek_path(), file_peek_line(), (rs_greek_keyboard ? rs_greek_keyboard : "")); + } + } else if (BOOL_OPT_ISFALSE(tmp)) { + /* This space intentionally left no longer blank =^) */ + } else { + print_error("parse error in file %s, line %lu: Invalid boolean value \"%s\" for attribute %s", + file_peek_path(), file_peek_line(), tmp, buff); + return; + } +#else + print_error("warning: support for the greek attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "app_keypad ")) { + + char *tmp = PWord(2, buff); + + if (!tmp) { + print_error("parse error in file %s, line %lu: Missing boolean value for attribute app_keypad", + file_peek_path(), file_peek_line()); + return; + } + if (BOOL_OPT_ISTRUE(tmp)) { + PrivateModes |= PrivMode_aplKP; + rs_app_keypad = (char *) true_vals; + } else if (BOOL_OPT_ISFALSE(tmp)) { + PrivateModes &= ~(PrivMode_aplKP); + rs_app_keypad = (char *) false_vals; + } else { + print_error("parse error in file %s, line %lu: Invalid boolean value \"%s\" for " + "attribute app_keypad", file_peek_path(), file_peek_line(), tmp); + return; + } + + } else if (!BEG_STRCASECMP(buff, "app_cursor ")) { + + char *tmp = PWord(2, buff); + + if (!tmp) { + print_error("parse error in file %s, line %lu: Missing boolean value for attribute app_cursor", + file_peek_path(), file_peek_line()); + return; + } + if (BOOL_OPT_ISTRUE(tmp)) { + PrivateModes |= PrivMode_aplCUR; + rs_app_cursor = (char *) true_vals; + } else if (BOOL_OPT_ISFALSE(tmp)) { + PrivateModes &= ~(PrivMode_aplCUR); + rs_app_cursor = (char *) false_vals; + } else { + print_error("parse error in file %s, line %lu: Invalid boolean value \"%s\" for " + "attribute app_cursor", file_peek_path(), file_peek_line(), tmp); + return; + } + + } else { + print_error("parse error in file %s, line %lu: Attribute \"%s\" is not valid " + "within context keyboard", file_peek_path(), file_peek_line(), buff); + } +} +#undef to_keysym + +void +parse_misc(char *buff) +{ + + ASSERT(buff != NULL); + + if (!BEG_STRCASECMP(buff, "print_pipe ")) { +#ifdef PRINTPIPE + rs_print_pipe = strdup(PWord(2, buff)); + chomp(rs_print_pipe); +#else + print_error("warning: support for the print_pipe attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "save_lines ")) { + rs_saveLines = strtol(PWord(2, buff), (char **) NULL, 0); + + } else if (!BEG_STRCASECMP(buff, "min_anchor_size ")) { + rs_min_anchor_size = strtol(PWord(2, buff), (char **) NULL, 0); + + } else if (!BEG_STRCASECMP(buff, "border_width ")) { +#ifdef BORDER_WIDTH_OPTION + TermWin.internalBorder = (short) strtol(PWord(2, buff), (char **) NULL, 0); +#else + print_error("warning: support for the border_width attribute was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "menu ")) { +#if MENUBAR_MAX + rs_menu = Word(2, buff); + if (NumWords(buff) > 2) { + char *btmp = Word(3, buff); + + if (BOOL_OPT_ISTRUE(btmp)) { + rs_menubar = *true_vals; + } else if (BOOL_OPT_ISFALSE(btmp)) { + rs_menubar = *false_vals; + } + } +#else + print_error("warning: support for menus was not compiled in, ignoring"); +#endif + + } else if (!BEG_STRCASECMP(buff, "term_name ")) { + rs_term_name = Word(2, buff); + + } else if (!BEG_STRCASECMP(buff, "debug ")) { + debug_level = (unsigned int) strtoul(PWord(2, buff), (char **) NULL, 0); + + } else if (!BEG_STRCASECMP(buff, "exec ")) { + + register unsigned short k, n; + + Options |= Opt_exec; + + rs_execArgs = (char **) malloc(sizeof(char *) * ((n = NumWords(PWord(2, buff))) + 1)); + + for (k = 0; k < n; k++) { + rs_execArgs[k] = Word(k + 2, buff); + D_OPTIONS(("rs_execArgs[%d] == %s\n", k, rs_execArgs[k])); + } + rs_execArgs[n] = (char *) NULL; + + } else if (!BEG_STRCASECMP(buff, "cut_chars ")) { +#ifdef CUTCHAR_OPTION + rs_cutchars = Word(2, buff); + chomp(rs_cutchars); +#else + print_error("warning: support for the cut_chars attribute was not compiled in, ignoring"); +#endif + + } else { + print_error("parse error in file %s, line %lu: Attribute \"%s\" is not valid " + "within context misc", file_peek_path(), file_peek_line(), buff); + } +} + +void +parse_pixmaps(char *buff) +{ + + long w, h; + char *w1, *h1; + unsigned long n; + +#ifdef PIXMAP_SUPPORT + ASSERT(buff != NULL); + + if (!BEG_STRCASECMP(buff, "background ")) { + + if ((n = NumWords(buff) < 4) || (n > 6)) { + char *tmp = PWord(2, buff); + + print_error("parse error in file %s, line %lu: Invalid parameter list \"%s\" for attribute background", + file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + return; + } + w1 = PWord(2, buff); + h1 = PWord(3, buff); + w = strtol(w1, (char **) NULL, 0); + h = strtol(h1, (char **) NULL, 0); + if (w || h) { + rs_pixmapScale = (char *) true_vals; + Options |= Opt_pixmapScale; + rs_pixmaps[pixmap_bg] = Word(4, buff); + rs_pixmaps[pixmap_bg] = (char *) realloc(rs_pixmaps[pixmap_bg], strlen(rs_pixmaps[pixmap_bg]) + 9); + strcat(rs_pixmaps[pixmap_bg], "@100x100"); + } else { + rs_pixmaps[pixmap_bg] = Word(4, buff); + } + + } else if (!BEG_STRCASECMP(buff, "icon ")) { + rs_icon = Word(2, buff); + +# ifdef PIXMAP_SCROLLBAR + } else if (!BEG_STRCASECMP(buff, "scroll_up ")) { + + if ((n = NumWords(buff) < 4) || (n > 6)) { + char *tmp = PWord(2, buff); + + print_error("parse error in file %s, line %lu: Invalid parameter list \"%s\" for attribute " + "scroll_up", file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + return; + } + w1 = PWord(2, buff); + h1 = PWord(3, buff); + w = strtol(w1, (char **) NULL, 0); + h = strtol(h1, (char **) NULL, 0); + if (w || h) { + rs_pixmaps[pixmap_up] = Word(4, buff); + rs_pixmaps[pixmap_up] = (char *) realloc(rs_pixmaps[pixmap_up], strlen(rs_pixmaps[pixmap_up]) + 9); + strcat(rs_pixmaps[pixmap_up], "@100x100"); + } else { + rs_pixmaps[pixmap_up] = Word(4, buff); + } + } else if (!BEG_STRCASECMP(buff, "scroll_up_clicked ")) { + + if ((n = NumWords(buff) < 4) || (n > 6)) { + char *tmp = PWord(2, buff); + + print_error("parse error in file %s, line %lu: Invalid parameter list \"%s\" for attribute " + "scroll_up_clicked", file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + return; + } + w1 = PWord(2, buff); + h1 = PWord(3, buff); + w = strtol(w1, (char **) NULL, 0); + h = strtol(h1, (char **) NULL, 0); + if (w || h) { + rs_pixmaps[pixmap_upclk] = Word(4, buff); + rs_pixmaps[pixmap_upclk] = (char *) realloc(rs_pixmaps[pixmap_upclk], strlen(rs_pixmaps[pixmap_upclk]) + 9); + strcat(rs_pixmaps[pixmap_upclk], "@100x100"); + } else { + rs_pixmaps[pixmap_upclk] = Word(4, buff); + } + } else if (!BEG_STRCASECMP(buff, "scroll_down ")) { + + if ((n = NumWords(buff) < 4) || (n > 6)) { + char *tmp = PWord(2, buff); + + print_error("parse error in file %s, line %lu: Invalid parameter list \"%s\" for attribute " + "scroll_down", file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + return; + } + w1 = PWord(2, buff); + h1 = PWord(3, buff); + w = strtol(w1, (char **) NULL, 0); + h = strtol(h1, (char **) NULL, 0); + if (w || h) { + rs_pixmaps[pixmap_dn] = Word(4, buff); + rs_pixmaps[pixmap_dn] = (char *) realloc(rs_pixmaps[pixmap_dn], strlen(rs_pixmaps[pixmap_dn]) + 9); + strcat(rs_pixmaps[pixmap_dn], "@100x100"); + } else { + rs_pixmaps[pixmap_dn] = Word(4, buff); + } + } else if (!BEG_STRCASECMP(buff, "scroll_down_clicked ")) { + + if ((n = NumWords(buff) < 4) || (n > 6)) { + char *tmp = PWord(2, buff); + + print_error("parse error in file %s, line %lu: Invalid parameter list \"%s\" for attribute " + "scroll_down_clicked", file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + return; + } + w1 = PWord(2, buff); + h1 = PWord(3, buff); + w = strtol(w1, (char **) NULL, 0); + h = strtol(h1, (char **) NULL, 0); + if (w || h) { + rs_pixmaps[pixmap_dnclk] = Word(4, buff); + rs_pixmaps[pixmap_dnclk] = (char *) realloc(rs_pixmaps[pixmap_dnclk], strlen(rs_pixmaps[pixmap_dnclk]) + 9); + strcat(rs_pixmaps[pixmap_dnclk], "@100x100"); + } else { + rs_pixmaps[pixmap_dnclk] = Word(4, buff); + } + } else if (!BEG_STRCASECMP(buff, "scroll_background ")) { + + if ((n = NumWords(buff) < 4) || (n > 6)) { + char *tmp = PWord(2, buff); + + print_error("parse error in file %s, line %lu: Invalid parameter list \"%s\" for attribute " + "scroll_background", file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + return; + } + w1 = PWord(2, buff); + h1 = PWord(3, buff); + w = strtol(w1, (char **) NULL, 0); + h = strtol(h1, (char **) NULL, 0); + if (w || h) { + rs_pixmaps[pixmap_sb] = Word(4, buff); + rs_pixmaps[pixmap_sb] = (char *) realloc(rs_pixmaps[pixmap_sb], strlen(rs_pixmaps[pixmap_sb]) + 9); + strcat(rs_pixmaps[pixmap_sb], "@100x100"); + } else { + rs_pixmaps[pixmap_sb] = Word(4, buff); + } + } else if (!BEG_STRCASECMP(buff, "scroll_anchor ")) { + + if ((n = NumWords(buff) < 4) || (n > 6)) { + char *tmp = PWord(2, buff); + + print_error("parse error in file %s, line %lu: Invalid parameter list \"%s\" for attribute " + "scroll_anchor", file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + return; + } + w1 = PWord(2, buff); + h1 = PWord(3, buff); + w = strtol(w1, (char **) NULL, 0); + h = strtol(h1, (char **) NULL, 0); + if (w || h) { + rs_pixmaps[pixmap_sa] = Word(4, buff); + rs_pixmaps[pixmap_sa] = (char *) realloc(rs_pixmaps[pixmap_sa], strlen(rs_pixmaps[pixmap_sa]) + 9); + strcat(rs_pixmaps[pixmap_sa], "@100x100"); + } else { + rs_pixmaps[pixmap_sa] = Word(4, buff); + } + } else if (!BEG_STRCASECMP(buff, "scroll_anchor_clicked ")) { + + if ((n = NumWords(buff) < 4) || (n > 6)) { + char *tmp = PWord(2, buff); + + print_error("parse error in file %s, line %lu: Invalid parameter list \"%s\" for attribute " + "scroll_anchor_clicked", file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + return; + } + w1 = PWord(2, buff); + h1 = PWord(3, buff); + w = strtol(w1, (char **) NULL, 0); + h = strtol(h1, (char **) NULL, 0); + if (w || h) { + rs_pixmaps[pixmap_saclk] = Word(4, buff); + rs_pixmaps[pixmap_saclk] = (char *) realloc(rs_pixmaps[pixmap_saclk], strlen(rs_pixmaps[pixmap_saclk]) + 9); + strcat(rs_pixmaps[pixmap_saclk], "@100x100"); + } else { + rs_pixmaps[pixmap_saclk] = Word(4, buff); + } +# endif /* PIXMAP_SCROLLBAR */ +# ifdef PIXMAP_MENUBAR + } else if (!BEG_STRCASECMP(buff, "menu_background ")) { + + if ((n = NumWords(buff) < 4) || (n > 6)) { + char *tmp = PWord(2, buff); + + print_error("parse error in file %s, line %lu: Invalid parameter list \"%s\" for attribute " + "menu_background", file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + return; + } + w1 = PWord(2, buff); + h1 = PWord(3, buff); + w = strtol(w1, (char **) NULL, 0); + h = strtol(h1, (char **) NULL, 0); + if (w || h) { + rs_pixmaps[pixmap_mb] = Word(4, buff); + rs_pixmaps[pixmap_mb] = (char *) realloc(rs_pixmaps[pixmap_mb], strlen(rs_pixmaps[pixmap_mb]) + 9); + strcat(rs_pixmaps[pixmap_mb], "@100x100"); + } else { + rs_pixmaps[pixmap_mb] = Word(4, buff); + } + } else if (!BEG_STRCASECMP(buff, "menu_selected ")) { + + if ((n = NumWords(buff) < 4) || (n > 6)) { + char *tmp = PWord(2, buff); + + print_error("parse error in file %s, line %lu: Invalid parameter list \"%s\" for attribute " + "menu_selected", file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + return; + } + w1 = PWord(2, buff); + h1 = PWord(3, buff); + w = strtol(w1, (char **) NULL, 0); + h = strtol(h1, (char **) NULL, 0); + if (w || h) { + rs_pixmaps[pixmap_ms] = Word(4, buff); + rs_pixmaps[pixmap_ms] = (char *) realloc(rs_pixmaps[pixmap_ms], strlen(rs_pixmaps[pixmap_ms]) + 9); + strcat(rs_pixmaps[pixmap_ms], "@100x100"); + } else { + rs_pixmaps[pixmap_ms] = Word(4, buff); + } +# endif /* PIXMAP_MENUBAR */ + + } else if (!BEG_STRCASECMP(buff, "path ")) { + rs_path = Word(2, buff); + + } else if (!BEG_STRCASECMP(buff, "anim ")) { +# ifdef BACKGROUND_CYCLING_SUPPORT + char *tmp = PWord(2, buff); + + if (tmp) { + rs_anim_pixmap_list = strdup(tmp); + } else { + print_error("parse error in file %s, line %lu: Invalid parameter list \"\" for attribute anim", file_peek_path(), file_peek_line()); + } +# else + print_error("warning: support for the anim attribute was not compiled in, ignoring"); +# endif + + } else { + print_error("parse error in file %s, line %lu: Attribute \"%s\" is not valid " + "within context pixmaps", file_peek_path(), file_peek_line(), buff); + } +#else + print_error("warning: pixmap support was not compiled in, ignoring entire context"); + file_poke_skip(1); +#endif +} + +void +parse_kanji(char *buff) +{ + +#ifdef KANJI + ASSERT(buff != NULL); + + if (!BEG_STRCASECMP(buff, "encoding ")) { + if ((rs_kanji_encoding = Word(2, buff)) != NULL) { + if (BEG_STRCASECMP(rs_kanji_encoding, "eucj") && BEG_STRCASECMP(rs_kanji_encoding, "sjis")) { + print_error("parse error in file %s, line %lu: Invalid kanji encoding mode \"%s\"", + file_peek_path(), file_peek_line(), rs_kanji_encoding); + return; + } + set_kanji_encoding(rs_kanji_encoding); + } else { + print_error("parse error in file %s, line %lu: Invalid parameter list \"\" for attribute encoding", file_peek_path(), file_peek_line()); + } + } else if (!BEG_STRCASECMP(buff, "font ")) { + + char *tmp = PWord(2, buff); + unsigned char n; + + if (NumWords(buff) != 3) { + print_error("parse error in file %s, line %lu: Invalid parameter list \"%s\" for " + "attribute font", file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + return; + } + if (isdigit(*tmp)) { + n = (unsigned char) strtoul(tmp, (char **) NULL, 0); + if (n <= 4) { + rs_kfont[n] = Word(2, tmp); + } else { + print_error("parse error in file %s, line %lu: Invalid font index %d", + file_peek_path(), file_peek_line(), n); + } + } else { + tmp = Word(1, tmp); + print_error("parse error in file %s, line %lu: Invalid font index \"%s\"", + file_peek_path(), file_peek_line(), (tmp ? tmp : "")); + free(tmp); + } + } else { + print_error("parse error in file %s, line %lu: Attribute \"%s\" is not valid " + "within context kanji", file_peek_path(), file_peek_line(), buff); + } +#else + print_error("warning: kanji support was not compiled in, ignoring entire context"); + file_poke_skip(1); +#endif +} + +void +parse_undef(char *buff) +{ + + ASSERT(buff != NULL); + + print_error("parse error in file %s, line %lu: Undefined subcontext \"%s\" within context %s", + file_peek_path(), file_peek_line(), PWord(2, buff), + ctx_id_to_name(ctx_peek())); + file_poke_skip(1); + +} + +/* The config file reader. This loads a file called MAIN, which is + located by searching CONFIG_SEARCH_PATH, PATH_ENV, and $PATH. If + it can't find a config file, it displays a warning but continues. + -- mej */ + +#ifdef USE_THEMES +int +find_theme(char *path, char *name) +{ + + register char *search_path = strdup(path); + register char *cur_path, *conf_name; + int ver; + char buff[256]; + char *theme_root, *end_ptr; + char working_dir[PATH_MAX + 1]; + + if (!name) + return (0); + + D_OPTIONS(("Searching for theme %s\n", name)); + + for (cur_path = strtok(search_path, ":"); !file_peek_fp() && cur_path; + cur_path = strtok((char *) NULL, ":")) { + + D_OPTIONS(("cur_path == %s\n", cur_path)); + if (!BEG_STRCASECMP(cur_path, "~/")) { + chdir(getenv("HOME")); + cur_path += 2; + } + if (chdir(cur_path)) { + continue; + } + getcwd(working_dir, PATH_MAX); + D_OPTIONS(("cur_path == %s wd == %s\n", cur_path, working_dir)); + if (chdir(name)) { + continue; + } + if (rs_config_file) { + conf_name = rs_config_file; + } else { + conf_name = CONFIG_FILE_NAME; + } + file_poke_fp(fopen(conf_name, "rt")); + if (file_peek_fp()) { + fgets(buff, 256, file_peek_fp()); + D_OPTIONS(("Magic line \"%s\" [%s] VERSION == \"%s\" size == %lu\n", + buff, buff + 7, VERSION, sizeof(VERSION) - 1)); + if (BEG_STRCASECMP(buff, "')) != NULL) { + *end_ptr = 0; + } + if ((ver = BEG_STRCASECMP(buff + 7, VERSION)) > 0) { + print_error("warning: config file is designed for a newer version of Eterm"); +#ifdef WARN_OLDER + } else if (ver < 0) { + print_error("warning: config file is designed for an older version of Eterm"); +#endif + } + theme_root = (char *) MALLOC(strlen(working_dir) + strlen(cur_path) + strlen(name) + 16 + 1); + sprintf(theme_root, "ETERM_THEME_ROOT=%s/%s", working_dir, name); + putenv(theme_root); + D_OPTIONS(("%s\n", theme_root)); + } + } + } + return ((int) file_peek_fp()); +} + +#endif + +int +find_config_file(char *path, char *name) +{ + + register char *search_path = strdup(path); + register char *cur_path; + int ver; + char buff[256], *end_ptr; + +#if DEBUG >= DEBUG_OPTIONS + char *pwd2; + +#endif + + if (!name) + return (0); + + D_OPTIONS(("Searching for config file %s\n", name)); + + for (cur_path = strtok(search_path, ":"); !file_peek_fp() && cur_path; + cur_path = strtok((char *) NULL, ":")) { + + D_OPTIONS(("cur_path == %s\n", cur_path)); + if (!BEG_STRCASECMP(cur_path, "~/")) { + chdir(getenv("HOME")); + cur_path += 2; + } + chdir(cur_path); +#if DEBUG >= DEBUG_OPTIONS + if (debug_level >= DEBUG_OPTIONS) { + pwd2 = (char *) malloc(2048); + getcwd(pwd2, 2048); + DPRINTF(("cur_path == %s wd == %s\n", cur_path, pwd2)); + free(pwd2); + } +#endif + + file_poke_fp(fopen(name, "rt")); + if (file_peek_fp()) { + fgets(buff, 256, file_peek_fp()); + D_OPTIONS(("Magic line \"%s\" [%s] VERSION == \"%s\" size == %lu\n", + buff, buff + 7, VERSION, sizeof(VERSION) - 1)); + if (BEG_STRCASECMP(buff, "')) != NULL) { + *end_ptr = 0; + } + if ((ver = BEG_STRCASECMP(buff + 7, VERSION)) > 0) { + print_error("warning: config file is designed for a newer version of Eterm"); +#ifdef WARN_OLDER + } else if (ver < 0) { + print_error("warning: config file is designed for an older version of Eterm"); +#endif + } + } + } + } + return ((int) file_peek_fp()); +} + +void +read_config(void) +{ + + register char *search_path; + char *env_path, *path_env, *desc; + char buff[CONFIG_BUFF]; + char *conf_name, *end_ptr; + register unsigned long i = 0; + register char *loop_path; /* -nf */ + register char *cur_path; /* -nf */ + int ver; + unsigned char id; + file_state fs = + {NULL, CONFIG_FILE_NAME, 1, 0}; + + env_path = getenv("PATH"); + if (env_path) + i += strlen(env_path); + path_env = getenv(PATH_ENV); + if (path_env) + i += strlen(path_env); + i += sizeof(CONFIG_SEARCH_PATH) + 3; + search_path = (char *) MALLOC(i); + strcpy(search_path, CONFIG_SEARCH_PATH); + if (path_env) { + strcat(search_path, ":"); + strcat(search_path, path_env); + } + if (env_path) { + strcat(search_path, ":"); + strcat(search_path, env_path); + } + file_push(fs); + + getcwd(initial_dir, PATH_MAX); + +#ifdef USE_THEMES + if (rs_config_file) { + conf_name = rs_config_file; + } else { + conf_name = CONFIG_FILE_NAME; + } + if (!find_theme(search_path, rs_theme)) { + if (!find_theme(search_path, "Eterm")) { + if (!find_theme(search_path, "DEFAULT")) { + find_config_file(search_path, conf_name); + FREE(rs_theme); + rs_theme = NULL; + } + } + } +#else + conf_name = CONFIG_FILE_NAME; + find_config_file(search_path, conf_name); +#endif + + /* Modifications by NFin8 to print out search path when unable to find the configuration + file. Done 2/17/98 -nf */ + loop_path = strdup(search_path); + if (!file_peek_fp()) { + print_error("unable to find/open config file %s, I looked in:", conf_name); + for (cur_path = strtok(loop_path, ":"); cur_path; cur_path = strtok((char *) NULL, ":")) { + fprintf(stderr, "\t%s\n", cur_path); + } + print_error("...continuing with defaults"); + FREE(search_path); + return; + } + FREE(search_path); + + file_poke_path(conf_name); + ctx_peek() = 0; /* <== This looks weird, but works -- mej */ + for (; cur_file >= 0;) { + for (; fgets(buff, CONFIG_BUFF, file_peek_fp());) { + file_inc_line(); + if (!strchr(buff, '\n')) { + print_error("parse error in file %s, line %lu: line too long", file_peek_path(), file_peek_line()); + for (; fgets(buff, CONFIG_BUFF, file_peek_fp()) && !strrchr(buff, '\n');); + continue; + } + chomp(buff); + switch (*buff) { + case '#': + case 0: + break; + case '%': + if (!BEG_STRCASECMP(PWord(1, buff + 1), "include ")) { + shell_expand(buff); + fs.path = Word(2, buff + 1); + fs.line = 1; + fs.skip_to_end = 0; + if ((fs.fp = fopen(fs.path, "rt")) == NULL) { + print_error("I/O error in file %s, line %lu: Unable to open %%include file %s " + "(%s), continuing", file_peek_path(), file_peek_line(), fs.path, + strerror(errno)); + } else { + file_push(fs); + fgets(buff, CONFIG_BUFF, file_peek_fp()); + chomp(buff); + D_OPTIONS(("Magic line \"%s\" [%s] VERSION == \"%s\" " + "size == %lu\n", buff, buff + 7, VERSION, sizeof(VERSION) - 1)); + if ((end_ptr = strchr(buff, '>')) != NULL) { + *end_ptr = 0; + } + if (BEG_STRCASECMP(buff, "')) != NULL) { + *end_ptr = 0; + } + if ((ver = BEG_STRCASECMP(buff + 7, VERSION)) > 0) { + print_error("warning: %%included file %s is designed for a newer version of Eterm", file_peek_path()); +#ifdef WARN_OLDER + } else if (ver < 0) { + print_error("warning: %%included file %s is designed for an older version of Eterm", file_peek_path()); +#endif + } + } + } + } else { + print_error("parse error in file %s, line %lu: Undefined macro \"%s\"", file_peek_path(), file_peek_line(), buff); + } + break; + case 'b': + if (file_peek_skip()) + continue; + if (!BEG_STRCASECMP(buff, "begin ")) { + desc = PWord(2, buff); + ctx_name_to_id(id, desc, i); + if (id == CTX_UNDEF) { + parse_undef(buff); + } else { + if (ctx_peek()) { + for (i = 0; i <= CTX_MAX; i++) { + if (contexts[ctx_peek()].valid_sub_contexts[i]) { + if (contexts[ctx_peek()].valid_sub_contexts[i] == id) { + ctx_push(id); + break; + } + } else { + print_error("parse error in file %s, line %lu: subcontext %s is not valid " + "within context %s", file_peek_path(), file_peek_line(), + contexts[id].description, contexts[ctx_peek()].description); + break; + } + } + } else if (id != CTX_MAIN) { + print_error("parse error in file %s, line %lu: subcontext %s is not valid " + "outside context main", file_peek_path(), file_peek_line(), + contexts[id].description); + break; + } else { + ctx_push(id); + } + } + break; + } + case 'e': + if (!BEG_STRCASECMP(buff, "end ") || !strcasecmp(buff, "end")) { + ctx_pop(); + file_poke_skip(0); + break; + } + default: + if (file_peek_skip()) + continue; + if ((id = ctx_peek())) { + shell_expand(buff); + (*ctx_id_to_func(id)) (buff); + } else { + print_error("parse error in file %s, line %lu: No established context to parse \"%s\"", + file_peek_path(), file_peek_line(), buff); + } + } + } + file_pop(); + } +} + +/* Initialize the default values for everything */ +void +init_defaults(void) +{ + + rs_name = APL_NAME " " VERSION; + +#if DEBUG >= DEBUG_MALLOC + if (debug_level >= DEBUG_MALLOC) { + memrec_init(); + } +#endif + + Options = (Opt_scrollBar); + Xdisplay = NULL; + display_name = NULL; + rs_term_name = NULL; +#ifdef CUTCHAR_OPTION + rs_cutchars = NULL; +#endif +#ifndef NO_BOLDFONT + rs_boldFont = NULL; +#endif +#ifdef PRINTPIPE + rs_print_pipe = NULL; +#endif + rs_title = NULL; /* title name for window */ + rs_iconName = NULL; /* icon name for window */ + rs_geometry = NULL; /* window geometry */ + +#if (MENUBAR_MAX) + rs_menu = NULL; +#endif +#ifdef PIXMAP_SUPPORT + rs_path = NULL; +#endif +#ifndef NO_BRIGHTCOLOR + colorfgbg = DEFAULT_RSTYLE; +#endif + + TermWin.internalBorder = DEFAULT_BORDER_WIDTH; + +} + +/* Sync up options with our internal data after parsing options and configs */ +void +post_parse(void) +{ + + register int i, count; + + if (rs_scrollbar_type) { + if (!strcasecmp(rs_scrollbar_type, "xterm")) { +#ifdef XTERM_SCROLLBAR + scrollBar.type = SCROLLBAR_XTERM; +#else + print_error("Support for xterm scrollbars was not compiled in. Sorry."); +#endif + } else if (!strcasecmp(rs_scrollbar_type, "next")) { +#ifdef NEXT_SCROLLBAR + scrollBar.type = SCROLLBAR_NEXT; +#else + print_error("Support for NeXT scrollbars was not compiled in. Sorry."); +#endif + } else if (!strcasecmp(rs_scrollbar_type, "motif")) { +#ifdef MOTIF_SCROLLBAR + scrollBar.type = SCROLLBAR_MOTIF; +#else + print_error("Support for motif scrollbars was not compiled in. Sorry."); +#endif + } else { + print_error("Unrecognized scrollbar type \"%s\".", rs_scrollbar_type); + } + } + if (rs_scrollbar_width) { + scrollBar.width = rs_scrollbar_width; + } + if (scrollBar.type == SCROLLBAR_XTERM) { + sb_shadow = 0; + } else { + sb_shadow = (Options & Opt_scrollBar_floating) ? 0 : SHADOW; + } + + /* set any defaults not already set */ + if (!rs_title) + rs_title = rs_name; + if (!rs_iconName) + rs_iconName = rs_name; + if ((TermWin.saveLines = rs_saveLines) < 0) { + TermWin.saveLines = SAVELINES; + } + /* no point having a scrollbar without having any scrollback! */ + if (!TermWin.saveLines) + Options &= ~Opt_scrollBar; + +#ifdef PRINTPIPE + if (!rs_print_pipe) + rs_print_pipe = PRINTPIPE; +#endif +#ifdef CUTCHAR_OPTION + if (!rs_cutchars) + rs_cutchars = CUTCHARS; +#endif + +#ifndef NO_BOLDFONT + if (rs_font[0] == NULL && rs_boldFont != NULL) { + rs_font[0] = rs_boldFont; + rs_boldFont = NULL; + } +#endif + for (i = 0; i < NFONTS; i++) { + if (!rs_font[i]) + rs_font[i] = def_fontName[i]; +#ifdef KANJI + if (!rs_kfont[i]) { + rs_kfont[i] = def_kfontName[i]; + } +#endif + } + +#ifdef XTERM_REVERSE_VIDEO + /* this is how xterm implements reverseVideo */ + if (Options & Opt_reverseVideo) { + if (!rs_color[fgColor]) + rs_color[fgColor] = def_colorName[bgColor]; + if (!rs_color[bgColor]) + rs_color[bgColor] = def_colorName[fgColor]; + } +#endif + + for (i = 0; i < NRS_COLORS; i++) { + if (!rs_color[i]) + rs_color[i] = def_colorName[i]; + } + +#ifdef CHANGE_SCOLLCOLOR_ON_FOCUS + /* If they don't set the unfocused color, use the scrollbar color to "turn the option off" */ + if (!rs_color[unfocusedScrollColor]) { + rs_color[unfocusedScrollColor] = rs_color[scrollColor]; + } +#endif + +#ifndef XTERM_REVERSE_VIDEO + /* this is how we implement reverseVideo */ + if (Options & Opt_reverseVideo) { + char *tmp; + + /* swap foreground/background colors */ + + tmp = rs_color[fgColor]; + rs_color[fgColor] = rs_color[bgColor]; + rs_color[bgColor] = tmp; + + tmp = def_colorName[fgColor]; + def_colorName[fgColor] = def_colorName[bgColor]; + def_colorName[bgColor] = tmp; + } +#endif + + /* convenient aliases for setting fg/bg to colors */ + color_aliases(fgColor); + color_aliases(bgColor); +#ifndef NO_CURSORCOLOR + color_aliases(cursorColor); + color_aliases(cursorColor2); +#endif /* NO_CURSORCOLOR */ +#ifndef NO_BOLDUNDERLINE + color_aliases(colorBD); + color_aliases(colorUL); +#endif /* NO_BOLDUNDERLINE */ + color_aliases(pointerColor); + color_aliases(borderColor); + + /* add startup-menu: */ +#if (MENUBAR_MAX) + /* In a borderless Eterm where the user hasn't said otherwise, make the menubar move the window */ + if (Options & Opt_borderless && rs_menubar_move == NULL) { + Options |= Opt_menubar_move; + } + delay_menu_drawing = 1; + menubar_read(rs_menu); + delay_menu_drawing--; + if (rs_menubar == *false_vals) { + delay_menu_drawing = 0; + } +#else + delay_menu_drawing = 0; +#endif + +#ifdef BACKGROUND_CYCLING_SUPPORT + if (rs_anim_pixmap_list != NULL) { + rs_anim_delay = strtoul(rs_anim_pixmap_list, (char **) NULL, 0); + fflush(stdout); + if (rs_anim_delay == 0) { + free(rs_anim_pixmap_list); + rs_anim_pixmap_list = NULL; + } else { + char *w1, *h1, *temp; + unsigned long w, h; + + count = NumWords(rs_anim_pixmap_list) - 1; /* -1 for the delay */ + rs_anim_pixmaps = (char **) MALLOC(sizeof(char *) * (count + 1)); + + for (i = 0; i < count; i++) { + temp = Word(i + 2, rs_anim_pixmap_list); /* +2 rather than +1 to account for the delay */ + if (temp == NULL) + break; + if (NumWords(temp) != 3) { + if (NumWords(temp) == 1) { + rs_anim_pixmaps[i] = temp; + } + } else { + w1 = PWord(1, temp); + h1 = PWord(2, temp); + w = strtol(w1, (char **) NULL, 0); + h = strtol(h1, (char **) NULL, 0); + if (w || h) { + rs_anim_pixmaps[i] = Word(3, temp); + rs_anim_pixmaps[i] = (char *) realloc(rs_anim_pixmaps[i], strlen(rs_anim_pixmaps[i]) + 9); + strcat(rs_anim_pixmaps[i], ";100x100"); + } else { + rs_anim_pixmaps[i] = Word(3, temp); + rs_anim_pixmaps[i] = (char *) realloc(rs_anim_pixmaps[i], strlen(rs_anim_pixmaps[i]) + 9); + strcat(rs_anim_pixmaps[i], ";0x0"); + } + FREE(temp); + } + } + rs_anim_pixmaps[count] = NULL; + free(rs_anim_pixmap_list); + } + } else { + rs_anim_delay = 0; + } +#endif + +} + +unsigned char +save_config(char *path) +{ + + register FILE *fp; + register short i; + char *tmp_str, dt_stamp[50]; + time_t cur_time = time(NULL); + struct tm *cur_tm; + struct stat fst; + + cur_tm = localtime(&cur_time); + + if (!path) { + path = (char *) MALLOC(PATH_MAX + 1); + snprintf(path, PATH_MAX, "%s/MAIN", getenv("ETERM_THEME_ROOT")); + path[PATH_MAX] = 0; + } + if (!lstat(path, &fst)) { + char bak_path[PATH_MAX], timestamp[16]; + + /* File exists. Make a backup. */ + strftime(timestamp, 16, "%Y%m%d.%H%M%S", cur_tm); + snprintf(bak_path, PATH_MAX - 1, "%s.%s", path, timestamp); + link(path, bak_path); + unlink(path); + } + if ((fp = fopen(path, "w")) == NULL) { + print_error("Unable to save configuration to file \"%s\" -- %s\n", path, strerror(errno)); + return errno; + } + strftime(dt_stamp, 50, "%x at %X", cur_tm); + fprintf(fp, "<" APL_NAME "-" VERSION ">\n"); + fprintf(fp, "# Eterm Configuration File\n"); + fprintf(fp, "# Automatically generated by " APL_NAME "-" VERSION " on %s\n", dt_stamp); + + fprintf(fp, "begin main\n\n"); + + fprintf(fp, " begin color\n"); + fprintf(fp, " foreground %s\n", rs_color[fgColor]); + fprintf(fp, " background %s\n", rs_color[bgColor]); + fprintf(fp, " tint 0x%06x\n", rs_tintMask); + fprintf(fp, " shade %lu%%\n", rs_shadePct); + fprintf(fp, " cursor %s\n", rs_color[cursorColor]); + fprintf(fp, " cursor_text %s\n", rs_color[cursorColor2]); + fprintf(fp, " menu_text %s\n", rs_color[menuTextColor]); + fprintf(fp, " scrollbar %s\n", rs_color[scrollColor]); + fprintf(fp, " unfocusedscrollbar %s\n", rs_color[unfocusedScrollColor]); + fprintf(fp, " pointer %s\n", rs_color[pointerColor]); + fprintf(fp, " video normal\n"); + for (i = 0; i < 16; i++) { + fprintf(fp, " color %d %s\n", i, rs_color[minColor + i]); + } + if (rs_color[colorBD]) { + fprintf(fp, " color bd %s\n", rs_color[colorBD]); + } + if (rs_color[colorUL]) { + fprintf(fp, " color ul %s\n", rs_color[colorUL]); + } + fprintf(fp, " end color\n\n"); + + fprintf(fp, " begin attributes\n"); + if (rs_geometry) { + fprintf(fp, " geometry %s\n", rs_geometry); + } + XFetchName(Xdisplay, TermWin.parent, &tmp_str); + fprintf(fp, " title %s\n", tmp_str); + fprintf(fp, " name %s\n", rs_name); + XGetIconName(Xdisplay, TermWin.parent, &tmp_str); + fprintf(fp, " iconname %s\n", tmp_str); + if (rs_desktop != -1) { + fprintf(fp, " desktop %d\n", rs_desktop); + } + fprintf(fp, " scrollbar_type %s\n", (scrollBar.type == SCROLLBAR_XTERM ? "xterm" : (scrollBar.type == SCROLLBAR_MOTIF ? "motif" : "next"))); + fprintf(fp, " scrollbar_width %d\n", scrollBar.width); + for (i = 0; i < 5; i++) { + fprintf(fp, " font %d %s\n", i, rs_font[i]); + } +#ifndef NO_BOLDFONT + if (rs_boldFont) { + fprintf(fp, " font bold %s\n", i, rs_boldFont); + } +#endif + fprintf(fp, " end attributes\n\n"); + + fprintf(fp, " begin pixmaps\n"); + if (rs_pixmaps[pixmap_bg] && *rs_pixmaps[pixmap_bg]) { + fprintf(fp, " background %s %s\n", (Options & Opt_pixmapScale ? "-1 -1" : "0 0"), rs_pixmaps[pixmap_bg]); + } + if (rs_icon) { + fprintf(fp, " icon %s\n", rs_icon); + } + if (rs_path) { + fprintf(fp, " path \"%s\"\n", rs_path); + } + if (rs_anim_delay) { + fprintf(fp, " anim %d ", rs_anim_delay); + for (i = 0; rs_anim_pixmaps[i]; i++) { + fprintf(fp, "\"%s\" ", rs_anim_pixmaps[i]); + } + fprintf(fp, "\n"); + } + fprintf(fp, " end pixmaps\n\n"); + +#ifdef KANJI + fprintf(fp, " begin kanji\n"); + fprintf(fp, " encoding %s\n", rs_kanji_encoding); + for (i = 0; i < 5; i++) { + fprintf(fp, " font %d %s\n", i, rs_kfont[i]); + } + fprintf(fp, " end kanji\n\n"); +#endif + + fprintf(fp, " begin toggles\n"); + fprintf(fp, " map_alert %d\n", (Options & Opt_mapAlert ? 1 : 0)); + fprintf(fp, " visual_bell %d\n", (Options & Opt_visualBell ? 1 : 0)); + fprintf(fp, " login_shell %d\n", (Options & Opt_loginShell ? 1 : 0)); + fprintf(fp, " scrollbar %d\n", (Options & Opt_scrollBar ? 1 : 0)); + fprintf(fp, " menubar %d\n", (menuBar.state ? 1 : 0)); + fprintf(fp, " utmp_logging %d\n", (Options & Opt_utmpLogging ? 1 : 0)); + fprintf(fp, " meta8 %d\n", (Options & Opt_meta8 ? 1 : 0)); + fprintf(fp, " iconic %d\n", (Options & Opt_iconic ? 1 : 0)); + fprintf(fp, " home_on_echo %d\n", (Options & Opt_homeOnEcho ? 1 : 0)); + fprintf(fp, " home_on_input %d\n", (Options & Opt_homeOnInput ? 1 : 0)); + fprintf(fp, " home_on_refresh %d\n", (Options & Opt_homeOnRefresh ? 1 : 0)); + fprintf(fp, " scrollbar_floating %d\n", (Options & Opt_scrollBar_floating ? 1 : 0)); + fprintf(fp, " scrollbar_right %d\n", (Options & Opt_scrollBar_right ? 1 : 0)); + fprintf(fp, " scrollbar_popup %d\n", (Options & Opt_scrollbar_popup ? 1 : 0)); + fprintf(fp, " borderless %d\n", (Options & Opt_borderless ? 1 : 0)); + fprintf(fp, " save_under %d\n", (Options & Opt_saveUnder ? 1 : 0)); + fprintf(fp, " trans %d\n", (Options & Opt_pixmapTrans ? 1 : 0)); + fprintf(fp, " watch_desktop %d\n", (Options & Opt_watchDesktop ? 1 : 0)); + fprintf(fp, " no_cursor %d\n", (Options & Opt_noCursor ? 1 : 0)); + fprintf(fp, " menubar_move %d\n", (Options & Opt_menubar_move ? 1 : 0)); + fprintf(fp, " pause %d\n", (Options & Opt_pause ? 1 : 0)); + fprintf(fp, " xterm_select %d\n", (Options & Opt_xterm_select ? 1 : 0)); + fprintf(fp, " select_line %d\n", (Options & Opt_select_whole_line ? 1 : 0)); + fprintf(fp, " select_trailing_spaces %d\n", (Options & Opt_select_trailing_spaces ? 1 : 0)); + fprintf(fp, " viewport_mode %d\n", (Options & Opt_viewport_mode ? 1 : 0)); + fprintf(fp, " end toggles\n\n"); + + fprintf(fp, " begin keyboard\n"); + tmp_str = XKeysymToString(ks_smallfont); + if (tmp_str) { + fprintf(fp, " smallfont_key %s\n", tmp_str); + } + tmp_str = XKeysymToString(ks_bigfont); + if (tmp_str) { + fprintf(fp, " bigfont_key %s\n", XKeysymToString(ks_bigfont)); + } + for (i = 0; i < 256; i++) { + if (KeySym_map[i]) { + fprintf(fp, " keysym 0xff%02x \"%s\"\n", i, (KeySym_map[i] + 1)); + } + } +#ifdef GREEK_SUPPORT + if (rs_greek_keyboard) { + fprintf(fp, " greek on %s\n", rs_greek_keyboard); + } +#endif + fprintf(fp, " app_keypad %d\n", (PrivateModes & PrivMode_aplKP ? 1 : 0)); + fprintf(fp, " app_cursor %d\n", (PrivateModes & PrivMode_aplCUR ? 1 : 0)); + fprintf(fp, " end keyboard\n\n"); + + fprintf(fp, " begin misc\n"); +#ifdef PRINTPIPE + if (rs_print_pipe) { + fprintf(fp, " print_pipe \"%s\"\n", rs_print_pipe); + } +#endif + fprintf(fp, " save_lines %d\n", rs_saveLines); + fprintf(fp, " min_anchor_size %d\n", rs_min_anchor_size); + fprintf(fp, " border_width %d\n", TermWin.internalBorder); + fprintf(fp, " menu %s\n", rs_menu); + fprintf(fp, " term_name %s\n", getenv("TERM")); + fprintf(fp, " debug %d\n", debug_level); + if (Options & Opt_exec && rs_execArgs) { + fprintf(fp, " exec "); + for (i = 0; rs_execArgs[i]; i++) { + fprintf(fp, "'%s' ", rs_execArgs[i]); + } + fprintf(fp, "\n"); + } +#ifdef CUTCHAR_OPTIONS + if (rs_cutchars) { + fprintf(fp, " cut_chars \"%s\"\n", rs_cutchars); + } +#endif + fprintf(fp, " end misc\n\n"); + fprintf(fp, "end main\n"); + + fclose(fp); + return 0; +} diff --git a/src/options.h b/src/options.h new file mode 100644 index 0000000..c5a7895 --- /dev/null +++ b/src/options.h @@ -0,0 +1,107 @@ +/* options.h -- Eterm options module header file + * -- 25 July 1997, mej + * + * This file is original work by Michael Jennings and + * Tuomo Venalainen . This file, and any other file + * bearing this same message or a similar one, is distributed under + * the GNU Public License (GPL) as outlined in the COPYING file. + * + * Copyright (C) 1997, Michael Jennings and Tuomo Venalainen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _OPTIONS_H_ +#define _OPTIONS_H_ +/* includes */ +#include +#include /* Xlib, Xutil, Xresource, Xfuncproto */ +#include "feature.h" + +/* prototypes */ +unsigned long NumWords(const char *str); + +/* extern variables */ +extern char **rs_execArgs; /* Args to exec (-e or --exec) */ +extern char *rs_title; /* Window title */ +extern char *rs_iconName; /* Icon name */ +extern char *rs_geometry; /* Geometry string */ +extern int rs_desktop; /* Startup desktop */ +extern int rs_saveLines; /* Lines in the scrollback buffer */ +extern unsigned short rs_min_anchor_size; /* Minimum size, in pixels, of the scrollbar anchor */ +extern const char *rs_scrollBar_right; +extern const char *rs_scrollBar_floating; +extern const char *rs_scrollbar_popup; +extern char *rs_viewport_mode; +extern const char *rs_term_name; +extern const char *rs_menubar; +extern const char *rs_menu; +extern const char *rs_menubar_move; +extern const char *rs_pause; +extern char *rs_icon; +extern char *rs_scrollbar_type; +extern unsigned long rs_scrollbar_width; +extern char *rs_scrollbar_type; +extern char *rs_anim_pixmap_list; +extern char **rs_anim_pixmaps; +extern time_t rs_anim_delay; +extern char *rs_path; + +extern const char *true_vals[]; +extern const char *false_vals[]; +#define BOOL_OPT_ISTRUE(s) (!strcasecmp((s), true_vals[0]) || !strcasecmp((s), true_vals[1]) \ + || !strcasecmp((s), true_vals[2]) || !strcasecmp((s), true_vals[3])) +#define BOOL_OPT_ISFALSE(s) (!strcasecmp((s), false_vals[0]) || !strcasecmp((s), false_vals[1]) \ + || !strcasecmp((s), false_vals[2]) || !strcasecmp((s), false_vals[3])) + +#ifdef CUTCHAR_OPTION +extern char *rs_cutchars; +#endif + +#ifdef KEYSYM_ATTRIBUTE +extern unsigned char *KeySym_map[256]; +#endif + +#if defined (HOTKEY_CTRL) || defined (HOTKEY_META) +extern KeySym ks_bigfont; +extern KeySym ks_smallfont; +#endif + +#ifdef PIXMAP_SUPPORT +extern char *rs_pixmaps[]; + +#define pixmap_bg 0 +#define pixmap_sb 1 +#define pixmap_up 2 +#define pixmap_upclk 3 +#define pixmap_dn 4 +#define pixmap_dnclk 5 +#define pixmap_sa 6 +#define pixmap_saclk 7 +#define pixmap_mb 8 +#define pixmap_ms 9 +#endif /* PIXMAP_SUPPORT */ + +/* prototypes */ +_XFUNCPROTOBEGIN + +extern void get_options(int, char **); +extern char *chomp(char *); +extern void read_config(void); + +_XFUNCPROTOEND + +#endif /* _OPTIONS_H_ */ diff --git a/src/pixmap.c b/src/pixmap.c new file mode 100644 index 0000000..08f465d --- /dev/null +++ b/src/pixmap.c @@ -0,0 +1,1611 @@ +/* pixmap.c -- Eterm pixmap handling routines + * -- vendu & mej + * + * This file is original work by Michael Jennings and + * Tuomo Venalainen . This file, and any other file + * bearing this same message or a similar one, is distributed under + * the GNU Public License (GPL) as outlined in the COPYING file. + * + * Copyright (C) 1997, Michael Jennings and Tuomo Venalainen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +static const char cvs_ident[] = "$Id$"; + +#include +#include +#include +#include +#include + +#include "main.h" +#include "feature.h" +#include "../libmej/debug.h" +#include "mem.h" +#include "options.h" +#ifdef PIXMAP_SUPPORT +# include "pixmap.h" +# include "screen.h" +# ifdef USE_POSIX_THREADS +# include "threads.h" +# endif +# include "Eterm.xpm" /* Icon pixmap */ +#endif +#ifdef PIXMAP_SCROLLBAR +# include "scrollbar.h" +#endif +#ifdef PIXMAP_MENUBAR +# include "menubar.h" +#endif + +#ifdef USE_IMLIB +# include "eterm_imlib.h" +#endif + +#ifdef PIXMAP_SUPPORT +/* Specifying a single extension is irrelevant with Imlib. -vendu */ +# ifdef USE_IMLIB +# define PIXMAP_EXT NULL +# endif + +extern XWindowAttributes attr; +extern char *rs_path; +extern char *rs_pixmapScale; + +# ifdef PIXMAP_OFFSET +extern const char *rs_pixmapTrans; +extern unsigned int rs_shadePct; +extern unsigned long rs_tintMask; +Pixmap desktop_pixmap = None; +Pixmap viewport_pixmap = None; +Window desktop_window = None; + +# endif +# ifdef USE_EFFECTS +int fade_in(Pixmap *, ImlibImage *, int); +int fade_out(Pixmap *, ImlibImage *, int); + +# endif + +extern short bg_needs_update; + +void set_bgPixmap(const char * /* file */ ); +void resize_subwindows(int, int); + +# ifdef USE_POSIX_THREADS +extern short bg_set; +extern char *sig_to_str(int sig); +extern pthread_t resize_sub_thr; +extern pthread_attr_t resize_sub_thr_attr; + +# endif + +# ifdef PIXMAP_OFFSET +extern XSizeHints szHint; +Pixmap offset_pixmap(Pixmap, int, int, renderop_t); + +# endif + +pixmap_t bgPixmap = +{0, 0, 50, 50, None}; + +# ifdef PIXMAP_SCROLLBAR +pixmap_t upPixmap = +{0, 0, 50, 50, None}; +pixmap_t dnPixmap = +{0, 0, 50, 50, None}; +pixmap_t sbPixmap = +{0, 0, 50, 50, None}; +pixmap_t saPixmap = +{0, 0, 50, 50, None}; + +# endif + +# ifdef USE_IMLIB +ImlibData *imlib_id = NULL; +imlib_t imlib_bg = +{NULL, 0, 0}; + +# ifdef PIXMAP_SCROLLBAR +imlib_t imlib_up = +{NULL, 0, 0}; +imlib_t imlib_dn = +{NULL, 0, 0}; +imlib_t imlib_sb = +{NULL, 0, 0}; +imlib_t imlib_sa = +{NULL, 0, 0}; + +# endif + +# ifdef PIXMAP_MENUBAR +extern menu_t *ActiveMenu; +pixmap_t mbPixmap = +{0, 0, 50, 50, None}; +pixmap_t mb_selPixmap = +{0, 0, 50, 50, None}; + +# ifdef USE_IMLIB +imlib_t imlib_mb = +{NULL, 0, 0}; +imlib_t imlib_ms = +{NULL, 0, 0}; + +# endif +# endif + +inline ImlibImage * +ReadImageViaImlib(Display * d, const char *filename) +{ + Image *tmp; + + D_IMLIB(("ReadImageViaImlib(%s)\n", filename)); + + tmp = ImlibLoadImage(imlib_id, (char *) filename, NULL); + return tmp; +} + +# endif /* USE_IMLIB */ + +/* + * These GEOM strings indicate absolute size/position: + * @ `WxH+X+Y' + * @ `WxH+X' -> Y = X + * @ `WxH' -> Y = X = 50 + * @ `W+X+Y' -> H = W + * @ `W+X' -> H = W, Y = X + * @ `W' -> H = W, X = Y = 50 + * @ `0xH' -> H *= H/100, X = Y = 50 (W unchanged) + * @ `Wx0' -> W *= W/100, X = Y = 50 (H unchanged) + * @ `=+X+Y' -> (H, W unchanged) + * @ `=+X' -> Y = X (H, W unchanged) + * + * These GEOM strings adjust position relative to current position: + * @ `+X+Y' + * @ `+X' -> Y = X + * + * And this GEOM string is for querying current scale/position: + * @ `?' + */ + + +/* '[', 2*4 + 2*3 digits + 3 delimiters, ']'. -vendu */ +# define GEOM_LEN 19 /* #undef'd immediately after scale_pixmap(). - vendu */ +int +scale_pixmap(const char *geom, pixmap_t * pmap) +{ + + static char str[GEOM_LEN + 1] = + {'\0'}; + int w = 0, h = 0, x = 0, y = 0; + int flags; + int changed = 0; + char *p; + int n; + Screen *scr; + + if (geom == NULL) + return 0; + scr = ScreenOfDisplay(Xdisplay, Xscreen); + if (!scr) + return; + + D_PIXMAP(("scale_pixmap(\"%s\")\n", geom)); + if (!strcmp(geom, "?")) { +# if 0 + sprintf(str, /* Nobody in their right mind would want this to happen -- mej */ + "[%dx%d+%d+%d]", + bgPixmap.w, + bgPixmap.h, + bgPixmap.x, + bgPixmap.y); + xterm_seq(XTerm_title, str); +# endif + return 0; + } + if ((p = strchr(geom, ';')) == NULL) + p = strchr(geom, '\0'); + n = (p - geom); + if (n > GEOM_LEN - 1) + return 0; + + strncpy(str, geom, n); + str[n] = '\0'; + + flags = XParseGeometry(str, &x, &y, &w, &h); + + if (!flags) { + flags |= WidthValue; /* default is tile */ + w = 0; + } + if (flags & WidthValue) { + if (!(flags & XValue)) { + x = 50; + } + if (!(flags & HeightValue)) + h = w; + + if (w && !h) { + w = pmap->w * ((float) w / 100); + h = pmap->h; + } else if (h && !w) { + w = pmap->w; + h = pmap->h * ((float) h / 100); + } + /* Can't get any bigger than fullscreen */ + if (w > scr->width) + w = scr->width; + if (h > scr->height) + h = scr->height; + + if (pmap->w != w) { + pmap->w = w; + changed++; + } + if (pmap->h != h) { + pmap->h = h; + changed++; + } + } + if (!(flags & YValue)) { + if (flags & XNegative) + flags |= YNegative; + y = x; + } + if (!(flags & WidthValue) && geom[0] != '=') { + x += pmap->x; + y += pmap->y; + } else { + if (flags & XNegative) + x += 100; + if (flags & YNegative) + y += 100; + } + + x = (x <= 0 ? 0 : (x >= 100 ? 100 : x)); + y = (y <= 0 ? 0 : (y >= 100 ? 100 : y));; + if (pmap->x != x) { + pmap->x = x; + changed++; + } + if (pmap->y != y) { + pmap->y = y; + changed++; + } + D_PIXMAP(("scale_pixmap() exiting with pmap.w == %d, pmap.h == %d, pmap.x == %d, pmap.y == %d\n", pmap->w, pmap->h, pmap->x, pmap->y)); + return changed; +} +# undef GEOM_LEN + +void +render_pixmap(Window win, imlib_t image, pixmap_t pmap, int which, renderop_t renderop) +{ + + XGCValues gcvalue; + GC gc; + unsigned int width = 0; + unsigned int height = 0; + float p, incr; + int xsize, ysize; + Pixmap pixmap = None; + unsigned short rendered = 0; + +# ifdef PIXMAP_OFFSET + static unsigned int last_width = 0, last_height = 0, last_x = 0, last_y = 0; + int x, y; + int px, py; + unsigned int pw, ph, pb, pd; + Window w; + Screen *scr; + +# ifdef PIXMAP_SCROLLBAR + int scr_x, scr_y, scr_w, scr_h; + Window dummy; + +# endif +# endif /* PIXMAP_OFFSET */ + + scr = ScreenOfDisplay(Xdisplay, Xscreen); + if (!scr) + return; + + if (!image.im +# ifdef PIXMAP_OFFSET + && !(Options & Opt_pixmapTrans) +# endif + ) { + D_PIXMAP(("render_pixmap(): no image loaded\n")); + + if (!(background_is_pixmap())) { + XSetWindowBackground(Xdisplay, win, PixColors[bgColor]); + XClearWindow(Xdisplay, win); + } + return; + } + switch (which) { + case pixmap_bg: + D_PIXMAP(("render_pixmap(0x%x): rendering pixmap_bg\n", image.im)); + width = +#ifdef PIXMAP_OFFSET + Options & Opt_viewport_mode ? scr->width : +#endif + TermWin_TotalWidth(); + height = +#ifdef PIXMAP_OFFSET + Options & Opt_viewport_mode ? scr->height : +#endif + TermWin_TotalHeight(); + break; + case pixmap_sb: + if ((scrollbar_is_pixmapped()) + || (!(Options & Opt_pixmapTrans))) { + D_PIXMAP(("render_pixmap(): rendering pixmap_sb\n")); + width = scrollbar_total_width(); + height = TermWin.height; + } + break; + case pixmap_sa: + if (scrollbar_is_pixmapped()) { + D_PIXMAP(("render_pixmap(): rendering pixmap_sa\n")); + width = scrollbar_total_width(); + height = scrollbar_anchor_max_height(); + } + break; + case pixmap_saclk: + if (scrollbar_is_pixmapped()) { + D_PIXMAP(("render_pixmap(): rendering pixmap_saclk\n")); + width = scrollbar_total_width(); + height = scrollbar_anchor_max_height(); + } + break; + case pixmap_up: + if (scrollbar_is_pixmapped()) { + D_PIXMAP(("render_pixmap(): rendering pixmap_up\n")); + width = scrollbar_total_width(); + height = scrollbar_arrow_height(); + } + break; + case pixmap_upclk: + if (scrollbar_is_pixmapped()) { + D_PIXMAP(("render_pixmap(): rendering pixmap_upclk\n")); + width = scrollbar_total_width(); + height = scrollbar_arrow_height(); + } + break; + case pixmap_dn: + if (scrollbar_is_pixmapped()) { + D_PIXMAP(("render_pixmap(): rendering pixmap_dn\n")); + width = scrollbar_total_width(); + height = scrollbar_arrow_height(); + } + break; + case pixmap_dnclk: + if (scrollbar_is_pixmapped()) { + D_PIXMAP(("render_pixmap(): rendering pixmap_dnclk\n")); + width = scrollbar_total_width(); + height = scrollbar_arrow_height(); + } + break; + case pixmap_mb: + if (menubar_is_pixmapped()) { + D_PIXMAP(("render_pixmap(): rendering pixmap_mb\n")); + width = menuBar_TotalHeight(); + height = menuBar_TotalHeight(); + } + break; + default: + D_PIXMAP(("render_pixmap(): nothing to render\n")); + return; + } + + if (!(width) || !(height)) + return; + + gcvalue.foreground = PixColors[bgColor]; + gc = XCreateGC(Xdisplay, win, GCForeground, &gcvalue); + +# if defined(PIXMAP_OFFSET) + if (Options & Opt_pixmapTrans) { + + if (desktop_window == None) { + get_desktop_window(); + } + if (desktop_window == None) { + print_error("Unable to locate desktop window. If you are running Enlightenment, please\n" + "restart. If not, please set your background image with Esetroot, then try again."); + Options &= ~(Opt_pixmapTrans); + render_pixmap(win, image, pmap, which, renderop); + return; + } + if (desktop_pixmap == None) { + desktop_pixmap = get_desktop_pixmap(); + last_x = last_y = -1; + if (desktop_pixmap != None) { +#ifdef IMLIB_TRANS + if (imlib_bg.im != NULL) { + D_IMLIB(("ImlibDestroyImage()\n")); + Imlib_kill_image(imlib_id, imlib_bg.im); /* No sense in caching transparency stuff */ + imlib_bg.im = NULL; + } + imlib_bg.im = Imlib_create_image_from_drawable(imlib_id, desktop_pixmap, None, 0, 0, scr->width, scr->height); + colormod_trans(imlib_bg, gc, scr->width, scr->height); + D_IMLIB(("ImlibRender(0x%x@%dx%d)\n", imlib_bg.im, scr->width, scr->height)); + ImlibRender(imlib_id, imlib_bg.im, scr->width, scr->height); + desktop_pixmap = Imlib_move_image(imlib_id, imlib_bg.im); + Imlib_kill_image(imlib_id, imlib_bg.im); /* No sense in caching transparency stuff */ + imlib_bg.im = NULL; +#else + pixmap = desktop_pixmap; + XGetGeometry(Xdisplay, desktop_pixmap, &w, &px, &py, &pw, &ph, &pb, &pd); + if (pw < scr->width || ph < scr->height) { + desktop_pixmap = XCreatePixmap(Xdisplay, win, pw, ph, Xdepth); + XCopyArea(Xdisplay, pixmap, desktop_pixmap, gc, 0, 0, pw, ph, 0, 0); + colormod_trans(desktop_pixmap, gc, pw, ph); + } else { + desktop_pixmap = XCreatePixmap(Xdisplay, win, scr->width, scr->height, Xdepth); + XCopyArea(Xdisplay, pixmap, desktop_pixmap, gc, 0, 0, scr->width, scr->height, 0, 0); + colormod_trans(desktop_pixmap, gc, scr->width, scr->height); + } +#endif + } + } + if (desktop_pixmap != None) { + XTranslateCoordinates(Xdisplay, win, desktop_window, 0, 0, &x, &y, &w); + if (width != last_width || height != last_height || x != last_x || y != last_y) { + if (TermWin.pixmap != None) { + XFreePixmap(Xdisplay, TermWin.pixmap); + } + TermWin.pixmap = XCreatePixmap(Xdisplay, win, width, height, Xdepth); + D_PIXMAP(("desktop_pixmap == %08x, TermWin.pixmap == %08x\n", desktop_pixmap, TermWin.pixmap)); + if (TermWin.pixmap != None) { + XGetGeometry(Xdisplay, desktop_pixmap, &w, &px, &py, &pw, &ph, &pb, &pd); + if (pw < scr->width || ph < scr->height) { + XFreeGC(Xdisplay, gc); + gc = XCreateGC(Xdisplay, desktop_pixmap, 0, &gcvalue); + XSetTile(Xdisplay, gc, desktop_pixmap); + XSetTSOrigin(Xdisplay, gc, pw - (x % pw), ph - (y % ph)); + XSetFillStyle(Xdisplay, gc, FillTiled); + XFillRectangle(Xdisplay, TermWin.pixmap, gc, 0, 0, scr->width, scr->height); + } else { + XCopyArea(Xdisplay, desktop_pixmap, TermWin.pixmap, gc, x, y, width, height, 0, 0); + } + } + } + last_x = x; + last_y = y; + } else { + last_x = last_y = -1; + } + if (TermWin.pixmap != None) { + pmap.pixmap = TermWin.pixmap; + } + last_width = width; + last_height = height; +# ifdef PIXMAP_SCROLLBAR + if (scrollbar_visible() && Options & Opt_scrollBar_floating) { + scr_w = scrollbar_total_width(); + scr_h = height; + if (desktop_pixmap != None) { + sbPixmap.pixmap = XCreatePixmap(Xdisplay, TermWin.parent, scr_w, scr_h, Xdepth); + D_PIXMAP(("0x%x = XCreatePixmap(%d, %d)\n", sbPixmap.pixmap, scr_w, scr_h)); + XTranslateCoordinates(Xdisplay, scrollBar.win, desktop_window, 0, 0, &scr_x, &scr_y, &dummy); + + XGetGeometry(Xdisplay, desktop_pixmap, &w, &px, &py, &pw, &ph, &pb, &pd); + XFreeGC(Xdisplay, gc); + gc = XCreateGC(Xdisplay, desktop_pixmap, 0, &gcvalue); + XSetTile(Xdisplay, gc, desktop_pixmap); + XSetTSOrigin(Xdisplay, gc, pw - (scr_x % pw), ph - (scr_y % ph)); + XSetFillStyle(Xdisplay, gc, FillTiled); + XFillRectangle(Xdisplay, sbPixmap.pixmap, gc, 0, 0, scr_w, scr_h); + + D_PIXMAP(("XSetWindowBackgroundPixmap(sbPixmap.pixmap)\n")); + } + XSetWindowBackgroundPixmap(Xdisplay, scrollBar.win, sbPixmap.pixmap); + D_PIXMAP(("XFreePixmap(sbPixmap.pixmap)\n")); + /*XFreePixmap(Xdisplay, sbPixmap.pixmap); */ + XClearWindow(Xdisplay, scrollBar.win); + } +# endif /* PIXMAP_SCROLLBAR */ + } else +# endif + { + +# ifdef PIXMAP_OFFSET + last_width = last_height = last_x = last_y = 0; +# endif + + if (image.im) { + int w = pmap.w; + int h = pmap.h; + int x = pmap.x; + int y = pmap.y; + + xsize = image.im->rgb_width; + ysize = image.im->rgb_height; + + D_PIXMAP(("render_pixmap(): w == %d, h == %d, x == %d, y == %d\n", w, h, x, y)); + + /* Don't tile too big or scale too small */ + if (w > scr->width || h > scr->height) { + w = 1; /* scale to 100% */ + } else if (width > (10 * xsize) || height > (10 * ysize)) { + w = 0; /* tile */ + } +# ifdef PIXMAP_OFFSET + if (Options & Opt_viewport_mode) { + D_PIXMAP(("Viewport mode enabled. viewport_pixmap == 0x%08x and TermWin.pixmap == 0x%08x\n", + viewport_pixmap, TermWin.pixmap)); + if (viewport_pixmap == None) { + if (w) { + D_PIXMAP(("Scaling image to %dx%d\n", scr->width, scr->height)); + colormod_pixmap(image, gc, scr->width, scr->height); + Imlib_render(imlib_id, image.im, scr->width, scr->height); + } else { + D_PIXMAP(("Tiling image at %dx%d\n", xsize, ysize)); + colormod_pixmap(image, gc, xsize, ysize); + Imlib_render(imlib_id, image.im, xsize, ysize); + } + viewport_pixmap = Imlib_copy_image(imlib_id, image.im); + } + if (TermWin.pixmap != None) { + XGetGeometry(Xdisplay, TermWin.pixmap, &dummy, &px, &py, &pw, &ph, &pb, &pd); + if (pw != TermWin_TotalWidth() || ph != TermWin_TotalHeight()) { + XFreePixmap(Xdisplay, TermWin.pixmap); + TermWin.pixmap = None; + } + } + if (TermWin.pixmap == None) { + TermWin.pixmap = XCreatePixmap(Xdisplay, TermWin.vt, TermWin_TotalWidth(), TermWin_TotalHeight(), Xdepth); + D_PIXMAP(("Created pixmap == 0x%08x and TermWin.pixmap == 0x%08x\n", viewport_pixmap, TermWin.pixmap)); + } + XTranslateCoordinates(Xdisplay, win, Xroot, 0, 0, &x, &y, &dummy); + D_PIXMAP(("Translated coords are %d, %d\n", x, y)); + if (w) { + XCopyArea(Xdisplay, viewport_pixmap, TermWin.pixmap, gc, x, y, TermWin_TotalWidth(), TermWin_TotalHeight(), 0, 0); + } else { + XFreeGC(Xdisplay, gc); + gc = XCreateGC(Xdisplay, viewport_pixmap, 0, &gcvalue); + XSetTile(Xdisplay, gc, viewport_pixmap); + XSetTSOrigin(Xdisplay, gc, xsize - (x % xsize), ysize - (y % ysize)); + XSetFillStyle(Xdisplay, gc, FillTiled); + XFillRectangle(Xdisplay, TermWin.pixmap, gc, 0, 0, TermWin_TotalWidth(), TermWin_TotalHeight()); + } + pmap.pixmap = TermWin.pixmap; + } else +# endif + + if (w) { + + /* + * horizontal scaling + */ + + D_PIXMAP(("render_pixmap(): horizontal scaling\n")); + + incr = (float) xsize; + + p = 0; + + if (w == 1) { + /* display image directly - no scaling at all */ + incr = width; + + D_PIXMAP(("render_pixmap(): no horizontal scaling\n")); + + if (xsize <= width) { + w = xsize; + x = (width - w) / 2; + w += x; + } else { + x = 0; + w = width; + } + } else if (w < 10) { + incr *= w; /* fit W images across screen */ + x = 0; + w = width; + } else { + incr *= 100.0 / w; + /* contract */ + if (w < 100) { + w = (w * width) / 100; + /* position */ + if (x >= 0) { + float pos; + + pos = (float) x / 100 * width - (w / 2); + + x = (width - w); + if (pos <= 0) + x = 0; + else if (pos < x) + x = pos; + } else { + x = (width - w) / 2; + } + w += x; + } else if (w >= 100) { + /* expand + */ + /* position */ + if (x > 0) { + float pos; + + pos = (float) x / 100 * xsize - (incr / 2); + + p = xsize - (incr); + if (pos <= 0) + p = 0; + else if (pos < p) + p = pos; + } + x = 0; + w = width; + } + } + incr /= width; + + /* + * vertical scaling + */ + + D_PIXMAP(("render_pixmap(): vertical scaling\n")); + + incr = (float) ysize; + p = 0; + + if (h == 1) { + /* display image directly - no scaling at all */ + incr = height; + + D_PIXMAP(("render_pixmap(): no vertical scaling\n")); + + if (ysize <= height) { + h = ysize; + y = (height - h) / 2; + h += y; + } else { + y = 0; + h = height; + } + } else if (h < 10) { + incr *= h; /* fit H images across screen */ + y = 0; + h = height; + } else { + incr *= 100.0 / h; + /* contract */ + if (h < 100) { + h = (h * height) / 100; + /* position */ + if (y >= 0) { + float pos; + + pos = (float) y / 100 * height - (h / 2); + + y = (height - h); + if (pos < 0.0f) + y = 0; + else if (pos < y) + y = pos; + } else { + y = (height - h) / 2; + } + h += y; + } else if (h >= 100) { + /* expand + */ + /* position */ + if (y > 0) { + float pos; + + pos = (float) y / 100 * ysize - (incr / 2); + + p = ysize - (incr); + if (pos < 0) + p = 0; + else if (pos < p) + p = pos; + } + y = 0; + h = height; + } + } + incr /= height; + + image.last_w = w; + image.last_h = h; + + D_IMLIB(("ImlibRender(0x%x@%dx%d)\n", image.im, w, h)); + colormod_pixmap(image, gc, w, h); + ImlibRender(imlib_id, image.im, w, h); + + D_IMLIB(("pmap.pixmap = ImlibCopyImageToPixmap(0x%x)\n", image.im)); + pmap.pixmap = ImlibCopyImageToPixmap(imlib_id, image.im); + + } else { + /* if (w), light years above. -vendu */ + /* tiled */ + + D_PIXMAP(("render_pixmap(): tiling pixmap\n")); + + if (!((Options & Opt_pixmapTrans) && rendered)) { + D_IMLIB(("ImlibRender(0x%x@%dx%d)\n", image.im, xsize, ysize)); + colormod_pixmap(image, gc, xsize, ysize); + ImlibRender(imlib_id, image.im, xsize, ysize); + rendered = 1; + } + D_IMLIB(("pixmap = ImlibCopyImageToPixmap()\n")); + pixmap = ImlibCopyImageToPixmap(imlib_id, image.im); + +# ifdef PIXMAP_OFFSET + if (Options & Opt_pixmapTrans) { + D_IMLIB(("ImlibFreePixmap(0x%x)\n", pixmap)); + ImlibFreePixmap(imlib_id, pixmap); + pixmap = None; + } else +# endif + { + D_PIXMAP(("XCreatePixmap(pmap.pixmap(%d,%d))\n", width, height)); + pmap.pixmap = XCreatePixmap(Xdisplay, win, + width, height, Xdepth); + + for (y = 0; y < height; y += ysize) { + unsigned int h = (height - y); + + if (h > ysize) + h = ysize; + + for (x = 0; x < width; x += xsize) { + unsigned int w = (width - x); + + if (w > xsize) + w = xsize; + D_PIXMAP(("XCopyArea(pixmap(%dx%d)->pmap.pixmap)\n", w, h)); + XCopyArea(Xdisplay, pixmap, pmap.pixmap, gc, 0, 0, w, h, x, y); + } + } + + D_IMLIB(("ImlibFreePixmap(0x%x)\n", pixmap)); + ImlibFreePixmap(imlib_id, pixmap); + pixmap = None; + } + } + } else + XFillRectangle(Xdisplay, pixmap, gc, 0, 0, width, height); + } + if (pmap.pixmap != None) { + D_PIXMAP(("XSetWindowBackgroundPixmap(pmap.pixmap)\n")); + XSetWindowBackgroundPixmap(Xdisplay, win, pmap.pixmap); + if (imlib_id +#ifndef IMLIB_TRANS + && !(Options & Opt_pixmapTrans || Options & Opt_viewport_mode) +#endif + ) { + D_IMLIB(("ImlibFreePixmap(pmap.pixmap)\n")); + ImlibFreePixmap(imlib_id, pmap.pixmap); + pmap.pixmap = None; + } + } + XSync(Xdisplay, 0); + XFreeGC(Xdisplay, gc); + XClearWindow(Xdisplay, win); + XFlush(Xdisplay); + XSync(Xdisplay, 0); +} +# else /* PIXMAP_SUPPORT */ +# define scale_pixmap(str,p) ((void)0) +# define render_pixmap() ((void)0) +# endif /* PIXMAP_SUPPORT */ + +# if defined(PIXMAP_SUPPORT) || (MENUBAR_MAX) +/* + * search for FILE in the current working directory, and within the + * colon-delimited PATHLIST, adding the file extension EXT if required. + * + * FILE is either @ or zero terminated + */ +const char * +search_path(const char *pathlist, const char *file, const char *ext) +{ + /* FIXME: the 256 below should be changed to some #define in */ + static char name[256]; + char *p; + const char *path; + int maxpath, len; + struct stat fst; + + if (!pathlist || !file) { /* If either one is NULL, there really isn't much point in going on.... */ + return ((const char *) NULL); + } + if (!ext) { + ext = ""; + } + D_OPTIONS(("search_path(\"%s\", \"%s\", \"%s\") called.\n", pathlist, file, ext)); + D_OPTIONS(("search_path(): Checking for file \"%s\"\n", file)); + if (!access(file, R_OK)) { + if (stat(file, &fst)) { + D_OPTIONS(("Unable to stat %s -- %s\n", file, strerror(errno))); + } else { + D_OPTIONS(("Stat returned mode 0x%08o, S_ISDIR() == %d\n", fst.st_mode, S_ISDIR(fst.st_mode))); + } + if (!S_ISDIR(fst.st_mode)) + return file; + } + /* Changed to use '@' as the delimiter. -vendu */ + if ((p = strchr(file, '@')) == NULL) + p = strchr(file, '\0'); + len = (p - file); + + /* check about adding a trailing extension */ + if (ext != NULL) { + + char *dot; + + dot = strrchr(p, '.'); + path = strrchr(p, '/'); + if (dot != NULL || (path != NULL && dot <= path)) + ext = NULL; + } + /* leave room for an extra '/' and trailing '\0' */ + maxpath = sizeof(name) - (len + (ext ? strlen(ext) : 0) + 2); + if (maxpath <= 0) + return NULL; + + /* check if we can find it now */ + strncpy(name, file, len); + name[len] = '\0'; + + D_OPTIONS(("search_path(): Checking for file \"%s\"\n", name)); + if (!access(name, R_OK)) { + stat(name, &fst); + if (!S_ISDIR(fst.st_mode)) + return name; + } + if (ext) { + strcat(name, ext); + D_OPTIONS(("search_path(): Checking for file \"%s\"\n", name)); + if (!access(name, R_OK)) { + stat(name, &fst); + if (!S_ISDIR(fst.st_mode)) + return name; + } + } + for (path = pathlist; path != NULL && *path != '\0'; path = p) { + + int n; + + /* colon delimited */ + if ((p = strchr(path, ':')) == NULL) + p = strchr(path, '\0'); + + n = (p - path); + if (*p != '\0') + p++; + + if (n > 0 && n <= maxpath) { + + strncpy(name, path, n); + if (name[n - 1] != '/') + name[n++] = '/'; + name[n] = '\0'; + strncat(name, file, len); + + D_OPTIONS(("search_path(): Checking for file \"%s\"\n", name)); + if (!access(name, R_OK)) { + stat(name, &fst); + if (!S_ISDIR(fst.st_mode)) + return name; + } + if (ext) { + strcat(name, ext); + D_OPTIONS(("search_path(): Checking for file \"%s\"\n", name)); + if (!access(name, R_OK)) { + stat(name, &fst); + if (!S_ISDIR(fst.st_mode)) + return name; + } + } + } + } + return NULL; +} +# endif /* PIXMAP_SUPPORT || (MENUBAR_MAX) */ + +# ifdef PIXMAP_SUPPORT +/* I think it might be cool to make Eterm load the pixmaps in background. + * You'd be able to start typing commands without waiting for the bg + * pixmap processing to end. Thoughts right now: fork(), pthreads. -vendu + */ + +void +set_bgPixmap(const char *file) +{ + const char *f = NULL; + + ASSERT(file != NULL); + + if (!file) { + return; + } + D_IMLIB(("set_bgPixmap(%s)\n", file)); + + /* Turn on scaling */ + if ((Options & Opt_pixmapScale) || (rs_pixmapScale)) { + bgPixmap.h = 100; + bgPixmap.w = 100; + } + /* XSetWindowBackground(Xdisplay, TermWin.vt, PixColors[bgColor]); */ + + if (*file != '\0') { + /* XGetWindowAttributes(Xdisplay, TermWin.vt, &attr); */ + + /* search environment variables here too */ +# ifdef USE_IMLIB + if ((f = search_path(rs_path, file, PIXMAP_EXT)) == NULL) +# endif +# ifdef PATH_ENV +# ifdef USE_IMLIB + if ((f = search_path(getenv(PATH_ENV), file, PIXMAP_EXT)) == NULL) +# endif +# endif /* PATH_ENV */ +# ifdef USE_IMLIB + f = search_path(getenv("PATH"), file, PIXMAP_EXT); +# endif + +# ifdef USE_IMLIB + if (f != NULL) { + rs_pixmaps[pixmap_bg] = strdup(f); + if (imlib_bg.im != NULL) { + D_IMLIB(("ImlibDestroyImage()\n")); + ImlibDestroyImage(imlib_id, imlib_bg.im); + imlib_bg.im = NULL; + } + D_IMLIB(("ReadImageViaImlib(%s)\n", (char *) f)); + imlib_bg.im = ReadImageViaImlib(Xdisplay, (char *) f); + } + if (imlib_bg.im == NULL) { +# endif + char *p; + + if ((p = strchr(file, ';')) == NULL && (p = strchr(file, '@')) == NULL) + p = strchr(file, '\0'); + print_error("couldn't load image file \"%.*s\"", (p - file), file); + if (!(background_is_pixmap())) { + XSetWindowBackground(Xdisplay, TermWin.vt, PixColors[bgColor]); + } +# ifdef USE_POSIX_THREADS + XSetWindowBackground(Xdisplay, TermWin.vt, PixColors[bgColor]); +# endif + } else { +# ifdef USE_POSIX_THREADS + /* FIXME: the if tests should be removed and done once at the + * else above. + */ + if (bg_needs_update) { + D_THREADS(("pthread_attr_init(resize_sub_thr_attr)\n")); + pthread_attr_init(&resize_sub_thr_attr); +# ifdef MUTEX_SYNCH + if (pthread_mutex_trylock(&mutex) == EBUSY) { + D_THREADS(("set_bgPixmap(): pthread_cancel(resize_sub_thr);\n")); + pthread_cancel(resize_sub_thr); + } else { + D_THREADS(("pthread_mutex_trylock(&mutex): ")); + pthread_mutex_unlock(&mutex); + D_THREADS(("pthread_mutex_unlock(&mutex)\n")); + } +# else + if (bg_set) { + D_THREADS(("Background set, cancelling thread\n")); + pthread_cancel(resize_sub_thr); + } +# endif + + if (!(pthread_create(&resize_sub_thr, &resize_sub_thr_attr, + (void *) &render_bg_thread, NULL))) { + bg_set = 0; +# ifdef MUTEX_SYNCH + /* D_THREADS("pthread_mutex_lock(&mutex);\n"); */ + /* pthread_mutex_lock(&mutex); */ +# endif + D_THREADS(("thread created\n")); + } else { + D_THREADS(("pthread_create() failed!\n")); + } + } +# else + +# ifdef PIXMAP_OFFSET + if (Options & Opt_viewport_mode) { + if (viewport_pixmap != None) { + XFreePixmap(Xdisplay, viewport_pixmap); + viewport_pixmap = None; + bg_needs_update = 1; + } + } +# endif + if (bg_needs_update) { + D_PIXMAP(("set_bgPixmap(): render_pixmap(TermWin.vt), case 2\n")); + render_pixmap(TermWin.vt, imlib_bg, bgPixmap, 0, 1); + scr_touch(); + bg_needs_update = 0; + } +# endif + } + + /* init_imlib = 1; */ + /* pthread_join(resize_sub_thr, NULL); */ + D_PIXMAP(("set_bgPixmap() exitting\n")); + } +# ifdef IMLIB_TRANS + else if (Options & Opt_pixmapTrans) { + render_pixmap(TermWin.vt, imlib_bg, bgPixmap, 0, 1); + scr_touch(); + bg_needs_update = 0; + } +# endif + + if (!f || *f == '\0') { + if (imlib_bg.im != NULL) { + D_IMLIB(("ImlibDestroyImage()\n")); + ImlibDestroyImage(imlib_id, imlib_bg.im); + imlib_bg.im = NULL; + } + XSetWindowBackground(Xdisplay, TermWin.vt, PixColors[bgColor]); + XClearWindow(Xdisplay, TermWin.vt); + scr_touch(); + XFlush(Xdisplay); + } +} + +# ifdef PIXMAP_SCROLLBAR +void +set_Pixmap(const char *file, Pixmap dest_pmap, int type) +{ + const char *f; + imlib_t img; + + /* FIXME: assert() looks like a bad thing. Calls abort(). IMHO, stupid. */ + assert(file != NULL); + + D_IMLIB(("set_Pixmap(%s)\n", file)); + + if (*file != '\0') { + /* search environment variables here too */ +# ifdef USE_IMLIB + if ((f = search_path(rs_path, file, PIXMAP_EXT)) == NULL) +# endif +# ifdef PATH_ENV +# ifdef USE_IMLIB + if ((f = search_path(getenv(PATH_ENV), file, PIXMAP_EXT)) == NULL) +# endif +# endif /* PATH_ENV */ +# ifdef USE_IMLIB + f = search_path(getenv("PATH"), file, PIXMAP_EXT); +# endif + +# ifdef USE_IMLIB + if (f != NULL) { + D_IMLIB(("ReadImageViaImlib(%s)\n", (char *) f)); + img.im = ReadImageViaImlib(Xdisplay, (char *) f); + } + if (img.im == NULL) { +# endif + char *p; + + if ((p = strchr(file, ';')) == NULL) + p = strchr(file, '\0'); + print_error("couldn't load image file \"%.*s\"", (p - file), file); + } else { + switch (type) { + case pixmap_sb: + render_pixmap(scrollBar.win, img, sbPixmap, pixmap_sb, 0); + break; + case pixmap_sa: + render_pixmap(scrollBar.sa_win, img, saPixmap, pixmap_sa, 0); + break; + case pixmap_saclk: + render_pixmap(scrollBar.sa_win, img, sa_clkPixmap, pixmap_saclk, 0); + break; + case pixmap_up: + render_pixmap(scrollBar.up_win, img, upPixmap, pixmap_up, 0); + break; + case pixmap_upclk: + render_pixmap(scrollBar.up_win, img, up_clkPixmap, pixmap_upclk, 0); + break; + case pixmap_dn: + render_pixmap(scrollBar.dn_win, img, dnPixmap, pixmap_dn, 0); + break; + case pixmap_dnclk: + render_pixmap(scrollBar.dn_win, img, dn_clkPixmap, pixmap_dnclk, 0); + break; + case pixmap_mb: +/* render_pixmap(ActiveMenu->win, img, mbPixmap, pixmap_mb, 0); */ + break; + case pixmap_ms: +/* render_pixmap(ActiveMenu->win, img, mb_selPixmap, pixmap_ms, 0); */ + break; + default: + D_PIXMAP(("WARNING: set_Pixmap() returning\n")); + return; + } + } + } + D_PIXMAP(("set_scrPixmap() exitting\n")); +} +# endif /* PIXMAP_SCROLLBAR */ + +void +colormod_pixmap(imlib_t image, GC gc, int w, int h) +{ + + unsigned int bright; + ImlibColorModifier xform = + {0xff, 0xff, 0xff}, rx = + {0xff, 0xff, 0xff}, gx = + {0xff, 0xff, 0xff}, bx = + {0xff, 0xff, 0xff}; + + if (rs_shadePct == 0 && rs_tintMask == 0xffffff) { + Imlib_set_image_modifier(imlib_id, image.im, &xform); + Imlib_set_image_red_modifier(imlib_id, image.im, &rx); + Imlib_set_image_green_modifier(imlib_id, image.im, &gx); + Imlib_set_image_blue_modifier(imlib_id, image.im, &bx); + return; + } + if (rs_shadePct != 0) { + bright = 0xff - ((rs_shadePct * 0xff) / 100); + xform.brightness = bright; + Imlib_set_image_modifier(imlib_id, image.im, &xform); + } else { + Imlib_set_image_modifier(imlib_id, image.im, &xform); + } + + if (rs_tintMask != 0xffffff) { + rx.brightness = (rs_tintMask & 0xff0000) >> 16; + gx.brightness = (rs_tintMask & 0x00ff00) >> 8; + bx.brightness = rs_tintMask & 0x0000ff; + Imlib_set_image_red_modifier(imlib_id, image.im, &rx); + Imlib_set_image_green_modifier(imlib_id, image.im, &gx); + Imlib_set_image_blue_modifier(imlib_id, image.im, &bx); + } else { + Imlib_set_image_red_modifier(imlib_id, image.im, &rx); + Imlib_set_image_green_modifier(imlib_id, image.im, &gx); + Imlib_set_image_blue_modifier(imlib_id, image.im, &bx); + } + + D_PIXMAP(("Image modifiers: xform == %08x, rx == %08x, gx == %08x, bx == %08x\n", + xform.brightness, rx.brightness, gx.brightness, bx.brightness)); +} + +# ifdef USE_IMLIB +# undef PIXMAP_EXT +# endif + +# ifdef PIXMAP_OFFSET + +# ifdef IMLIB_TRANS +void +colormod_trans(imlib_t image, GC gc, int w, int h) +{ + + unsigned int bright; + ImlibColorModifier xform = + {0xff, 0xff, 0xff}, rx = + {0xff, 0xff, 0xff}, gx = + {0xff, 0xff, 0xff}, bx = + {0xff, 0xff, 0xff}; + + if (rs_shadePct == 0 && rs_tintMask == 0xffffff) { + return; + } + if (rs_shadePct != 0) { + bright = 0xff - ((rs_shadePct * 0xff) / 100); + xform.brightness = bright; + Imlib_set_image_modifier(imlib_id, image.im, &xform); + } + if (rs_tintMask != 0xffffff) { + rx.brightness = (rs_tintMask & 0xff0000) >> 16; + gx.brightness = (rs_tintMask & 0x00ff00) >> 8; + bx.brightness = rs_tintMask & 0x0000ff; + Imlib_set_image_red_modifier(imlib_id, image.im, &rx); + Imlib_set_image_green_modifier(imlib_id, image.im, &gx); + Imlib_set_image_blue_modifier(imlib_id, image.im, &bx); + } + D_PIXMAP(("Image modifiers: xform == %08x, rx == %08x, gx == %08x, bx == %08x\n", + xform.brightness, rx.brightness, gx.brightness, bx.brightness)); +} + +# else /* IMLIB_TRANS */ + +void +colormod_trans(Pixmap p, GC gc, int w, int h) +{ + + XImage *ximg; + register unsigned long v, i; + unsigned long x, y; + unsigned int r, g, b; + float rm, gm, bm, shade; + ImlibColor ctab[256]; + int real_depth = 0; + register int br, bg, bb; + register unsigned int mr, mg, mb; + + if (rs_shadePct == 0 && rs_tintMask == 0xffffff) { + return; + } + if (Xdepth <= 8) { + + XColor cols[256]; + + for (i = 0; i < (1 << Xdepth); i++) { + cols[i].pixel = i; + cols[i].flags = DoRed | DoGreen | DoBlue; + } + XQueryColors(Xdisplay, Xcmap, cols, 1 << Xdepth); + for (i = 0; i < (1 << Xdepth); i++) { + ctab[i].r = cols[i].red >> 8; + ctab[i].g = cols[i].green >> 8; + ctab[i].b = cols[i].blue >> 8; + ctab[i].pixel = cols[i].pixel; + } + } else if (Xdepth == 16) { + + XWindowAttributes xattr; + + XGetWindowAttributes(Xdisplay, desktop_window, &xattr); + if ((xattr.visual->red_mask == 0x7c00) && (xattr.visual->green_mask == 0x3e0) && (xattr.visual->blue_mask == 0x1f)) { + real_depth = 15; + } + } + if (!real_depth) { + real_depth = Xdepth; + } + shade = (float) (100 - rs_shadePct) / 100.0; + rm = (float) ((rs_tintMask & 0xff0000) >> 16) / 255.0 * shade; + gm = (float) ((rs_tintMask & 0x00ff00) >> 8) / 255.0 * shade; + bm = (float) (rs_tintMask & 0x0000ff) / 255.0 * shade; + + ximg = XGetImage(Xdisplay, p, 0, 0, w, h, -1, ZPixmap); + if (ximg == NULL) { + print_warning("colormod_trans: XGetImage(Xdisplay, 0x%08x, 0, 0, %d, %d, -1, ZPixmap) returned NULL.", + p, w, h); + return; + } + if (Xdepth <= 8) { + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + v = XGetPixel(ximg, x, y); + r = (int) ctab[v & 0xff].r * rm; + g = (int) ctab[v & 0xff].g * gm; + b = (int) ctab[v & 0xff].b * bm; + v = Imlib_best_color_match(imlib_id, &r, &g, &b); + XPutPixel(ximg, x, y, v); + } + } + } else { + /* Determine bitshift and bitmask values */ + switch (real_depth) { + case 15: + br = 7; + bg = 2; + bb = 3; + mr = mg = mb = 0xf8; + break; + case 16: + br = 8; + bg = bb = 3; + mr = mb = 0xf8; + mg = 0xfc; + break; + case 24: + case 32: + br = 16; + bg = 8; + bb = 0; + mr = mg = mb = 0xff; + break; + default: + print_warning("colormod_trans: Bit depth of %d is unsupported for tinting/shading.", real_depth); + return; + } + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + v = XGetPixel(ximg, x, y); + r = (int) (((v >> br) & mr) * rm) & 0xff; + g = (int) (((v >> bg) & mg) * gm) & 0xff; + b = (int) (((v << bb) & mb) * bm) & 0xff; + v = ((r & mr) << br) | ((g & mg) << bg) | ((b & mb) >> bb); + XPutPixel(ximg, x, y, v); + } + } + } + XPutImage(Xdisplay, p, gc, ximg, 0, 0, 0, 0, w, h); + XDestroyImage(ximg); +} + +# endif /* IMLIB_TRANS */ + +Window +get_desktop_window(void) +{ + + Atom prop, type, prop2; + int format; + unsigned long length, after; + unsigned char *data; + unsigned int nchildren; + Window w, root, *children, parent; + Window last_desktop_window = desktop_window; + + if ((prop = XInternAtom(Xdisplay, "_XROOTPMAP_ID", True)) == None) { + D_PIXMAP(("No _XROOTPMAP_ID found.\n")); + } + if ((prop2 = XInternAtom(Xdisplay, "_XROOTCOLOR_PIXEL", True)) == None) { + D_PIXMAP(("No _XROOTCOLOR_PIXEL found.\n")); + } + if (prop == None && prop2 == None) { + return None; + } +#ifdef WATCH_DESKTOP_OPTION + if (Options & Opt_watchDesktop) { + if (TermWin.wm_parent != None) { + XSelectInput(Xdisplay, TermWin.wm_parent, None); + } + if (TermWin.wm_grandparent != None) { + XSelectInput(Xdisplay, TermWin.wm_grandparent, None); + } + } +#endif + + for (w = TermWin.parent; w; w = parent) { + + D_PIXMAP(("Current window ID is: 0x%08x\n", w)); + + if ((XQueryTree(Xdisplay, w, &root, &parent, &children, &nchildren)) == False) { + D_PIXMAP((" Egad! XQueryTree() returned false!\n")); + return None; + } + D_PIXMAP((" Window is 0x%08x with %d children, root is 0x%08x, parent is 0x%08x\n", + w, nchildren, root, parent)); + if (nchildren) { + XFree(children); + } +#ifdef WATCH_DESKTOP_OPTION + if (Options & Opt_watchDesktop && parent != None) { + if (w == TermWin.parent) { + TermWin.wm_parent = parent; + XSelectInput(Xdisplay, TermWin.wm_parent, StructureNotifyMask); + } else if (w == TermWin.wm_parent) { + TermWin.wm_grandparent = parent; + XSelectInput(Xdisplay, TermWin.wm_grandparent, StructureNotifyMask); + } + } +#endif + + if (prop != None) { + XGetWindowProperty(Xdisplay, w, prop, 0L, 1L, False, AnyPropertyType, + &type, &format, &length, &after, &data); + } else if (prop2 != None) { + XGetWindowProperty(Xdisplay, w, prop2, 0L, 1L, False, AnyPropertyType, + &type, &format, &length, &after, &data); + } else { + continue; + } + if (type != None) { + D_PIXMAP((" Found desktop as window 0x%08x\n", w)); + return (desktop_window = w); + } + } + + D_PIXMAP(("No suitable parent found.\n")); + return (desktop_window = None); + +} + +Pixmap +get_desktop_pixmap(void) +{ + + Pixmap p; + Atom prop, type, prop2; + int format; + unsigned long length, after; + unsigned char *data; + register unsigned long i = 0; + time_t blah; + + if (desktop_window == None) + return None; + + prop = XInternAtom(Xdisplay, "_XROOTPMAP_ID", True); + prop2 = XInternAtom(Xdisplay, "_XROOTCOLOR_PIXEL", True); + + if (prop == None && prop2 == None) { + return None; + } + if (prop != None) { + XGetWindowProperty(Xdisplay, desktop_window, prop, 0L, 1L, False, AnyPropertyType, + &type, &format, &length, &after, &data); + if (type == XA_PIXMAP) { + p = *((Pixmap *) data); + /* + blah = time(NULL); + D_PIXMAP(("Time index: %s\n", ctime(&blah))); + for (i=0; i < 4000000000 && !p; i++) { + D_PIXMAP((" Null pixmap returned. i == %lu Trying again in 20 ms.\n", i)); + usleep(2000000); + XGetWindowProperty(Xdisplay, desktop_window, prop, 0L, 1L, False, AnyPropertyType, + &type, &format, &length, &after, &data); + if (type != XA_PIXMAP) { + p = None; + break; + } else { + p = *((Pixmap *)data); + } + } + blah = time(NULL); + D_PIXMAP(("Time index: %s\n", ctime(&blah))); + if (i != 0 && p != 0) { + _exit(0); + } + */ + D_PIXMAP((" Found pixmap 0x%08x\n", p)); + return p; + } + } + if (prop2 != None) { + XGetWindowProperty(Xdisplay, desktop_window, prop2, 0L, 1L, False, AnyPropertyType, + &type, &format, &length, &after, &data); + if (type == XA_CARDINAL) { + D_PIXMAP((" Solid color not yet supported.\n")); + return None; + } + } + D_PIXMAP(("No suitable attribute found.\n")); + return None; + +} +# endif /* PIXMAP_OFFSET) */ + +void +shaped_window_apply_mask(Window win, Pixmap mask) +{ + + static signed char have_shape = -1; + int unused; + + D_PIXMAP(("shaped_window_apply_mask(0x%08x, 0x%08x) called.\n", win, mask)); + if (win == None || mask == None) + return; + +#ifdef HAVE_X_SHAPE_EXT + if (1 == have_shape) { + D_PIXMAP(("shaped_window_apply_mask(): Shape extension available, applying mask.\n")); + XShapeCombineMask(Xdisplay, win, ShapeBounding, 0, 0, mask, ShapeSet); + } else if (0 == have_shape) { + D_PIXMAP(("shaped_window_apply_mask(): Shape extension not available.\n")); + return; + } else { /* Don't know yet? */ + D_PIXMAP(("shaped_window_apply_mask(): Looking for shape extension.\n")); + if (!XQueryExtension(Xdisplay, "SHAPE", &unused, &unused, &unused)) { + have_shape = 0; + D_PIXMAP(("shaped_window_apply_mask(): Shape extension not found.\n")); + return; + } else { + have_shape = 1; + D_PIXMAP(("shaped_window_apply_mask(): Shape extension available, applying mask.\n")); + XShapeCombineMask(Xdisplay, win, ShapeBounding, 0, 0, mask, ShapeSet); + } + } +#else + D_PIXMAP(("shaped_window_apply_mask(): Shape support disabled.\n")); +#endif +} + +void +set_icon_pixmap(char *filename, XWMHints * pwm_hints) +{ + + const char *icon_path; + ImlibImage *temp_im; + XWMHints *wm_hints; + + if (pwm_hints) { + wm_hints = pwm_hints; + } else { + wm_hints = XGetWMHints(Xdisplay, TermWin.parent); + } + + if (filename && *filename) { + if ((icon_path = search_path(rs_path, filename, NULL)) == NULL) +# ifdef PATH_ENV + if ((icon_path = search_path(getenv(PATH_ENV), filename, NULL)) == NULL) +# endif + icon_path = search_path(getenv("PATH"), filename, NULL); + + if (icon_path != NULL) { + XIconSize *icon_sizes; + int count, i, w = 64, h = 64; + + temp_im = ReadImageViaImlib(Xdisplay, icon_path); + /* If we're going to render the image anyway, might as well be nice and give it to the WM in a size it likes. */ + if (XGetIconSizes(Xdisplay, Xroot, &icon_sizes, &count)) { + for (i = 0; i < count; i++) { + D_PIXMAP(("Got icon sizes: Width %d to %d +/- %d, Height %d to %d +/- %d\n", icon_sizes[i].min_width, icon_sizes[i].max_width, + icon_sizes[i].width_inc, icon_sizes[i].min_height, icon_sizes[i].max_height, icon_sizes[i].height_inc)); + w = MIN(icon_sizes[i].max_width, 64); /* 64x64 is plenty big */ + h = MIN(icon_sizes[i].max_height, 64); + } + fflush(stdout); + XFree(icon_sizes); + } + Imlib_render(imlib_id, temp_im, w, h); + wm_hints->icon_pixmap = Imlib_copy_image(imlib_id, temp_im); + wm_hints->icon_mask = Imlib_copy_mask(imlib_id, temp_im); + wm_hints->icon_window = XCreateSimpleWindow(Xdisplay, TermWin.parent, 0, 0, w, h, 0, 0L, 0L); + shaped_window_apply_mask(wm_hints->icon_window, wm_hints->icon_mask); + XSetWindowBackgroundPixmap(Xdisplay, wm_hints->icon_window, wm_hints->icon_pixmap); + wm_hints->flags |= IconWindowHint; + Imlib_destroy_image(imlib_id, temp_im); + } + } else { + /* Use the default. It's 48x48, so if the WM doesn't like it, tough cookies. Pixmap -> ImlibImage -> Render -> Pixmap would be + too expensive, IMHO. */ + Imlib_data_to_pixmap(imlib_id, Eterm_xpm, &wm_hints->icon_pixmap, &wm_hints->icon_mask); + wm_hints->icon_window = XCreateSimpleWindow(Xdisplay, TermWin.parent, 0, 0, 48, 48, 0, 0L, 0L); + shaped_window_apply_mask(wm_hints->icon_window, wm_hints->icon_mask); + XSetWindowBackgroundPixmap(Xdisplay, wm_hints->icon_window, wm_hints->icon_pixmap); + wm_hints->flags |= IconWindowHint; + } + + /* Only set the hints ourselves if we were passed a NULL pointer for pwm_hints */ + if (!pwm_hints) { + XSetWMHints(Xdisplay, TermWin.parent, wm_hints); + XFree(wm_hints); + } +} + +# ifdef USE_EFFECTS +int +fade_in(Pixmap * pmap, ImlibImage * img, int frames) +{ + + static int i = 0; + register int f = frames; + ImlibColorModifier mod; + double gamma, brightness, contrast; + + Imlib_get_image_modifier(imlib_id, img, &mod); + + if (i < f) { + i++; + gamma = (double) mod.gamma / i; + brightness = (double) mod.brightness / i; + contrast = (double) mod.contrast / i; + Imlib_set_image_modifier(imlib_id, img, &mod); + } else if (i == f) { + i = 0; + } + /* how many frames to go */ + return (f - i); +} +# endif /* USE_EFFECTS */ + +#endif /* PIXMAP_SUPPORT */ diff --git a/src/pixmap.h b/src/pixmap.h new file mode 100644 index 0000000..d1d9ba3 --- /dev/null +++ b/src/pixmap.h @@ -0,0 +1,89 @@ +/* pixmap.h for Eterm. + * 17 Feb 1998 vendu + */ + +#ifndef _PIXMAP_H +# define _PIXMAP_H + +#include + +# ifdef USE_IMLIB +# include "eterm_imlib.h" +# endif + +typedef struct { + short w, h, x, y; + Pixmap pixmap; +} pixmap_t; + +# ifdef USE_IMLIB +typedef struct { + Image *im; + int last_w,last_h; +} imlib_t; + +# define background_is_pixmap() ((imlib_id != NULL) || Options & Opt_pixmapTrans) +# define background_is_image() (imlib_bg.im != NULL) + +# else + +# define background_is_pixmap() ((int)0) +# define background_is_image() ((int)0) + +# endif + +# ifdef USE_IMLIB +extern imlib_t imlib_bg; +extern ImlibData *imlib_id; +# ifdef PIXMAP_SCROLLBAR +imlib_t imlib_sb, imlib_sa, imlib_saclk; +# endif +# endif +pixmap_t bgPixmap; +# ifdef PIXMAP_SCROLLBAR +pixmap_t sbPixmap; +pixmap_t upPixmap, up_clkPixmap; +pixmap_t dnPixmap, dn_clkPixmap; +pixmap_t saPixmap, sa_clkPixmap; +# endif + +typedef short renderop_t; + +# ifdef PIXMAP_OFFSET +enum { FAKE_TRANSPARENCY }; +enum { tint_none, tint_red, tint_green, tint_blue, + tint_cyan, tint_magenta, tint_yellow }; + +# ifdef USE_IMLIB +void render_pixmap(Window win, imlib_t image, pixmap_t pmap, + int which, renderop_t renderop); +# endif +# endif + +# ifdef USE_POSIX_THREADS +void init_bg_pixmap_thread(void *file); +# endif +void set_bgPixmap(const char *file); +void set_Pixmap(const char *file, Pixmap dest_pmap, int type); +int scale_pixmap(const char *geom, pixmap_t *pmap); +# ifdef USE_IMLIB +void colormod_pixmap(imlib_t, GC, int, int); +# endif + +# ifdef PIXMAP_OFFSET +# ifdef IMLIB_TRANS +void colormod_trans(imlib_t, GC, int, int); +# else +void colormod_trans(Pixmap, GC, int, int); +# endif +Window get_desktop_window(void); +Pixmap get_desktop_pixmap(void); +extern Window desktop_window; +# endif +extern void shaped_window_apply_mask(Window, Pixmap); +extern void set_icon_pixmap(char *, XWMHints *); +# ifdef USE_IMLIB +extern ImlibImage *ReadImageViaImlib(Display *, const char *); +# endif + +#endif /* _PIXMAP_H */ diff --git a/src/profile.h b/src/profile.h new file mode 100644 index 0000000..816a891 --- /dev/null +++ b/src/profile.h @@ -0,0 +1,80 @@ +/* profile.h for Eterm. + * 25 Mar 1998, vendu. + */ + +#ifndef _PROFILE_H +# define _PROFILE_H + +/* included for a possible #define PROFILE */ +/* # include "feature.h" */ +# include +# include +# include + +/* NOTE: if PROFILE is not defined, all macros in this file will + * be set to (void)0 so they won't get compiled into binaries. + */ +#define PROFILE +# ifdef PROFILE + +/* Data structures */ + +typedef struct { + long long total; + struct timeval start; + struct timeval stop; +} P_counter_t; + +/* Profiling macros */ + +/* Sets tv to current time. + * struct timeval tv; + * Usage: P_SETTIMEVAL(struct timeval tv); + */ +# define P_SETTIMEVAL(tv) gettimeofday(&(tv), NULL) + +/* NOT FINISHED YET */ +# define P_UPDATETOTAL(cnt) { \ + cnt.total += P_CMPTIMEVALS_USEC(cnt.start, cnt.stop); \ +} + +/* Declare cnt and initialize by setting to zero. + * P_counter_t cnt; + * Usage: P_INITCOUNTER(counter); + * NOTES: cnt will be declared. This means that you'll + * probably need to localize a block where to use this; see + * the definition of P_CALL() elsewhere in this file. + */ +# define P_INITCOUNTER(cnt) \ + P_counter_t cnt = { 0, { 0, 0 }, { 0, 0 } } +/* Time from start to stop in microseconds + * struct timeval start, stop; + */ +# define P_CMPTIMEVALS_USEC(start, stop) \ + ((stop.tv_sec - start.tv_sec)*1000000 \ + + (stop.tv_usec - start.tv_usec)) + +/* Counts the time spent in the call f and outputs + * str: