commit 22b2a193d3c6e13474b1cb844d9f6e30bb22ab4f Author: Michael Jennings Date: Tue Aug 17 23:01:18 1999 +0000 Initial import of Eterm 0.8.9 sources SVN revision: 38 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: