diff options
author | Robert Lemmen <robertle@semistable.com> | 2005-10-02 16:55:03 +0200 |
---|---|---|
committer | Robert Lemmen <robertle@semistable.com> | 2005-10-02 16:55:03 +0200 |
commit | 506c0631ef00a77295dfcb885a2dd85ebd083e0d (patch) | |
tree | b1429d6834a665fb8b813dd7d39ca652448dd303 |
Import aewan_1.0.01.orig.tar.gz
[dgit import orig aewan_1.0.01.orig.tar.gz]
-rw-r--r-- | CHANGELOG | 37 | ||||
-rw-r--r-- | COPYING | 341 | ||||
-rw-r--r-- | Makefile.in | 85 | ||||
-rw-r--r-- | README | 77 | ||||
-rw-r--r-- | TODO | 30 | ||||
-rw-r--r-- | absmenu.c | 115 | ||||
-rw-r--r-- | absmenu.h | 116 | ||||
-rw-r--r-- | aecat.c | 275 | ||||
-rw-r--r-- | aeff.c | 349 | ||||
-rw-r--r-- | aeff.h | 104 | ||||
-rw-r--r-- | aemakeflic.c | 249 | ||||
-rw-r--r-- | aewan.c | 218 | ||||
-rw-r--r-- | aewl/aewl.c | 44 | ||||
-rw-r--r-- | aewl/aewl.h | 69 | ||||
-rw-r--r-- | aewl/allwidgets.h | 42 | ||||
-rw-r--r-- | aewl/button.c | 96 | ||||
-rw-r--r-- | aewl/button.h | 65 | ||||
-rw-r--r-- | aewl/field.c | 180 | ||||
-rw-r--r-- | aewl/field.h | 69 | ||||
-rw-r--r-- | aewl/form.c | 133 | ||||
-rw-r--r-- | aewl/form.h | 97 | ||||
-rw-r--r-- | aewl/form_int.h | 17 | ||||
-rw-r--r-- | aewl/label.c | 104 | ||||
-rw-r--r-- | aewl/label.h | 68 | ||||
-rw-r--r-- | aewl/listbox.c | 200 | ||||
-rw-r--r-- | aewl/listbox.h | 95 | ||||
-rw-r--r-- | aewl/util.c | 128 | ||||
-rw-r--r-- | aewl/util.h | 76 | ||||
-rw-r--r-- | aewl/widget.c | 48 | ||||
-rw-r--r-- | aewl/widget.h | 86 | ||||
-rw-r--r-- | bores/Makefile | 64 | ||||
-rw-r--r-- | bores/autod.c | 58 | ||||
-rw-r--r-- | bores/autod.h | 122 | ||||
-rw-r--r-- | bores/bores.h | 38 | ||||
-rw-r--r-- | bores/darray.c | 137 | ||||
-rw-r--r-- | bores/darray.h | 95 | ||||
-rw-r--r-- | bores/defs.h | 43 | ||||
-rw-r--r-- | bores/hashdict.c | 222 | ||||
-rw-r--r-- | bores/hashdict.h | 139 | ||||
-rw-r--r-- | bores/kurses.c | 293 | ||||
-rw-r--r-- | bores/kurses.h | 133 | ||||
-rw-r--r-- | bores/util.c | 270 | ||||
-rw-r--r-- | bores/util.h | 169 | ||||
-rw-r--r-- | chtr.c | 61 | ||||
-rw-r--r-- | chtr.h | 67 | ||||
-rw-r--r-- | clipboard.c | 70 | ||||
-rw-r--r-- | clipboard.h | 52 | ||||
-rw-r--r-- | colordlg.c | 96 | ||||
-rw-r--r-- | colordlg.h | 44 | ||||
-rw-r--r-- | commands.h | 83 | ||||
-rwxr-xr-x | configure | 4558 | ||||
-rw-r--r-- | configure.ac | 42 | ||||
-rw-r--r-- | debug_aewl.c | 121 | ||||
-rw-r--r-- | debug_aewl.h | 7 | ||||
-rw-r--r-- | document.c | 227 | ||||
-rw-r--r-- | document.h | 108 | ||||
-rw-r--r-- | editmeta.c | 123 | ||||
-rw-r--r-- | editmeta.h | 41 | ||||
-rw-r--r-- | export.c | 86 | ||||
-rw-r--r-- | export.h | 74 | ||||
-rw-r--r-- | filedlg.c | 319 | ||||
-rw-r--r-- | filedlg.h | 49 | ||||
-rw-r--r-- | handlekey.c | 624 | ||||
-rw-r--r-- | handlekey.h | 50 | ||||
-rw-r--r-- | helpdlg.c | 127 | ||||
-rw-r--r-- | helpdlg.h | 42 | ||||
-rw-r--r-- | init_aewl.c | 79 | ||||
-rw-r--r-- | init_aewl.h | 42 | ||||
-rw-r--r-- | keybind.c | 97 | ||||
-rw-r--r-- | keybind.h | 50 | ||||
-rw-r--r-- | keys.c | 64 | ||||
-rw-r--r-- | keys.h | 99 | ||||
-rw-r--r-- | layer.c | 314 | ||||
-rw-r--r-- | layer.h | 144 | ||||
-rw-r--r-- | layerdlg.c | 168 | ||||
-rw-r--r-- | layerdlg.h | 45 | ||||
-rw-r--r-- | make-package.sh | 23 | ||||
-rw-r--r-- | man/man1/aecat.1 | 63 | ||||
-rw-r--r-- | man/man1/aemakeflic.1 | 50 | ||||
-rw-r--r-- | man/man1/aewan.1 | 50 | ||||
-rw-r--r-- | man/man5/aewan.5 | 108 | ||||
-rw-r--r-- | menubar-items.inc | 77 | ||||
-rw-r--r-- | menubar.c | 228 | ||||
-rw-r--r-- | menubar.h | 51 | ||||
-rw-r--r-- | psd.c | 82 | ||||
-rw-r--r-- | psd.h | 98 | ||||
-rw-r--r-- | python/NOTICE | 6 | ||||
-rw-r--r-- | python/aewan.py | 185 | ||||
-rw-r--r-- | python/test.py | 54 | ||||
-rw-r--r-- | ui.c | 141 | ||||
-rw-r--r-- | ui.h | 80 | ||||
-rw-r--r-- | version.h | 41 | ||||
-rw-r--r-- | vlayer.c | 48 | ||||
-rw-r--r-- | vlayer.h | 80 | ||||
-rw-r--r-- | welcomedlg.c | 130 | ||||
-rw-r--r-- | welcomedlg.h | 42 |
96 files changed, 15206 insertions, 0 deletions
diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..50d1b6b --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,37 @@ +1.0.01 + + * aecat now accepts "comment" format (which extracts metadata from the file) + and -L option (which outputs layer count) - contributed by + Gerfried Fuchs (alfie@ist.org) + * corrected aeff (aewan file format) escape sequence interpretation bug + that was causing special characters in metainfo to get garbled + * added "resize layer" funcionality, also contributed by + Gerfried Fuchs (alfie@ist.org) + * both 'Load file' and 'Save file' now use dialog boxes that let the + user browse directories + * added a new export utility: aemakeflic, which converts aewan documents + into animations to be played in the 'less' command or as a shell script + * added a confirmation question when quitting the program or clearing + the document to prevent against accidental loss of current work + * in the version number, the revision will be conventionally written + with two digits from now on + +0.9.7 + + * cleaned up Makefile.in to make the bores/ directory (remnants of a library + that used to be separate from aewan) compile together with the rest + of the project instead of separately as libbores.a + +0.9.6 - release date: 2005-02-19 (minor bugfix release) + + * fixed segfault bug which resulted from trying to correct cursor coords + when a layer had just been added (reported in Debian bug tracking system) + +0.9.5 - release date: 2005-02-18 + + * menu introduced in order to make the interface more friendly + * "new file" (i.e. clear everything and start from scratch) funcionality added + * added patches from Gerfried Fuchs (alfie@ist.org): + - aecat now produces more XHTML-compliant html and supports + background color + - user can now manipulate upper-left corner of selection in select mode @@ -0,0 +1,341 @@ + 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + 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. + + <signature of Ty Coon>, 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/Makefile.in b/Makefile.in new file mode 100644 index 0000000..5aac058 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,85 @@ +# Copyright (c) 2003 Bruno T. C. de Oliveira +# +# LICENSE INFORMATION: +# 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 +# Copyright (c) 2002 Bruno T. C. de Oliveira +# +# INFORMAÇÕES DE LICENÇA: +# Este programa é um software de livre distribuição; você pode +# redistribuí-lo e/ou modificá-lo sob os termos da GNU General +# Public License, conforme publicado pela Free Software Foundation, +# pela versão 2 da licença ou qualquer versão posterior. +# +# Este programa é distribuído na esperança de que ele será útil +# aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +# a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +# QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +# License para obter mais detalhes (uma cópia acompanha este +# programa, armazenada no arquivo COPYING). + +sources=$(wildcard *.c) $(wildcard aewl/*.c) $(wildcard bores/*.c) +headers=$(wildcard *.h) $(wildcard bores/*.h) $(wildcard aewl/*.h) +execs=aewan@EXESUF@ aecat@EXESUF@ aemakeflic@EXESUF@ +mainobjs=$(patsubst %@EXESUF@,%.o,$(execs)) +objects=$(filter-out $(mainobjs), $(patsubst %.c,%.o,$(sources))) + +CC=@CC@ +CFLAGS=@CFLAGS@ -fno-strict-aliasing -Wall +LIBS=@LIBS@ +LDFLAGS=@LDFLAGS@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +bindir=@bindir@ +mandir=@mandir@ + +export CC +export CFLAGS +export LDFLAGS +export LIBS + +all: $(execs) + +$(execs): %@EXESUF@: %.o $(objects) + $(CC) $(CFLAGS) -o $@ $(objects) \ + $(patsubst %@EXESUF@, %.o, $@) $(LDFLAGS) $(LIBS) + +clean: + rm -f *.o aewl/*.o bores/*.o depends aewan.log $(execs) *.stackdump + +distclean: clean + rm -rf autom4te.cache config.status config.log Makefile + +cvsclean: distclean + rm -f configure + +install: all + mkdir -p $(DESTDIR)$(bindir) + cp $(execs) $(DESTDIR)$(bindir) + mkdir -p $(DESTDIR)$(mandir)/man1 $(DESTDIR)$(mandir)/man5 + cp man/man1/*.1 $(DESTDIR)$(mandir)/man1 + cp man/man5/*.5 $(DESTDIR)$(mandir)/man5 + +-include depends + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + +depends: $(sources) $(headers) + $(CC) $(CFLAGS) -MM $(sources) >depends + +.PHONY: clean all depends + @@ -0,0 +1,77 @@ +AEWAN Ascii Art Editor +Copyright (c) 2004 Bruno Takahashi C. de Oliveira +Licensed under the GNU General Public license +Refer to the COPYING file for a full text of the license. + +[[ 0. PROJECT HOME PAGE ]] + + http://aewan.sourceforge.net + +There you will find author information, FAQ, links to the latest +version of the program, etc. + +[[ 1. HOW TO COMPILE AND INSTALL ]] + +Assuming you downloaded aewan-0.X.Y.tar.gz (where X, Y represent nonnegative +integers), this is how you would compile it: + +$ tar -zxf aewan-0.X.Y.tar.gz +$ cd aewan-0.X.Y +$ ./configure +$ make +$ su -c 'make install' + +NOTE: as of version 0.8.7, aewan no longer requires the separate libbores +library, since it has been merged into the project. + +[[ 2. THANKS ]] + +Thanks to every who, directly or indirectly, contributed to this project. +In particular, I would like to thank: + + * Sourceforge.net for their excellent Open Source hosting infrastructure + * The authors of tetradraw, whose program served as an inspiration + to write this editor + +I would also like to thank Robert Lemmen <robertle@semistable.com> for all +his cooperation in getting aewan into the Debian distribution. + +PEOPLE WHO HAVE WORKED OR ARE CURRENTLY WORKING ON THIS PROJECT: + + * Bruno T. C. de Oliveira (brunotc@gmail.com) + * Peep Pullerits (http://solicit.estprog.ee; solicit@estprog.ee) + * Praveen Kurup <praveen_kurup@jasubhai.com> + * Gerfried Fuchs <alfie@ist.org> + +[[ 3. WHAT IS AEWAN ]] + +Summary: Aewan is a multi-layered ascii-art/animation editor that produces +both stand-alone cat-able art files and an easy-to-parse format for integration +in your terminal applications. It is primarily designed for Linux, although it +currently also compiles under FreeBSD and possibly other *NIX systems. + +More details: Aewan is a curses-based program that allows for the creation and +editing of ascii art. The user is able to move the cursor around the screen by +means of the arrow keys and 'paint' characters by pressing the corresponding +keys. There are dialog boxes that allow the user to choose foreground and +background colors, as well as bold and blink attributes. The user may also +select rectangular areas of the canvas in order to move, copy and paste them. +Aewan also supports 'intelligent' horizontal and vertical flipping (e.g. +converts '\' to '/', etc). + +What sets Aewan apart from similar projects is the fact that it can work with +multiple layers, and has the ability to turn transparency and visibility on and +off for each layer. A layer dialog is provided through which the user can +change the order of the layers. Thus, each layer can be edited independently in +order to generate a composite drawing. Instead of using the layers for +compositing, it is also possible to use the layers as frames for an animation, +thus enabling the user to create ascii animations with Aewan (note: to be fully +implemented next release). + +The file format is easy to parse, so it is easy to write a terminal-based +application that uses the Aewan files to display onscreen. Currently it has +been tested on the Linux terminal, rxvt, xterm, the Cygwin terminal and the +FreeBSD console. Although it is already quite stable (I am already using it on +some projects of mine), it is a little rough on the edges, but that can be +worked out in the near future. + @@ -0,0 +1,30 @@ +TODO +Items in order of importance + +CURRENT WORK + +- see TODO in filedlg.c + +CORRECTIONS: + +- [aewl] make the label widget a little more robust: make it respect its width + when painting itself + +- [aewl] make text fields 'scrollable' + +- [aewl] BUG: cursor in textfield goes arbitrarily to the right as text + is added beyond the visible part of it + +NEW FEATURES: + +- dialogs!!!! For saving files, opening files, confirming operations, + specifying layer dimensions, renaming layers and everything else +- IMPORT/EXPORT from/to ansi, etc + +- flip strategies (let user decide what characters are to be flipped) +- more intuitive transparent-layer handling (or add more documentation) +- enable smaller layers to be placed anywhere instead of always having + to be anchored to the top-left corner + +- configurable key bindings + diff --git a/absmenu.c b/absmenu.c new file mode 100644 index 0000000..15b1679 --- /dev/null +++ b/absmenu.c @@ -0,0 +1,115 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "bores/bores.h" +#include <ncurses.h> +#include <stdlib.h> + +#include "absmenu.h" + +AbsMenu *menu_create(int *ic, int x0, int y0, int w, int h, + int attr_sel, int attr_unsel, + void (*painter)(int, struct _AbsMenu *)) +{ + AbsMenu *new_menu = zalloc(sizeof(struct _AbsMenu)); + new_menu->item_count = ic ? ic : &(new_menu->__ic); + new_menu->x0 = x0; + new_menu->y0 = y0; + new_menu->w = w; + new_menu->h = h; + new_menu->attr_sel = attr_sel; + new_menu->attr_unsel = attr_unsel; + new_menu->painter = painter; + return new_menu; +} + +void menu_destroy(AbsMenu *m) { + if (m) free(m); +} + +void menu_set_count(AbsMenu *m, int i) { + m->__ic = i; +} + +int menu_get_count(AbsMenu *m) { + return *(m->item_count); +} + +void menu_paint(AbsMenu *m) { + int i; int index; int j; + int sely = m->y0; + for (i = 0; i < m->h; i++) { + index = i + m->item_at_top; + if (index == m->sel_item) sely = m->y0 + i; + + kurses_move(m->x0, m->y0 + i); + kurses_color_at((m->sel_item == index) ? m->attr_sel : m->attr_unsel); + for (j = 0; j < m->w; j++) addch(' '); + + kurses_move(m->x0, m->y0 + i); + if (index >= 0 && index < *(m->item_count)) (*m->painter)(index, m); + } + + /* place cursor on currently selected item */ + kurses_move(m->x0, sely); +} + +static void menu_correct(AbsMenu *m) { + /* corrige m->sel_item */ + while (m->sel_item < 0) m->sel_item = 0; + while (m->sel_item >= *(m->item_count)) m->sel_item = -1 + *(m->item_count); + + /* corrige m->item_at_top de forma que o item selecionado + * seja visível */ + if (m->item_at_top > m->sel_item) + m->item_at_top = m->sel_item; + else if (m->sel_item >= m->item_at_top + m->h) + m->item_at_top = m->sel_item - m->h + 1; +} + +void menu_handle_key(AbsMenu *m, int ch) { + switch (ch) { + case KEY_UP: m->sel_item--; break; + case KEY_DOWN: m->sel_item++; break; + case KEY_NPAGE: m->sel_item += m->h; break; + case KEY_PPAGE: m->sel_item -= m->h; break; + } + + menu_correct(m); +} + +void menu_select_item(AbsMenu *m, int i) { + m->sel_item = i; + menu_correct(m); +} + diff --git a/absmenu.h b/absmenu.h new file mode 100644 index 0000000..907b68a --- /dev/null +++ b/absmenu.h @@ -0,0 +1,116 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + + +/* absmenu.h - an abstract menu that lets creator specify a paint function, + * and even the address of an item count */ + +#ifndef _btco_aewan_abmenu_h +#define _btco_aewan_abmenu_h + +struct _AbsMenu { + int __ic; /* itemcount variable, if the caller chose to use + * nondynamic count */ + int *item_count; /* pointer to item count variable. If the caller chose + * nondynamic count, this points to __ic. Can never be + * NULL. */ + int x0, y0; /* rendering position onscreen */ + int w, h; /* dimensions of renderable area */ + + int attr_sel, attr_unsel; /* color attributes for selected and + unselected items */ + + int item_at_top; /* which item index is currently being drawn at + * the top of the menu. This defines the scrolling + * position of the menu. If *item_count > 0, + * this must be a value such that + * 0 <= item_at_top < *item_count */ + + int sel_item; /* the selected item in the menu. If *item_count > 0, + * this must be a value such that + * 0 <= sel_item < *item_count */ + + void (*painter)(int i, struct _AbsMenu *menu); + /* painter function that paints menu + entry index i */ +}; +typedef struct _AbsMenu AbsMenu; + +/* Create a new abstract menu. + * ic - address of a variable that will serve as the menu's item count. + * Pass NULL to use an internally maintained count that can be + * manipulated with menu_set_count and menu_get_count. + * + * x0, y0, w, h - a rectangle that indicates the area of the screen to which + * the menu should be rendered + * + * attr_sel, attr_unsel - color attributes to use for selected + * entries and unselected entries. The lowest four bits of an attribute + * is the background color, the next four bits indicate the foreground + * color. + * + * painter - the address of a function that will be called in order to + * paint the menu items. The cursor will be appropriately placed + * before the function call, and the whole line will already have + * been filled with the appropriate color; also, the appropriate + * color will already be set. The function also receives a pointer + * to the menu itself for convenience. + */ +AbsMenu *menu_create(int *ic, int x0, int y0, int w, int h, + int attr_sel, int attr_unsel, + void (*painter)(int, struct _AbsMenu *)); + +/* Destroys a menu previously created with menu_create */ +void menu_destroy(AbsMenu *m); + +/* Set the item count for menu m. This can only be used if NULL was + * passed as the <ic> parameter of menu_create when the menu was + * created. */ +void menu_set_count(AbsMenu *m, int i); + +/* Obtains menu item count */ +int menu_get_count(AbsMenu *m); + +/* Sets the selected item of the menu. Applies scrolling + * corrections to make sure item is visible */ +void menu_select_item(AbsMenu *m, int i); + +/* Paints menu to screen. Does not call refresh() */ +void menu_paint(AbsMenu *m); + +/* Performs appropriate action in response to key ch. For example, + * if ch is KEY_UP, decrement m->sel_item, etc. */ +void menu_handle_key(AbsMenu *m, int ch); + +#endif + @@ -0,0 +1,275 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "document.h" +#include "vlayer.h" +#include "export.h" +#include <stdbool.h> + +#include "bores/bores.h" +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> + +bool clear_screen = false; +bool suppress_newlines = false; + /* whether to suppress newlines on output. */ +bool use_color = true; +char *outputfile; + +FILE *f; + +Document *doc; /* the document we are outputting */ +int layer_number; /* the layer we will output; -1 means composite */ +Layer *lyr; /* the layer we are printing; NULL if printing composite */ +int width, height; + +struct html_output_state_t { + bool font_tag_open, blink_tag_open; /* which html tags are open */ + int color; /* The color we are currently outputting text in. + * This is a full 0-15 color code.*/ + int bgcolor; /* The color we are currently putting text onto. + * This is a full 0-15 color code.*/ +}; + +/* Extracts a cell from the appropriate layer (or build one, + * if we are dealing with a composite). Returns it. */ +void get_decoded_cell(int x, int y, DecodedCell *dec) { + if (lyr) decode_cell(&lyr->cells[x][y], dec); + else { + Cell c = document_calc_effective_cell(doc, x, y); + decode_cell(&c, dec); + } +} + +void output_text(void) { + VirtualLayer *vl; + + if (lyr) vl = vlayer_create_from_layer(lyr); + else vl = vlayer_create_from_composite(doc); + + if (!vl) { + fprintf(stderr, "Error creating virtual layer. Is the document empty?\n"); + exit(2); + } + + if (clear_screen) fputs("\x1B[2J\x1B[H", f); + if (!export_vlayer_to_ansi(vl, use_color, !suppress_newlines, false, f)) { + fprintf(stderr, "Error exporting virtual layer to ansi.\n"); + exit(2); + } + + vlayer_destroy(vl); +} + +#define COL_BLACK 0 +#define COL_RED 1 +#define COL_GREEN 2 +#define COL_YELLOW 3 +#define COL_BLUE 4 +#define COL_MAGENTA 5 +#define COL_CYAN 6 +#define COL_WHITE 7 + +static char *hex_codes[16] = { + "000000", "990000", "009900", "999900", + "000099", "990099", "009999", "999999", + "404040", "ff0000", "00ff00", "ffff00", + "0000ff", "ff00ff", "00ffff", "ffffff" }; + +void output_html(void) { + int x, y; + struct html_output_state_t cur_state; + DecodedCell dec; + + fputs("<html><body style=\"color:#ffffff;background-color:#000000;\">" + "<pre>", f); + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + get_decoded_cell(x, y, &dec); + + /* first set up the blink tag */ + if (use_color && dec.blink != cur_state.blink_tag_open) { + fprintf(f, "<%sblink>", dec.blink ? "" : "/"); + cur_state.blink_tag_open = dec.blink; + } + + /* set up color */ + if (use_color && (dec.fg != cur_state.color || + dec.bg != cur_state.bgcolor)) { + if (cur_state.font_tag_open) fputs("</span>", f); + fprintf(f, "<span style=\"color:#%s;background-color:#%s;\">", + hex_codes[dec.fg], hex_codes[dec.bg]); + cur_state.color = dec.fg; + cur_state.bgcolor = dec.bg; + cur_state.font_tag_open = true; + } + + /* now render the character */ + if (dec.ch >= 0 && dec.ch <= 32) fputs(" ", f); + else if (dec.ch == '&') fputs("&", f); + else if (dec.ch == '<') fputs("<", f); + else if (dec.ch == '>') fputs(">", f); + else fputc(dec.ch, f); + } + fputs("\n", f); + } + + /* close tags as needed and call it a day */ + if (cur_state.font_tag_open) fputs("</span>", f); + if (cur_state.blink_tag_open) fputs("</blink>", f); + fputs("</pre></body></html>", f); +} + +void output_comment(void) { + printf ("%s\n", doc->metainfo); +} + +void output_layercount(void) { + printf ("%d\n", doc->layer_count); +} + +#define MYSYNTAX \ + "Syntax: aecat [-b] [-c] [-{n|N}] [{-p | -l <layer_num>}]\n" \ + " [-f <format>] [-o <output_file>] inputfile\n" \ + "\n" \ + " -f : specifies output format - can be text, html or comment\n" \ + " The 'comment' format extracts document metadata.\n" \ + " -c : prepend a 'clear screen' escape sequence (only valid when\n" \ + " outputting text)\n" \ + " -o : writes output to specified file rather than stdout\n" \ + " -b : disables output of color (only characters will be\n" \ + " printed).\n" \ + " -l : specifies which layer of the document is to be used.\n" \ + " (must be an index, not a layer name). By default,\n" \ + " layer 0 will be used.\n" \ + " -L : displays how many layers the document has.\n" \ + " -p : exports a composite, that is, overlays all visible layers,\n" \ + " paying attention to layer transparency, etc. The size of the\n" \ + " composite will be the size of the first layer\n" \ + " -n : suppress output of newlines\n" \ + " -h : prints this help text\n" + +void rtfm() { /* rtfm = Read the FAQ and Manual, of course :-) */ + fprintf(stderr, MYSYNTAX); + exit(1); +} + +#define FMT_TEXT 1 +#define FMT_HTML 2 +#define FMT_COMMENT 3 +#define FMT_LAYERS 4 + +int main(int argc, char **argv) { + static char optstring[] = "o:chl:Lbpf:n"; + char *inputfile; + int ch; + + int out_fmt = 0; /* In what format to output. */ + + while (0 < (ch = getopt(argc, argv, optstring)) ) { + switch (ch) { + case 'c': clear_screen = true; break; + case 'o': outputfile = strdup(optarg); break; + case 'l': layer_number = atoi(optarg); break; + case 'L': out_fmt = FMT_LAYERS; break; + case 'p': layer_number = -1; break; + case 'b': use_color = false; break; + case 'n': suppress_newlines = true; break; + case 'f': + if (strcmp(optarg, "text") == 0) + out_fmt = FMT_TEXT; + else if (strcmp(optarg, "html") == 0) + out_fmt = FMT_HTML; + else if (strcmp(optarg, "comment") == 0) + out_fmt = FMT_COMMENT; + else { + fprintf(stderr, "Invalid format \"%s\"\n", optarg); + exit(1); + } + break; + default : rtfm(); + } + } + + if (!out_fmt) + out_fmt = FMT_TEXT; + + if (out_fmt != FMT_TEXT && clear_screen) + fprintf(stderr, "Warning: -c option only valid when outputting text\n"); + + if (out_fmt != FMT_TEXT && suppress_newlines) + fprintf(stderr, "Warning: -n option only valid when " + "outputting text\n"); + + if (optind >= argc) rtfm(); + inputfile = strdup(argv[optind]); + + if (! (doc = document_load_from(inputfile)) ) { + fprintf(stderr, "Error loading document from %s (bad format?).\n", + inputfile); + fprintf(stderr, "Error description:\n %s\n", aeff_get_error()); + exit(1); + } + + if (layer_number >= doc->layer_count) { + if (layer_number) + fprintf(stderr, "Document %s does not have the specified layer: %d\n", + inputfile, layer_number); + else + fprintf(stderr, "Document %s has no layers.\n", inputfile); + exit(1); + } + + width = doc->layers[0]->width; + height = doc->layers[0]->height; + lyr = layer_number >= 0 ? doc->layers[layer_number] : NULL; + + if (outputfile && !(f = fopen(outputfile, "w"))) { + fprintf(stderr, "Error opening %s for writing.\n", outputfile); + exit(1); + } + else f = stdout; /* print to standard output if no output file specified */ + + switch(out_fmt) { + case FMT_TEXT: output_text(); break; + case FMT_HTML: output_html(); break; + case FMT_COMMENT: output_comment(); break; + case FMT_LAYERS: output_layercount(); break; + } + + if (f != stdout) fclose(f); + return 0; +} @@ -0,0 +1,349 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +/* +AEWAN FILE FORMAT: + +Any line can contain as many initial spaces as it wants, but +TRAILING SPACES may be significant in string values and other places. + +A header whose name is BLAH is written as a line containing exactly: + + <BLAH + +A footer whose name is BLAH is written as a line containing exactly: + + >BLAH + +A labeled integer (label blah, value 42) will be a line of the form: + + blah: int: 42 + +A labeled string (label blah, value "Line 1\nLine 2\nLine 3") will be: + + blah: string: Line 1\:Line 2\:Line 3 + +Notice that newlines are escaped as '\:'. The rule is that any character +in the range 1 to 31, inclusive, is escaped as '\' followed by ('0' + ch). +A backslash is encoded as '\\' + +Notice that all data lines have three fields, delimited by ": " (the +space is significant and is necessary). +*/ + +#include "aeff.h" +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <zlib.h> +#include "bores/bores.h" + +char *err_string = 0; /* error buffer */ + +struct AeFile_ { + gzFile f; + int indent_level; /* current indent level, for pretty formatting. + * Purely cosmetic. */ +}; + +static bool read_parse_data_line(gzFile f, char **label, char **type, + char **value) { + /* reads and splits a data line, also converting the escape sequences + * found in the third field. If parse fails, set err_string and + * returns false. On success, returns true. */ + char *field_start[3]; + char *line; + + autod_begin; + autod_register(line, free); + + autod_assign( line, freadline_ex(f, gzgetc) ); + + /* look for ':' field separators and note their locations */ + field_start[0] = line; + if ( ! (field_start[1] = strchr(line, ':')) || + ! (field_start[2] = strchr(field_start[1] + 1, ':')) ) { + + dstrset(&err_string, "There's a data line with <3 fields."); + autod_return_value(false); + } + + /* split string by putting 0's on the field limit locations, + * and advacing the limits by 2 positions (to skip over the + * 0 we just put in and the space that immediately succeeds it) */ + *(field_start[1]) = 0; field_start[1] += 2; + *(field_start[2]) = 0; field_start[2] += 2; + + /* discard leading spaces from label that originated from the + * indentation */ + while (*(field_start[0]) == ' ' || + *(field_start[0]) == '\t') field_start[0]++; + + /* if we ended up with an empty field, we have bad syntax */ + if (field_start[0] >= field_start[1]) { + dstrset(&err_string, "There's a data line with an empty label"); + autod_return_value(false); + } + + /* now copy the needed portions to the return variables */ + if (label) *label = sstrdup(field_start[0]); + if (type) *type = sstrdup(field_start[1]); + if (value) *value = sstrdup(field_start[2]); + + /* and decode escape sequences found in value */ + if (value) { + const char *r = *value; + char *w = *value; + + while (*r) { + if (*r == '\\') + r++, *w = (*r == '\\') ? '\\' : *r - '0'; + else + *w = *r; + + r++, w++; + } + + *w = 0; + } + + /* and call it a day */ + autod_return_value(true); +} + +static void aeff_indent(AeFile *f) { + int n = f->indent_level; + while (n-- > 0) gzputc(f->f, '\t'); +} + +AeFile* aeff_open(const char *filename, char mode) { + AeFile *f = zalloc(sizeof(AeFile)); + + f->f = gzopen(filename, mode == 'r' ? "rb" : "wb"); + if (!f->f) { + free(f); + zfree(&err_string); + err_string = dsprintf("%s: %s", filename, strerror(errno)); + return NULL; + } + + f->indent_level = 0; + + return f; +} + +const char *aeff_get_error(void) { + return err_string; +} + +void aeff_set_error(const char *s) { + zfree(&err_string); + err_string = sstrdup(s); +} + +void aeff_close(AeFile* f) { + gzclose(f->f); + sfree(f); +} + +void aeff_write_header(AeFile *f, const char *header_name) { + aeff_indent(f); + gzprintf(f->f, "<%s\n", header_name); + f->indent_level++; +} + +/* generalization for read_header and read_footer */ +static bool aeff_read_mark(AeFile *f, const char *mark_name, char pref) { + char *line; + char *s; + zfree(&err_string); + + autod_begin; + autod_register(line, free); + + autod_assign(line, freadline_ex(f->f, gzgetc)); + + /* if EOF was reached before anything could be read, something is wrong */ + if (!line) { + err_string = dsprintf("EOF reading mark '%c%s'", pref, mark_name); + autod_return_value(false); + } + + /* discard leading blanks, store start of real text in s */ + s = line; + while (*s == ' ' || *s == '\t') s++; + + /* try to recognize the line as a header/footer, and match its name */ + if (strcmp(&s[1], mark_name) || s[0] != pref) { + err_string = dsprintf("Mark '%c%s' not found.", pref, mark_name); + autod_return_value(false); + } + + /* everything checks ok */ + autod_return_value(true); +} + +bool aeff_read_header(AeFile *f, const char *header_name) { + return aeff_read_mark(f, header_name, '<'); +} + +void aeff_write_footer(AeFile *f, const char *footer_name) { + f->indent_level--; + aeff_indent(f); + gzprintf(f->f, ">%s\n", footer_name); +} + +bool aeff_read_footer(AeFile *f, const char *footer_name) { + return aeff_read_mark(f, footer_name, '>'); +} + +void aeff_write_int(AeFile *f, const char *label, int a) { + aeff_indent(f); + gzprintf(f->f, "%s: int: %d\n", label, a); +} + +bool aeff_read_int(AeFile *f, const char *label, int *ret) { + char *rlabel, *rtype, *rvalue; + + autod_begin; + autod_register(rlabel, free); + autod_register(rtype, free); + autod_register(rvalue, free); + + if (!read_parse_data_line(f->f, &rlabel, &rtype, &rvalue)) + return false; + + if (strcmp(rtype, "int")) { + zfree(&err_string); + err_string = dsprintf("Field '%s' not marked as integer", label); + + autod_return_value(false); + } + + if (strcmp(rlabel, label)) { + zfree(&err_string); + err_string = dsprintf("Expected label '%s', found '%s'", label, rlabel); + + autod_return_value(false); + } + + if (ret) *ret = atoi(rvalue); + + autod_return_value(true); +} + +void aeff_write_bool(AeFile *f, const char *label, bool a) { + aeff_indent(f); + gzprintf(f->f, "%s: bool: %s\n", label, a ? "true" : "false"); +} + +bool aeff_read_bool(AeFile *f, const char *label, bool *ret) { + char *rlabel, *rtype, *rvalue; + + autod_begin; + autod_register(rlabel, free); + autod_register(rtype, free); + autod_register(rvalue, free); + + if (!read_parse_data_line(f->f, &rlabel, &rtype, &rvalue)) + return false; + + if (strcmp(rtype, "bool")) { + zfree(&err_string); + err_string = dsprintf("Field '%s' not marked as bool", label); + + autod_return_value(false); + } + + if (strcmp(rlabel, label)) { + zfree(&err_string); + err_string = dsprintf("Expected label '%s', found '%s'", label, rlabel); + + autod_return_value(false); + } + + if (ret) *ret = (*rvalue == 't') ? true : false; + + autod_return_value(true); +} + +void aeff_write_string(AeFile *f, const char *label, const char *s) { + aeff_indent(f); + gzprintf(f->f, "%s: str: ", label); + + /* now encode and write string */ + while (*s) { + if (*s >= 0 && *s <= 31) { + gzputc(f->f, '\\'); + gzputc(f->f, *s + '0'); + } + else if (*s == '\\') gzputs(f->f, "\\\\"); + else gzputc(f->f, *s); + s++; + } + + gzputc(f->f, '\n'); +} + +bool aeff_read_string(AeFile *f, const char *label, char **ret) { + char *rlabel, *rtype, *rvalue; + + autod_begin; + autod_register(rlabel, free); + autod_register(rtype, free); + autod_register(rvalue, free); + + if (!read_parse_data_line(f->f, &rlabel, &rtype, &rvalue)) + autod_return_value(false); + + if (strcmp(rtype, "str")) { + zfree(&err_string); + err_string = dsprintf("Field '%s' not marked as string", label); + + autod_return_value(false); + } + + if (strcmp(rlabel, label)) { + zfree(&err_string); + err_string = dsprintf("Expected label '%s', found '%s'", label, rlabel); + + autod_return_value(false); + } + + if (ret) *ret = sstrdup(rvalue); + + autod_return_value(true); +} + + @@ -0,0 +1,104 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +/* This module handles reading and writing aewan-formatted files. + * These functions provide an abstration layer for actual I/O, + * nothing else. The document_save, layer_save, and other functions + * call the functions herein. + * + * When any functions herein find an error, they set an internal + * static error description variable in addition to returning an error + * code. You can query the error description through a call to + * aeff_get_error() + * + * All aeff_read_* functions return bool indicating success or failure, + * and set the internal error string on the latter case. They also take + * label parameters, which they use to check whether the next piece + * of data in the stream has that label (returning an error if it doesn't). + */ + +#ifndef _btco_aewan_aeff_h +#define _btco_aewan_aeff_h + +#include <stdbool.h> +#include "bores/bores.h" + +typedef struct AeFile_ AeFile; /* opaque file type */ + +/* Open a file for I/O. <filename> is the name of the file to open, + * <mode> is either 'r' or 'w' and you can probably guess what it means. + * Returns the file handle or NULL on error (in which case the internal + * error string is set appropriately) */ +AeFile* aeff_open(const char *filename, char mode); + +/* Queries for a description of the last error. CAUTION: this function + * returns a pointer to an internal buffer that may be deallocated + * or overwritten at whim. So don't keep the returned pointer, just + * use it and forget about it, ask for it again later if you need it. + * + * This function returns NULL if no error string is set. */ +const char *aeff_get_error(void); + +/* Set an artificial error. */ +void aeff_set_error(const char *e); + +/* Closes a file opened with aeff_open */ +void aeff_close(AeFile* f); + +/* Reads/Writes a header (headers contain no data, they are just + * used for consistency checking) */ +void aeff_write_header(AeFile *f, const char *header_name); +bool aeff_read_header(AeFile *f, const char *header_name); + +/* Reads/Writes a footer (footers contain no data, they are just + * used for consistency checking) */ +void aeff_write_footer(AeFile *f, const char *footer_name); +bool aeff_read_footer(AeFile *f, const char *footer_name); + +/* Reads/writes a labeled integer */ +void aeff_write_int(AeFile *f, const char *label, int a); +bool aeff_read_int(AeFile *f, const char *label, int *ret); + +/* Reads/writes a labeled boolean */ +void aeff_write_bool(AeFile *f, const char *label, bool a); +bool aeff_read_bool(AeFile *f, const char *label, bool *ret); + +/* Reads/writes a labeled string. + * On the read function, the returned pointer points to a DYNAMICALLY + * ALLOCATED block that the caller is responsible for freeing. */ +void aeff_write_string(AeFile *f, const char *label, const char *s); +bool aeff_read_string(AeFile *f, const char *label, char **s); + +#endif + + diff --git a/aemakeflic.c b/aemakeflic.c new file mode 100644 index 0000000..e162a03 --- /dev/null +++ b/aemakeflic.c @@ -0,0 +1,249 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "document.h" +#include "vlayer.h" +#include "export.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#define AEFLIC_RTFM \ +"Syntax: aemakeflic [options] input.ae [outputfile.ext]\n" \ +"\n" \ +" Produces an animation file from an aewan document. Each layer in the\n" \ +" document will be used as one frame of the animation. See the man page\n" \ +" for more information.\n" \ +"\n" \ +" Options:\n" \ +"\n" \ +" -f {less|sh} movie format ('less movie' or shell-script)\n" \ +" The default is less.\n" \ +" -N suppress initial screen with instructions for\n" \ +" the given format\n" \ +" -b Disable colors (use text only)\n" \ +" -d {delay} Delay in milliseconds between frames\n" \ +"\n" \ + +#define DEFAULT_DELAY 100 + +/* settings */ +FILE *outf; /* the output file */ +bool add_instructions = true; +Document *doc; /* the document we are converting */ +int width, height; /* animation dimensions */ +bool use_color = true; +int interframe_delay = DEFAULT_DELAY; + /* delay between frames (shellscript only) + * given in milliseconds */ + +void rtfm() { + fputs(AEFLIC_RTFM,stderr); + exit(1); +} + +void output_lessmovie_instructions() { + const int instruction_lines = 18; /* VERY IMPORTANT: keep this value + * in sync with the message below. + * It indicates how many lines it + * occupies! */ + const int instruction_cols = 70; /* this can be overestimated but + * not underestimated */ + int lines_left; + int i; + + fprintf(outf, + "----------------------------------------[ TOP ]----------\n" + "AEWAN LESS-MOVIE\n\n" + "This is an ascii animation intended to be viewed in the 'less'\n" + "pager. You must set your terminal dimensions to the following:\n\n" + " %d columns x %d rows\n\n" + "Then run 'less -c -r <filename>.ae' and hold down the PageDown key\n" + "to see the animation play.\n\n" + "You can tell if the terminal dimensions are correct by looking at\n" + "the top and bottom dotted lines: the one marked '[ TOP ]' should\n" + "appear at the topmost line of the terminal and the dotted line\n" + "marked [ BOTTOM ] should appear at the bottommost. As you page-down\n" + "a few times, they should REMAIN FIXED, not move around.\n\n" + "This animation was generated with AEWAN, an open-source ascii and\n" + "animation editor. Visit http://aewan.sourceforge.net for more info.\n" + , width, height+1); + + lines_left = height - instruction_lines - 1; + if (lines_left < 1 || width < instruction_cols) { + fprintf(stderr, "Error: can't add instructions because the document\n" + "dimensions are too small. Height must be at least\n" + "%d and width must be at least %d.\n", + instruction_lines, instruction_cols); + exit(2); + } + + while (lines_left > 1) { + fputs("\n", outf); + lines_left--; + } + + fputs("----------------------------------------[ BOTTOM ]-------\n",outf); + + for (i = 4; i >= 1; i--) { + fputs("----------------------------------------[ TOP ]----------\n",outf); + lines_left = height - 2; + + fprintf(outf, "(movie starts in %d frame[s])...\n", i); + lines_left--; + + while (lines_left-- > 0) fputs("\n", outf); + fputs("----------------------------------------[ BOTTOM ]-------\n",outf); + } +} + +void output_shellscript_instructions() { + fprintf(outf, +"echo 'AEWAN SHELLSCRIPT ANIMATION'\n" +"echo 'This is an aewan animation shellscript. It will now play an'\n" +"echo 'animation on your terminal. Please make sure the terminal'\n" +"echo 'has at least the following dimensions:'\n" +"echo ' %d lines, %d columns'\n" +"echo\n" +"echo 'This animation was generated with AEWAN, an open-source ascii art and'\n" +"echo 'and animation editor. For more info, see http://aewan.sourceforge.net'\n" +"echo\n" +"echo 'Press ENTER to start the animation'\n" +"read\n" +"echo -ne '\\e[2J\\e[H'\n" + , height, width); +} + +void output_lessmovie() { + int i; + + if (add_instructions) output_lessmovie_instructions(); + + for (i = 0; i < doc->layer_count; i++) { + VirtualLayer *vl = vlayer_create_from_layer(doc->layers[i]); + export_vlayer_to_ansi(vl, use_color, true, false, outf); + vlayer_destroy(vl); + } +} + +void output_shellscript() { + int i; + + fputs("#!/bin/bash\n" + "# This is an aewan animation shellscript. Upon execution,\n" + "# it will play an animation on the terminal.\n" + "# Aewan is an open-source ascii art and animation editor.\n" + "# http://aewan.sourceforge.net\n" + "\n" + "echo -ne '\\e[2J\\e[H'\n", outf); + + if (add_instructions) output_shellscript_instructions(); + + for (i = 0; i < doc->layer_count; i++) { + VirtualLayer *vl = vlayer_create_from_layer(doc->layers[i]); + fputs("echo -ne '\\e[H'\n", outf); + fputs("cat <<QWPOEIURASDKJFAS\n", outf); + export_vlayer_to_ansi(vl, use_color, true, true, outf); + fputs("\nQWPOEIURASDKJFAS\n", outf); + /* FIXME: heinous bug: if the layer drawing mentions + * the word QWPOEIURASDKJFAS at the beginning of a line, + * bash will get confused. */ + fprintf(outf, "sleep %.3f\n", interframe_delay / 1000.0f); + vlayer_destroy(vl); + } +} + +#define FMT_LESS 0 +#define FMT_SH 1 +int main(int argc, char **argv) { + const char optstr[] = "f:Nbd"; + int ch; + int format = FMT_LESS; + const char *inputfile, *outputfile; + + while (0 <= (ch = getopt(argc, argv, optstr))) { + switch (ch) { + case 'f': + if (!strcasecmp(optarg, "less")) format = FMT_LESS; + else if (!strcasecmp(optarg, "sh")) format = FMT_SH; + else { + fputs("Unrecognized animation format!\n", stderr); + return 1; + } + break; + case 'N': add_instructions = false; break; + case 'b': use_color = false; break; + case 'd': interframe_delay = atoi(optarg); break; + default: rtfm(); + } + } + + if (optind >= argc) rtfm(); + inputfile = argv[optind]; + outputfile = (optind + 1 >= argc) ? NULL : argv[optind+1]; + + if (outputfile) { + if (!(outf = fopen(outputfile, "w"))) { + perror(outputfile); + fputs("Can't write outputfile.\n", stderr); + return 2; + } + } + else outf = stdout; /* use stdout for output if no output file specified */ + + /* load document */ + if (!(doc = document_load_from(inputfile))) { + fprintf(stderr, "Error loading document from %s.\n", inputfile); + fprintf(stderr, "Error description: %s\n", aeff_get_error()); + return 2; + } + + if (0 >= doc->layer_count) { + fprintf(stderr, "Document is empty. Can't create animation.\n"); + return 2; + } + + width = doc->layers[0]->width; + height = doc->layers[0]->height; + + switch (format) { + case FMT_LESS: output_lessmovie(); break; + case FMT_SH: output_shellscript(); break; + } + + if (outf != stdout) fclose(outf); + return 0; +} + @@ -0,0 +1,218 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + + +#include "bores/bores.h" +#include <stdlib.h> +#include <stdio.h> +#include <limits.h> +#include <ncurses.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> + +#include "document.h" +#include "keys.h" +#include "ui.h" +#include "psd.h" +#include "handlekey.h" +#include "welcomedlg.h" +#include "keybind.h" +#include "init_aewl.h" + +/* ----------------------------------------------------------------------- */ +/* function declarations */ +/* ----------------------------------------------------------------------- */ + +/* Redraws status bar at the top of the screen */ +void paint_status_bar(void); + +/* Paints the desktop background */ +void paint_desktop(void); + +/* Redraws screen: status bar, canvas, etc */ +void paint_screen(void); + +/* ----------------------------------------------------------------------- */ +/* function implementations */ +/* ----------------------------------------------------------------------- */ +void paint_status_bar() { + kurses_move(0, kurses_height() - 1); + kurses_color(3, 0); + printw("[Lyr %2d] (%3d, %3d) ", _lyr, _x, _y); + + if (_selmode == SM_NONE) { + printw("%-20s", _doc->layer_count ? _doc->layers[_lyr]->name : "[empty]"); + kurses_color(3, 0); + addstr(" "); + + kurses_color(_fg, _bg); + addstr("AaBbCc"); + kurses_color(7, 0); + addstr(" "); + + if (_insmode) { + kurses_color(0, 6 + 16); + printw(" INSERT "); + kurses_color(7, 0); + } + else printw(" "); + + if (_lgmode) { + kurses_color(0, 4); + addstr(" LINES! "); + kurses_color(7, 0); + } + else printw(" "); + + if (_compmode) { + kurses_color(0, 5); + addstr(" COMPOS "); + kurses_color(7, 0); + } + } + else if (_selmode == SM_SELECT) { + kurses_color(0, 2); + printw(" SELECT "); + kurses_color(2, 0); + printw(" (c)opy (m)ove (e)rase (f)g-tint (b)g-tint (o)-edge"); + } + else { + kurses_color(0, 1); + printw(" FLOAT "); + kurses_color(1, 0); + printw(" (s)tamp (x) flip-x (y) flip-y (t)ransparent "); + } +} + +void layer_paint_callback(int x, int y, int *ch, int *attr) { + int x0, x1, y0, y1; + get_norm_sel(&x0, &y0, &x1, &y1); + + if (x >= x0 && x <= x1 && y >= y0 && y <= y1) { + /* invert the colors (approximatelly) */ + *attr = ((*attr & 0x0F) << 4) | (*attr >> 4); + *attr &= 0xF7; /* turn of blinking attribute */ + } +} + +void paint_screen() { + int scr_width, scr_height, i; + + scr_width = kurses_width(); + scr_height = kurses_height(); + + erase(); + paint_desktop(); + paint_status_bar(); + if (doc_empty()) { + static char *msg = "[Document contains no layers; press F1 for menu]"; + kurses_move((scr_width - strlen(msg)) / 2, scr_height / 2); + kurses_color(7, 0); + printw(msg); + refresh(); + return; + } + + /* if in composite mode, paint all visible layers in reverse order */ + if (_compmode) { + for (i = _doc->layer_count - 1; i >= 0; i--) { + Layer *l = _doc->layers[i]; + if (l->visible) + layer_paint(l, -_svx, -_svy, 0, 0, + scr_width, scr_height - 1, + (_selmode == SM_SELECT && i == _lyr) ? + layer_paint_callback : 0); + } + } + else { + /* paint only current layer regardless of visibility, and with no + * transparency */ + layer_paint_opaque(_doc->layers[_lyr], -_svx, -_svy, 0, 0, + scr_width, scr_height - 1, + _selmode == SM_SELECT ? layer_paint_callback : 0); + } + + if (_clipboard && _selmode == SM_FLOAT) + /* paint clipboard */ + layer_paint(_clipboard, _x - _svx, _y - _svy, 0, 0, + scr_width, scr_height - 1, NULL); + + if (!kurses_move(_x - _svx, _y - _svy)) kurses_move(0, 0); + refresh(); +} + +void paint_desktop() { + int scr_width, scr_height; + int x, y; + + scr_width = kurses_width(); + scr_height = kurses_height(); + + kurses_color(8, 0); + for (y = 0; y < scr_height - 1; y++) { + kurses_move(0, y); + for (x = 0; x < scr_width; x++) addch(ACS_CKBOARD); + } +} + +/* ----------------------------------------------------------------------- */ +/* main function */ +/* ----------------------------------------------------------------------- */ +int main(int argc, char **argv) { + /* debug output to /tmp/aewan.log, or /dev/null */ + close(2); + #ifdef DEBUG + if (2 != open("aewan.log", O_WRONLY | O_CREAT | O_TRUNC)) exit(13); + #else + if (2 != open("/dev/null", O_WRONLY)) exit(13); + #endif + + zero_state(); + kurses_init(); + atexit(kurses_finalize); + keys_init(); + keybind_init(); + init_aewl(); + + if (argc >= 2) + u_load_file(argv[1]); + else + show_welcome_dlg(); + + while (1) { + paint_screen(); + handle_key(getch()); + } +} + diff --git a/aewl/aewl.c b/aewl/aewl.c new file mode 100644 index 0000000..0c32fd0 --- /dev/null +++ b/aewl/aewl.c @@ -0,0 +1,44 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "aewl.h" + +AewlAttrSettings aewl_attrs; /* declared as extern in aewl.h */ + +void aewl_init(const AewlAttrSettings *s) { + /* this is a very complicated function indeed. Lots of things to + * initialize: */ + aewl_attrs = *s; +} + + diff --git a/aewl/aewl.h b/aewl/aewl.h new file mode 100644 index 0000000..dceb597 --- /dev/null +++ b/aewl/aewl.h @@ -0,0 +1,69 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewl_h +#define _btco_aewl_h + +#include <ncurses.h> +#include <stdbool.h> +#include "widget.h" + +typedef struct AewlAttrQuad { + int normal, focus, highlight, highlight_focus; +} AewlAttrQuad; + +/* defines what curses attributes to use for various interface components */ +typedef struct AewlAttrSettings_ { + AewlAttrQuad text; + AewlAttrQuad button; + AewlAttrQuad frame; + AewlAttrQuad field; + int field_pad; /* color of the character with which text fields + * are padded */ +} AewlAttrSettings; + +#define AEWL_ATTR(type, focused, highlighted) ( focused ? \ + ( highlighted ? aewl_attrs.type.highlight_focus : aewl_attrs.type.focus ) \ + : \ + ( highlighted ? aewl_attrs.type.highlight : aewl_attrs.type.normal) ) + + +extern AewlAttrSettings aewl_attrs; + +/* Initializes the widget library. You must fill an AewlAttrSettings structure + * and pass it to this function to define which attributes will be used + * for each interface component */ +void aewl_init(const AewlAttrSettings *s); + +#endif + diff --git a/aewl/allwidgets.h b/aewl/allwidgets.h new file mode 100644 index 0000000..7a628ca --- /dev/null +++ b/aewl/allwidgets.h @@ -0,0 +1,42 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +/* includes all widget headers */ + +#include "widget.h" +#include "button.h" +#include "field.h" +#include "form.h" +#include "label.h" +#include "listbox.h" + diff --git a/aewl/button.c b/aewl/button.c new file mode 100644 index 0000000..3112a1c --- /dev/null +++ b/aewl/button.c @@ -0,0 +1,96 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "aewl.h" +#include "button.h" +#include "util.h" +#include <string.h> +#include <stdlib.h> + +AewlWidget *aewl_button_create(int x, int y, int width, int shortcut, + int result, const char *caption) { + AewlButton *b = malloc(sizeof(AewlButton)); + if (!b) return NULL; + memset(b, 0, sizeof(AewlButton)); + + if (width <= 0) width = aewl_util_strlen_esc(caption) + 2; + + aewl_widget_fill_defaults(&(b->base)); + b->base.x = x; + b->base.y = y; + b->base.height = 1; + b->base.width = width; + b->base.focusable = true; + b->base.shortcut = shortcut; + + b->base.fn_repaint = aewl_button_repaint; + b->base.fn_destroy = aewl_button_destroy; + b->base.fn_handlekey = aewl_button_handlekey; + + b->caption = strdup(caption); + b->result = result; + + return (AewlWidget*) b; +} + +void aewl_button_destroy(AewlWidget *button) { + AewlButton *b = (AewlButton*) button; + if (b->caption) free(b->caption); + free(b); +} + +void aewl_button_repaint(AewlWidget *button, bool focused) { + AewlButton *b = (AewlButton*) button; + int i; + int cx; + + wattrset(b->base.win, AEWL_ATTR(button, focused, false)); + + /* print button background by just placing spaces */ + wmove(b->base.win, b->base.y, b->base.x); + for (i = 0; i < b->base.width; i++) waddch(b->base.win, ' '); + + /* center caption and print it */ + cx = (2 * b->base.x + b->base.width - strlen(b->caption)) / 2; + aewl_util_mvwaddstr(b->base.win, b->base.y, cx, + AEWL_ATTR(button, focused, false), + AEWL_ATTR(button, focused, true), + b->caption); +} + +int aewl_button_handlekey(AewlWidget *button, int ch) { + AewlButton *b = (AewlButton*) button; + return (ch == 10 || ch == ' ') ? b->result : 0; +} + + diff --git a/aewl/button.h b/aewl/button.h new file mode 100644 index 0000000..07b4944 --- /dev/null +++ b/aewl/button.h @@ -0,0 +1,65 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewl_button_h +#define _btco_aewl_button_h + +#include "widget.h" + +/* definition of AewlButton */ +typedef struct AewlButton_ { + AewlWidget base; /* the widget */ + char *caption; /* the text that appears on the button */ + int result; /* the result code that the button issues + * when activated */ +} AewlButton; + +/* creates a button with the given parameters. If width is 0, button will + * be large enough to contain its caption. shortcut is the shortcut key + * to activate the button; result is the result code it yields when + * activated. The caption accepts '&' escaping to visually indicate the + * shortcut key. */ +AewlWidget *aewl_button_create(int x, int y, int width, int shortcut, + int result, const char *caption); + +/* destroys a button */ +void aewl_button_destroy(AewlWidget *button); + +/* repaint a button */ +void aewl_button_repaint(AewlWidget *button, bool focused); + +/* key handler function for buttons */ +int aewl_button_handlekey(AewlWidget *button, int ch); + +#endif + diff --git a/aewl/field.c b/aewl/field.c new file mode 100644 index 0000000..189e8e0 --- /dev/null +++ b/aewl/field.c @@ -0,0 +1,180 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "aewl.h" +#include "field.h" +#include "util.h" +#include <string.h> +#include <stdlib.h> + +/* field buffer dynamic reallocation settings */ +#define FIELD_DEFAULT_CAP 20 +#define FIELD_CAP_ADD 20 + +static void aewl_field_ensure_cap(AewlField *f, int cap); +static void buf_insert_char(char *buf, int cap, int pos, int ch); +static void buf_del_char(char *buf, int cap, int pos, int ch); + +AewlWidget *aewl_field_create(int x, int y, int width, int shortcut, + int result, const char *text) { + AewlField *f = malloc(sizeof(AewlField)); + AewlWidget *base; + + if (!f) return NULL; + + memset(f, 0, sizeof(AewlField)); + base = &f->base; + + aewl_widget_fill_defaults(base); + base->x = x; + base->y = y; + base->width = width; + base->height = 1; + base->focusable = true; + base->shortcut = shortcut; + base->fn_repaint = aewl_field_repaint; + base->fn_destroy = aewl_field_destroy; + base->fn_handlekey = aewl_field_handlekey; + + f->result = result; + f->pos = 0; + f->buffer = malloc(f->cap = FIELD_DEFAULT_CAP); + if (!f->buffer) return NULL; + + if (text) aewl_field_set_text(f, text); + + return (AewlWidget*) f; +} + +void aewl_field_set_text(AewlField *f, const char *text) { + int len = strlen(text); + aewl_field_ensure_cap(f, len + 1); + strcpy(f->buffer, text); + + if (f->pos > len) f->pos = len; +} + +const char *aewl_field_get_text(AewlField *f) { + return f->buffer; +} + +void aewl_field_destroy(AewlWidget *w) { + AewlField *f = (AewlField*) w; + if (f->buffer) free(f->buffer); + free(f); +} + +void aewl_field_repaint(AewlWidget *w, bool focused) { + int i; + AewlField *f = (AewlField*) w; + const char *str = f->buffer; + + wattrset(w->win, AEWL_ATTR(field, focused, false)); + + /* print text and pad rest of field with spaces */ + wmove(w->win, w->y, w->x); + for (i = 0; i < w->width; i++) { + if (*str) { + waddch(w->win, *str); + str++; + } + else { + wattrset(w->win, aewl_attrs.field_pad); + waddch(w->win, '_'); + } + + } + + /* position cursor where it should be */ + wmove(w->win, w->y, w->x + f->pos); +} + +int aewl_field_handlekey(AewlWidget *w, int ch) { + AewlField *f = (AewlField*) w; + int len = strlen(f->buffer); + + /* if it is a 'printable' character, insert it into the field */ + if (ch >= 32 && ch <= 255 && ch != 127) { + aewl_field_ensure_cap(f, len + 2); + buf_insert_char(f->buffer, f->cap, f->pos, ch); + f->pos++; + return 0; + } + + /* test for control keys and such */ + switch (ch) { + case 10: return f->result; + case KEY_RIGHT: if (f->pos < len) f->pos++; /* it is ok for pos == len */ + break; + case KEY_LEFT: if (f->pos) f->pos--; break; + case KEY_HOME: f->pos = 0; break; + case KEY_END: f->pos = len; break; + case 'U'-'A'+1: aewl_field_set_text(f, ""); break; + + case KEY_BACKSPACE: case 8: + if (f->pos) { + buf_del_char(f->buffer, f->cap, f->pos - 1, ch); + f->pos--; + } + break; + + case KEY_DC: + if (f->pos < len) buf_del_char(f->buffer, f->cap, f->pos, ch); + break; + } + + return 0; +} + + +static void aewl_field_ensure_cap(AewlField *f, int cap) { + if (f->cap >= cap) return; + + if (! (f->buffer = realloc(f->buffer, f->cap = cap + FIELD_CAP_ADD)) ) + abort(); +} + +static void buf_insert_char(char *buf, int cap, int pos, int ch) { + /* this function does NOT reallocate the buffer to make room, it + * expects there to be room already */ + int i; + for (i = cap - 1; i > pos; i--) buf[i] = buf[i-1]; + buf[pos] = ch; +} + +static void buf_del_char(char *buf, int cap, int pos, int ch) { + int i; + for (i = pos; i < cap - 1; i++) buf[i] = buf[i+1]; +} + + diff --git a/aewl/field.h b/aewl/field.h new file mode 100644 index 0000000..6de85e4 --- /dev/null +++ b/aewl/field.h @@ -0,0 +1,69 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewl_field_h +#define _btco_aewl_field_h + +#include "widget.h" + +/* definition of AewlField */ +typedef struct AewlField_ { + AewlWidget base; /* the widget */ + int result; /* result code returned when user presses ENTER + * while editing this field */ + char *buffer; /* text buffer containing this field's text */ + int cap; /* allocated capacity of above buffer */ + int pos; /* position of cursor within field */ +} AewlField; + +/* creates a field with the given parameters */ +AewlWidget *aewl_field_create(int x, int y, int width, int shortcut, + int result, const char *text); + +/* destroys a field */ +void aewl_field_destroy(AewlWidget *w); + +/* repaint a field */ +void aewl_field_repaint(AewlWidget *w, bool focused); + +/* key handler function for fields */ +int aewl_field_handlekey(AewlWidget *w, int ch); + +/* sets the field's text to the given text */ +void aewl_field_set_text(AewlField *f, const char *text); + +/* returns the field's current text */ +const char *aewl_field_get_text(AewlField *f); + +#endif + diff --git a/aewl/form.c b/aewl/form.c new file mode 100644 index 0000000..49112b8 --- /dev/null +++ b/aewl/form.c @@ -0,0 +1,133 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include <string.h> +#include <stdlib.h> +#include "form_int.h" + +AewlForm *aewl_form_create(WINDOW *w) { + AewlForm *f = malloc(sizeof(struct AewlForm_)); + if (!f) return NULL; + + f->win = w; + f->first_widget = NULL; + f->last_widget = NULL; + f->focus_widget = NULL; + return f; +} + +void aewl_form_add_widget(AewlForm *f, AewlWidget *wid) { + wid->win = f->win; /* tell widget where it is supposed to draw itself */ + wid->form = f; /* tell widget which form it belongs to */ + wid->next = NULL; /* will be the end of the list */ + + if (!f->first_widget) /* form's first widget */ + f->first_widget = f->last_widget = wid; + else /* append to end of list */ + f->last_widget->next = f->last_widget = wid; + + /* if this widget is focusable, and form does not yet have a focused + * widget, this one becomes the focused widget */ + if (!f->focus_widget && wid->focusable) f->focus_widget = wid; +} + +void aewl_form_paint(AewlForm *f, bool refresh) { + AewlWidget *w; + + /* paint all the nonfocused widgets */ + for (w = f->first_widget; w; w = w->next) + if (w != f->focus_widget && w->fn_repaint) w->fn_repaint(w, false); + + /* now paint focus widget */ + if (f->focus_widget && f->focus_widget->fn_repaint) + f->focus_widget->fn_repaint(f->focus_widget, true); + + if (refresh) wrefresh(f->win); +} + +int aewl_form_dispatch_key(AewlForm *f, int ch) { + AewlWidget *w; + int result; + + if (ch == 9 && f->focus_widget) { + /* tab key: move focus to next focusable widget */ + + /* notice that if f->focus_widget == NULL, that means that the + * form does not have ANY focusable widget, in which case + * we don't even enter this 'if' */ + do { + f->focus_widget = f->focus_widget->next; + if (!f->focus_widget) f->focus_widget = f->first_widget; + } while (!f->focus_widget->focusable); + + aewl_form_paint(f, true); + return 0; + } + + /* check if the key is a shortcut for some widget; if so, it gets the + * focus */ + for (w = f->first_widget; w; w = w->next) { + if (w->shortcut == ch && w->focusable) { + f->focus_widget = w; + aewl_form_paint(f, true); + return 0; + } + } + + /* deliver key to focused widget, if there is one */ + if (f->focus_widget && f->focus_widget->fn_handlekey) { + result = f->focus_widget->fn_handlekey(f->focus_widget, ch); + aewl_form_paint(f, true); + return result; + } + + return 0; /* nothing done */ +} + +void aewl_form_destroy(AewlForm *f) { + AewlWidget *tmp, *w = f->first_widget; + + while (w) { + tmp = w->next; + w->fn_destroy(w); + w = tmp; + } + + free(f); +} + +AewlWidget *aewl_form_get_focus_widget(AewlForm *fn) { + return fn->focus_widget; +} + + diff --git a/aewl/form.h b/aewl/form.h new file mode 100644 index 0000000..055d43e --- /dev/null +++ b/aewl/form.h @@ -0,0 +1,97 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewl_form_h +#define _btco_aewl_form_h + +#include <ncurses.h> +#include <stdbool.h> +#include "widget.h" + +/* Defines a form, an abstract entity used as a container for widgets. + * The structure is opaque; see form.c if curious about its internals */ +struct AewlForm_; +typedef struct AewlForm_ AewlForm; + +/* Creates a new form. The passed curses window is where the widgets will + * be rendered. Pass stdscr to render the form to the main screen rather + * than a window. Returns NULL if a problem occurs (i.e., out of memory) */ +AewlForm *aewl_form_create(WINDOW *w); + +/* Adds a widget to a form. The form will be responsible for deleting + * it, you needn't (and mustn't) mind */ +void aewl_form_add_widget(AewlForm *frm, AewlWidget *wid); + +/* Paints all the form's widgets to the screen (i.e. to the window that + * the form is tied with). You only need to call this once, or when + * the screen contents are somehow lost. Widgets redraw themselves + * when appropriate without your interference. + * + * This function will call wrefresh on the form's window if refresh == true. + */ +void aewl_form_paint(AewlForm *frm, bool refresh); + +/* Process a keystroke. This will check what is the widget that currently + * has the focus and will deliver the keypress to its handler. Also handles + * keys for switching focus and so on. Returns a result code (just a plain + * integer -- you can configure your widgets to return certain result codes + * when they are activated), or 0 (special result code meaning the key + * was not handled by any widget). + * + * A typical construct for "running" a form is + * + * aewl_form_paint(f); + * while (42 != aewl_form_dispatch_key(ch)); + * aewl_form_destroy(f); + * + * The above code will run the form until some widget returns the result + * code 42 in response to a keypress. + * + * We don't provide you a function to do that (such as aewl_form_run or + * something) because you will always want to intercept keystrokes and + * process them somehow before handing it over to aewl_form_dispatch, + * (if nothing else, for knowing when to close the form!) so this 'event + * loop' must be written by you. + */ +int aewl_form_dispatch_key(AewlForm *frm, int ch); + +/* Destroys (deallocates) the given form and ALL WIDGETS WITHIN. Do not + * destroy widgets separately! */ +void aewl_form_destroy(AewlForm *frm); + +/* Returns which is the focused widget in the form */ +AewlWidget *aewl_form_get_focus_widget(AewlForm *fn); + + +#endif + diff --git a/aewl/form_int.h b/aewl/form_int.h new file mode 100644 index 0000000..52be7a6 --- /dev/null +++ b/aewl/form_int.h @@ -0,0 +1,17 @@ +#ifndef aewan_aewl_form_int_h +#define aewan_aewl_form_int_h + +/* Form internals */ + +#include "form.h" +struct AewlForm_ { + WINDOW *win; /* the curses window that houses this form */ + AewlWidget *first_widget; /* first widget in form. Others follow in + * linked list */ + AewlWidget *last_widget; /* tail of above linked list */ + AewlWidget *focus_widget; /* points to the widget that currently has + * focus */ +}; + +#endif + diff --git a/aewl/label.c b/aewl/label.c new file mode 100644 index 0000000..c516f3a --- /dev/null +++ b/aewl/label.c @@ -0,0 +1,104 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "aewl.h" +#include "label.h" +#include "util.h" +#include "form_int.h" +#include <string.h> +#include <stdlib.h> + +/* creates a label with the given parameters */ +AewlWidget *aewl_label_create(int x, int y, int width, const char *text) { + AewlLabel *l = malloc(sizeof(AewlLabel)); + AewlWidget *base; + if (!l) return NULL; + memset(l, 0, sizeof(AewlLabel)); + + base = &l->base; + + aewl_widget_fill_defaults(base); + base->x = x; + base->y = y; + base->width = (width > 0) ? width : aewl_util_strlen_esc(text); + base->height = 1; + base->focusable = false; + base->shortcut = 0; + + base->fn_repaint = aewl_label_repaint; + base->fn_destroy = aewl_label_destroy; + base->fn_handlekey = NULL; + + l->caption = strdup(text); + if (!l->caption) return NULL; + + return (AewlWidget*) l; +} + +/* destroys a label */ +void aewl_label_destroy(AewlWidget *w) { + AewlLabel *l = (AewlLabel*) w; + free(l->caption); + free(w); +} + +/* repaint a label */ +void aewl_label_repaint(AewlWidget *w, bool focused) { + AewlLabel *l = (AewlLabel*) w; + int n = w->width; + + if (l->focus_peer && (l->focus_peer == w->form->focus_widget)) + focused = true; + + /* clear the label first */ + wmove(w->win, w->y, w->x); + while (n--) waddch(w->win, ' '); + + /* now print contents */ + aewl_util_mvwaddstr(w->win, w->y, w->x, + AEWL_ATTR(text, focused, false), + AEWL_ATTR(text, focused, true), + l->caption); +} + +/* sets the label's text to the given text */ +void aewl_label_set_text(AewlLabel *l, const char *text) { + if (l->caption) free(l->caption); + l->caption = strdup(text); + if (!l->caption) abort(); +} + +void aewl_label_set_focus_peer(AewlLabel *l, AewlWidget *peer) { + l->focus_peer = peer; +} + diff --git a/aewl/label.h b/aewl/label.h new file mode 100644 index 0000000..8603b33 --- /dev/null +++ b/aewl/label.h @@ -0,0 +1,68 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewl_label_h +#define _btco_aewl_label_h + +#include "widget.h" + +/* definition of AewlLabel */ +typedef struct AewlLabel_ { + AewlWidget base; /* the widget */ + char *caption; /* caption to display */ + AewlWidget *focus_peer; /* the focus peer of the label. The focus peer + * is the widget whose focus status determines + * whether this label will 'appear' focused or + * not. When the peer has the focus, this + * widget will be drawn focused */ +} AewlLabel; + +/* creates a label with the given parameters. If width is 0, + * width is calculated from the width of the text. */ +AewlWidget *aewl_label_create(int x, int y, int width, const char *text); + +/* destroys a label */ +void aewl_label_destroy(AewlWidget *w); + +/* repaint a label */ +void aewl_label_repaint(AewlWidget *w, bool focused); + +/* sets the label's text to the given text */ +void aewl_label_set_text(AewlLabel *l, const char *text); + +/* sets the focus peer for this label. See the description above for + * what the focus peer is. */ +void aewl_label_set_focus_peer(AewlLabel *l, AewlWidget *peer); + +#endif + diff --git a/aewl/listbox.c b/aewl/listbox.c new file mode 100644 index 0000000..e839fee --- /dev/null +++ b/aewl/listbox.c @@ -0,0 +1,200 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "aewl.h" +#include "listbox.h" +#include "util.h" +#include <string.h> +#include <stdlib.h> + +#define DEFAULT_CAPACITY 20 +#define CAPACITY_INCREMENT 20 + +AewlWidget *aewl_listbox_create(int x, int y, int width, int height, + int shortcut, const char *caption, int result) { + AewlListBox *lb = malloc(sizeof(AewlListBox)); + AewlWidget *base = &lb->base; + if (!lb) return NULL; + memset(lb, 0, sizeof(AewlListBox)); + + aewl_widget_fill_defaults(&(lb->base)); + base->x = x; + base->y = y; + base->width = width; + base->height = height; + base->focusable = true; + base->shortcut = shortcut; + + base->fn_repaint = aewl_listbox_repaint; + base->fn_destroy = aewl_listbox_destroy; + base->fn_handlekey = aewl_listbox_handlekey; + + lb->caption = caption ? strdup(caption) : NULL; + lb->result = result; + lb->sel = 0; + lb->iat = 0; + + lb->item_count = 0; + lb->capacity = DEFAULT_CAPACITY; + lb->items = malloc(sizeof(char*) * DEFAULT_CAPACITY); + if (!lb->items) { + free(lb); + return NULL; + } + + return (AewlWidget*) lb; +} + + +void aewl_listbox_clear(AewlListBox *lb) { + int i; + for (i = 0; i < lb->item_count; i++) + if (lb->items[i]) free(lb->items[i]); + lb->item_count = 0; + lb->iat = 0; + lb->sel = 0; +} + +void aewl_listbox_add(AewlListBox *lb, const char *text) { + if (lb->capacity <= lb->item_count) { + lb->capacity += CAPACITY_INCREMENT; + lb->items = realloc(lb->items, sizeof(char*) * lb->capacity); + if (!lb->items) abort(); + } + + /* add new item to end of list now that we are sure there is + * capacity for it */ + if (! (lb->items[lb->item_count++] = strdup(text)) ) abort(); +} + +const char *aewl_listbox_get(AewlListBox *lb, int i) { + if (i < 0 || i >= lb->item_count) return NULL; + return lb->items[i]; +} + +bool aewl_listbox_set(AewlListBox *lb, int i, const char *newvalue) { + if (i < 0 || i >= lb->item_count) return false; + if (lb->items[i]) free(lb->items[i]); + if (! (lb->items[i] = strdup(newvalue)) ) abort(); + return true; +} + +void aewl_listbox_destroy(AewlWidget *listbox) { + AewlListBox *lb = (AewlListBox*) listbox; + aewl_listbox_clear(lb); + free(lb->items); + if (lb->caption) free(lb->caption); + free(lb); +} + +void aewl_listbox_repaint(AewlWidget *listbox, bool focused) { + AewlListBox *lb = (AewlListBox*) listbox; + AewlWidget *base = &lb->base; + int i, y; + + /* erase and draw bounding box */ + wattrset(base->win, AEWL_ATTR(frame, focused, false)); + aewl_util_erase(base->win, base->x, base->y, base->width, base->height); + aewl_util_drawbox(base->win, base->x, base->y, base->width, base->height); + + /* draw caption across top, if any */ + if (lb->caption) + aewl_util_mvwaddstr(base->win, base->y, base->x + 2, + AEWL_ATTR(frame, focused, false), + AEWL_ATTR(frame, focused, true), lb->caption); + + /* draw items, if there are any */ + if (lb->item_count) { + for ( y = base->y + 1, i = lb->iat; + y < base->y + base->height - 1 && i < lb->item_count; + i++, y++) { + + wmove(base->win, y, base->x + 1); + wattrset(base->win, AEWL_ATTR(field, focused, i == lb->sel)); + aewl_util_addnstr(base->win, base->width - 2, lb->items[i]); + } + } + + /* if there are more items than can be seen, show an indication */ + wattrset(base->win, AEWL_ATTR(frame, focused, true)); + + if (lb->iat > 0) + mvwaddch(base->win, base->y + 1, base->x + base->width - 1, '^'); + if (lb->iat + base->height - 2 < lb->item_count) + mvwaddch(base->win, base->y + base->height - 2, + base->x + base->width - 1, 'v'); + + /* move the cursor to the selected item */ + wmove(base->win, base->y + 1 + (lb->sel - lb->iat), base->x + 1); +} + +int aewl_listbox_handlekey(AewlWidget *listbox, int ch) { + AewlListBox *lb = (AewlListBox*) listbox; + AewlWidget *base = &lb->base; + + switch (ch) { + case KEY_UP: lb->sel--; break; + case KEY_DOWN: lb->sel++; break; + case KEY_PPAGE: lb->sel -= base->height - 2; break; + case KEY_NPAGE: lb->sel += base->height - 2; break; + case 10: return lb->result; /* action key */ + } + + /* apply corrections */ + if (lb->sel < 0) lb->sel = 0; + if (lb->sel >= lb->item_count) lb->sel = lb->item_count - 1; + + /* ensure visibility of selected item */ + if (lb->sel < lb->iat) lb->iat = lb->sel; + if (lb->sel >= lb->iat + (base->height - 2)) + lb->iat = lb->sel - (base->height - 2) + 1; + + return 0; +} + +int aewl_listbox_get_sel(AewlListBox *lb) { + if (lb->sel >= 0 && lb->sel < lb->item_count) return lb->sel; + return -1; +} + +static int _compar(const void *p1, const void *p2) { + const char **a = (const char**) p1; + const char **b = (const char**) p2; + return strcmp(*a, *b); +} + +void aewl_listbox_sort(AewlListBox *lb) { + qsort(lb->items, lb->item_count, sizeof(const char*), _compar); +} + + diff --git a/aewl/listbox.h b/aewl/listbox.h new file mode 100644 index 0000000..a544191 --- /dev/null +++ b/aewl/listbox.h @@ -0,0 +1,95 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewl_listbox_h +#define _btco_aewl_listbox_h + +#include "widget.h" + +/* definition of AewlListBox */ +typedef struct AewlListBox_ { + AewlWidget base; /* the widget */ + char *caption; /* the title that appears at the top of the listbox's + * bounding frame */ + int result; /* the result code that the listbox issues + * when the user presses ENTER on it */ + + int sel; /* currently selected item */ + int iat; /* index at top, that is, what list item is currently being + * displayed at the top of the list area. This value changes + * as the list is scrolled */ + + /* dynamic array of listbox items */ + int item_count; + int capacity; + char **items; +} AewlListBox; + +/* creates a list box with the given parameters. The caption accepts + * the '&' escape code for highlighting a character. */ +AewlWidget *aewl_listbox_create(int x, int y, int width, int height, + int shortcut, const char *caption, + int result); + +/* empties the list box, that is, deletes all items */ +void aewl_listbox_clear(AewlListBox *lb); + +/* adds an item to the list box */ +void aewl_listbox_add(AewlListBox *lb, const char *text); + +/* returns the text of the list item whose index is i, or NULL + * if the index is invalid. */ +const char *aewl_listbox_get(AewlListBox *lb, int i); + +/* returns what index is currently selected in the listbox. + * If there is no selection, returns -1. */ +int aewl_listbox_get_sel(AewlListBox *lb); + +/* sets the text of the item whose index is i to the given text. + * Returns false if (and only if) the index i is invalid. */ +bool aewl_listbox_set(AewlListBox *lb, int i, const char *newvalue); + +/* destroys a list box */ +void aewl_listbox_destroy(AewlWidget *listbox); + +/* repaint a listbox */ +void aewl_listbox_repaint(AewlWidget *listbox, bool focused); + +/* key handler function for listboxes */ +int aewl_listbox_handlekey(AewlWidget *listbox, int ch); + +/* sorts the contents of the list box alphabetically */ +void aewl_listbox_sort(AewlListBox *listbox); + +#endif + diff --git a/aewl/util.c b/aewl/util.c new file mode 100644 index 0000000..95b3a7c --- /dev/null +++ b/aewl/util.c @@ -0,0 +1,128 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "util.h" +#define SWAP_VARS(type, x, y) { type tmp; tmp = x; x = y; y = tmp; } + +void aewl_util_mvwaddstr(WINDOW *w, int y, int x, int attr1, int attr2, + const char *str) { + wattrset(w, attr1); + wmove(w, y, x); + + while (*str) { + if (*str == '&') { + str++; + wattrset(w, attr2); + waddch(w, *str); + wattrset(w, attr1); + str++; + continue; + } + + waddch(w, *str); + str++; + } +} + +int aewl_util_strlen_esc(const char *str) { + int l = 0; + while (*str) { + if (*str == '&') { + str+=2; + l++; + continue; + } + + str++; + l++; + } + + return l; +} + +void aewl_util_drawbox(WINDOW *win, int x0, int y0, int w, int h) { + /* left border */ + aewl_util_drawline_v(win, x0, y0, y0 + h - 1, + ACS_ULCORNER, ACS_VLINE, ACS_LLCORNER); + /* right border */ + aewl_util_drawline_v(win, x0 + w - 1, y0, y0 + h - 1, + ACS_URCORNER, ACS_VLINE, ACS_LRCORNER); + /* top border minus corners */ + aewl_util_drawline_h(win, x0 + 1, x0 + w - 2, y0, + ACS_HLINE, ACS_HLINE, ACS_HLINE); + /* bottom border minus corners */ + aewl_util_drawline_h(win, x0 + 1, x0 + w - 2, y0 + h - 1, + ACS_HLINE, ACS_HLINE, ACS_HLINE); +} + +void aewl_util_drawline_h(WINDOW *w, int x0, int x1, int y, + int lc, int mc, int rc) { + int x; + if (x0 > x1) SWAP_VARS(int, x0, x1); + + for (x = x0; x <= x1; x++) { + wmove(w, y, x); + if (x == x0) waddch(w, lc); + else if (x == x1) waddch(w, rc); + else waddch(w, mc); + } +} + +void aewl_util_drawline_v(WINDOW *w, int x, int y0, int y1, + int tc, int mc, int bc) { + int y; + if (y0 > y1) SWAP_VARS(int, y0, y1); + + for (y = y0; y <= y1; y++) { + wmove(w, y, x); + if (y == y0) waddch(w, tc); + else if (y == y1) waddch(w, bc); + else waddch(w, mc); + } +} + +void aewl_util_addnstr(WINDOW *w, int n, const char *str) { + while (n-- && *str) waddch(w, *(str++)); +} + +void aewl_util_erase(WINDOW *win, int x, int y, int w, int h) { + int j; + + while (h--) { + j = w; + wmove(win, y++, x); + while (j--) waddch(win, ' '); + } +} + + diff --git a/aewl/util.h b/aewl/util.h new file mode 100644 index 0000000..259a91c --- /dev/null +++ b/aewl/util.h @@ -0,0 +1,76 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewl_util_h +#define _btco_aewl_util_h + +#include <ncurses.h> + +/* Prints a string of text on the given window at the given position, + * interpreting the '&' escape character as meaning "set the next character's + * attribute to attr2. Rest of string is printed in attr1 */ +void aewl_util_mvwaddstr(WINDOW *w, int y, int x, int attr1, int attr2, + const char *str); + +/* Calculates the printed length of the given string, considering the + * '&' escape character. So the printed length of "&Abc" is 3, although + * strlen() would return 4. */ +int aewl_util_strlen_esc(const char *str); + +/* Clears the given rectangle by overwriting it with spaces*/ +void aewl_util_erase(WINDOW *win, int x, int y, int w, int h); + +/* Draws a box on the given window with the given coordinates. x, y are the + * top-left, h,w are the dimensions. */ +void aewl_util_drawbox(WINDOW *win, int x, int y, int w, int h); + +/* Draws a horizontal line in the given window, from (x0, y) to (x1, y). + * The leftmost character will be lc, the middle will be filled with mc + * characters, and the rightmost character will be rc */ +void aewl_util_drawline_h(WINDOW *w, int x0, int x1, int y, + int lc, int mc, int rc); + +/* Draws a vertical line in the given window, from (x, y0) to (x, y1). + * The topmost character will be tc, the middle will be filled with mc + * characters, and the bottommost character will be bc */ +void aewl_util_drawline_v(WINDOW *w, int x, int y0, int y1, + int tc, int mc, int bc); + + +/* Prints the given string as in addstr(), except that no more than n + * characters will be printed */ +void aewl_util_addnstr(WINDOW *w, int n, const char *str); + + +#endif + diff --git a/aewl/widget.c b/aewl/widget.c new file mode 100644 index 0000000..c851dc5 --- /dev/null +++ b/aewl/widget.c @@ -0,0 +1,48 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "widget.h" + +void aewl_widget_fill_defaults(AewlWidget *w) { + w->win = stdscr; + w->x = w->y = 0; + w->width = w->height = 0; + w->shortcut = 0; + w->focusable = false; + + w->fn_repaint = NULL; + w->fn_handlekey = NULL; + w->fn_destroy = NULL; +} + + diff --git a/aewl/widget.h b/aewl/widget.h new file mode 100644 index 0000000..b20e22b --- /dev/null +++ b/aewl/widget.h @@ -0,0 +1,86 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewl_widget_h +#define _btco_aewl_widget_h + +#include <ncurses.h> +#include <stdbool.h> + +struct AewlForm_; + +/* definition of AewlWidget */ +struct AewlWidget_; +struct AewlWidget_ { + WINDOW *win; /* the window where this widget draws + * itself. This is set when the + * widget is added to a form, you don't + * need to assign it explicitly. */ + + struct AewlForm_ *form; /* the form to which this widget belongs. This + * is set when the widget is added to a form */ + + int x, y, width, height; /* widget position and dimensions */ + + int shortcut; /* shortcut key to focus widget */ + bool focusable; /* indicates whether the widget can + * receive input focus */ + + struct AewlWidget_* next; /* link to next widget in chain; for use + * when chaining widgets in a linked list */ + + /* functions */ + + /* repaints widget onscreen. <focused> indicates whether the widget + * is focused or not. Can be NULL (does not repaint) */ + void (*fn_repaint)(struct AewlWidget_ *self, bool focused); + + /* handles a keypress directed to this widget. Returns a result code + * (an integer value, plain and simple). This function pointer + * can be NULL (handles no keys, result code returned always 0) */ + int (*fn_handlekey)(struct AewlWidget_ *self, int ch); + + /* destroys the widget */ + void (*fn_destroy)(struct AewlWidget_ *self); +}; +typedef struct AewlWidget_ AewlWidget; + +/* There is no function to create a widget out of thin air. This is like + * an "abstract class" if you want to think about it that way. */ + +/* Fills in (in-place) the default values for the fields of the given widget. + * This function is to be called from concrete widget implementation code */ +void aewl_widget_fill_defaults(AewlWidget* w); + +#endif + diff --git a/bores/Makefile b/bores/Makefile new file mode 100644 index 0000000..71815f1 --- /dev/null +++ b/bores/Makefile @@ -0,0 +1,64 @@ +# Copyright (c) 2003 Bruno T. C. de Oliveira +# +# LICENSE INFORMATION: +# 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 +# Copyright (c) 2002 Bruno T. C. de Oliveira +# +# INFORMAÇÕES DE LICENÇA: +# Este programa é um software de livre distribuição; você pode +# redistribuí-lo e/ou modificá-lo sob os termos da GNU General +# Public License, conforme publicado pela Free Software Foundation, +# pela versão 2 da licença ou qualquer versão posterior. +# +# Este programa é distribuído na esperança de que ele será útil +# aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +# a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +# QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +# License para obter mais detalhes (uma cópia acompanha este +# programa, armazenada no arquivo COPYING). + +SOURCES=$(wildcard *.c) +HEADERS=$(filter-out bores.h,$(wildcard *.h)) +OBJECTS=$(patsubst %.c,%.o,$(SOURCES)) + +CFLAGS+=-Wall + +all: libbores.a bores.h + +bores.h: + @echo >bores.h + @echo "/* ------ GENERATED FILE. DO NOT EDIT -------- */" >>bores.h + @echo "/* THIS FILE IS OVERWRITTEN EVERY TIME YOU */" >>bores.h + @echo "/* BUILD THE BORES LIBRARY. */" >>bores.h + @echo "/* */" >>bores.h + @echo "/* Copyright (c) 2003 Bruno T. C. de Oliveira. */" >>bores.h + @echo "/* All rights reserved. */" >>bores.h + for i in $(HEADERS); do echo "#include \"$$i\"" >>bores.h; done + +libbores.a: $(OBJECTS) + rm -f libbores.a + ar -r libbores.a $(OBJECTS) + +.depends: $(SOURCES) $(HEADERS) + $(CC) $(CFLAGS) -MM $(SOURCES) >.depends + +-include .depends + +clean: + rm -f *.o .depends libbores.a bores.h + +.PHONY: clean all + + diff --git a/bores/autod.c b/bores/autod.c new file mode 100644 index 0000000..2ab7b48 --- /dev/null +++ b/bores/autod.c @@ -0,0 +1,58 @@ +#include "autod.h" +#include <stdio.h> + +void do_autod_register(AutodRegistryNode *head, void **ptr, + autod_destructor_t destr) { + AutodRegistryNode *newnode = (AutodRegistryNode*) + malloc(sizeof(AutodRegistryNode)); + newnode->ptr = ptr; + newnode->destructor = destr; + newnode->next = head->next; + head->next = newnode; + + *(ptr) = 0; /* zero the pointer to make sure it doesn't contain + * garbage */ +} + +void do_autod_assign(AutodRegistryNode *head, void **ptr, void *newvalue) { + AutodRegistryNode *n; + + if (*ptr) { + /* destroy previous value before attributing a new value; for that, + * we must look for the corresponding node in the registry */ + n = head->next; + while (n) { + if (n->ptr == ptr) { + /* got it, call destructor */ + (*(n->destructor))(*ptr); + break; + } + } + + if (!n) { + /* not found: abort */ + fprintf(stderr, "autod: FATAL ERROR: attempt to assign to\n" + "unregistered pointer.\n\n"); + abort(); + } + } + + /* we are clear to assign a new value */ + *ptr = newvalue; +} + +void do_autod_cleanup(AutodRegistryNode *head, void *ignore_ptr) { + AutodRegistryNode *n = head->next; + AutodRegistryNode *next; + + while (n) { + if (*(n->ptr) && *(n->ptr) != ignore_ptr) + (*(n->destructor))(*(n->ptr)); /* call destructor */ + + next = n->next; + free(n); /* free the node */ + + n = next; /* advance to next */ + } +} + diff --git a/bores/autod.h b/bores/autod.h new file mode 100644 index 0000000..6645d6f --- /dev/null +++ b/bores/autod.h @@ -0,0 +1,122 @@ +/* +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +/* This is a set of convenience macros and functions for enabling + * "automatic" destruction of dynamically-allocated objects when + * exitting the scope of a function. This is especially useful + * in functions that can return at several points, and it would be + * difficult to keep track of what is allocated at which point in order + * to free everything correctly. + * + * The philosophy is this: + * + * void my_func(...) { + * Brick *my_brick; + * Camel *my_camel; + * char *my_string; + * + * autod_begin; + * autod_register(my_brick, brick_destroy); // also sets my_brick = NULL + * autod_register(my_camel, camel_destroy); // also sets my_camel = NULL + * autod_register(my_string, free); // also sets my_string = NULL + * + * // do what you want with my_brick, my_camel and my_string + * + * if (somefunc() == ERROR) + * autod_return; // this takes care of destroying my_brick, + * // my_camel and my_string, by calling the + * // destructor function specified when registering + * + * // do more stuff with my_brick, my_camel, my_string + * + * autod_return; // don't forget to put this at the end + * } + * + * Sometimes you will want to return a registered object, which means + * that it should not be free'd (the caller will get ownership of the + * object). In this case, use autod_return_obj(v), and all registered + * pointers will be free'd except v, which will be returned. + * + * Also, notice you should never do: + * + * my_camel = other_camel; + * + * Because the original value of my_camel will be lost and will not + * be free'd (memory leak). Instead, you should do: + * + * if (my_camel) camel_destroy(my_camel); + * my_camel = other_camel; + * + * Since this occurs often, a convenience macro is provided: + * + * autod_assign(my_camel, other_camel); + * + * This takes care of destroying the old camel before assigning the new one + * (this sentence really sounds weird). + */ + + +#ifndef btco_bores_autod_h +#define btco_bores_autod_h + +#include <stdlib.h> + +typedef void (*autod_destructor_t)(void*); + +typedef struct AutodRegistryNode_ { + void **ptr; + autod_destructor_t destructor; + struct AutodRegistryNode_ *next; +} AutodRegistryNode; + +#define autod_begin AutodRegistryNode autodregistry_head; \ + autodregistry_head.next = 0 + +#define autod_register(ptr, d) do_autod_register(&autodregistry_head, \ + (void**)&ptr, (autod_destructor_t)d) + +#define autod_return_value(v) { do_autod_cleanup(&autodregistry_head, 0); return v; } +#define autod_return_obj(v) { do_autod_cleanup(&autodregistry_head, (void*)v); return v; } +#define autod_return { do_autod_cleanup(&autodregistry_head, 0); return; } +#define autod_assign(ptr, newvalue) do_autod_assign(&autodregistry_head, \ + (void**)&ptr, newvalue) + +void do_autod_register(AutodRegistryNode *head, void **ptr, + autod_destructor_t destr); + +void do_autod_assign(AutodRegistryNode *head, void **ptr, void *newvalue); + +void do_autod_cleanup(AutodRegistryNode *head, void *ignore_ptr); + + +#endif + + diff --git a/bores/bores.h b/bores/bores.h new file mode 100644 index 0000000..2d1eb21 --- /dev/null +++ b/bores/bores.h @@ -0,0 +1,38 @@ +/* +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "autod.h" +#include "darray.h" +#include "defs.h" +#include "hashdict.h" +#include "kurses.h" +#include "util.h" + diff --git a/bores/darray.c b/bores/darray.c new file mode 100644 index 0000000..a461aeb --- /dev/null +++ b/bores/darray.c @@ -0,0 +1,137 @@ +/* +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + + +#include "darray.h" +#include "util.h" +#include <stdio.h> +#include <stdlib.h> + +#define DEFAULT_CAPACITY 20 + +#define CAPACITY_AHEAD 20 /* when a value is assigned to an out of bounds + item, this is how far beyond it the capacity + grows. */ + +struct DArray_ { + int len; + int cap; + void **items; + void (*value_destroyer)(void*); +}; + +DArray* darray_create() { + return darray_create_ex(DEFAULT_CAPACITY, NULL); +} + +DArray* darray_create_ex(int cap, void (*vd)(void*)) { + DArray* da = zalloc(sizeof(DArray)); + + da->len = 0; + da->cap = (cap > 0) ? cap : DEFAULT_CAPACITY; + da->items = zalloc(sizeof(void*) * da->cap); + da->value_destroyer = vd; + + return da; +} + +void darray_destroy(DArray* da) { + int i; + if (!da) return; + if (da->value_destroyer) { + /* call value destroyer for each item */ + for (i = 0; i < da->len; i++) + if (da->items[i]) (*da->value_destroyer)(da->items[i]); + } + + /* free up the items array then the darray itself */ + sfree(da->items); + sfree(da); +} + +int darray_len(DArray* da) { + /* this one is really complicated */ + return da->len; +} + +void* darray_get(DArray* da, int i) { + return (i >= 0 && i < da->len) ? da->items[i] : NULL; +} + +void darray_set(DArray* da, int i, const void *v) { + if (i < 0) { + fprintf(stderr, "*** FATAL ERROR ***\n" + "Attempt to darray_set with negative index %d\n", i); + abort(); + } + else if (i >= da->len) { + da->cap = i + CAPACITY_AHEAD; + da->items = srealloc(da->items, sizeof(void*) * da->cap); + + /* grow array while assignung NULLs to all newly included items */ + while (i >= da->len) da->items[da->len++] = NULL; + } + else { + /* call value destroyer if there was anything there */ + if (da->items[i] && da->value_destroyer) + (*da->value_destroyer)(da->items[i]); + } + + da->items[i] = (void*) v; +} + +void* darray_snatch(DArray *da, int i) { + void *v; + if (i >= 0 && i < da->len) { + v = da->items[i]; + da->items[i] = NULL; + return v; + } + else return NULL; +} + +void darray_append(DArray *da, const void *v) { + darray_set(da, da->len, v); +} + +void darray_remove(DArray *da, int i) { + if (i < 0 || i >= da->len) return; + if (da->items[i] && da->value_destroyer) + (*da->value_destroyer)(da->items[i]); + + while (i < da->len - 1) { + da->items[i] = da->items[i+1]; + i++; + } + + da->len--; +} + diff --git a/bores/darray.h b/bores/darray.h new file mode 100644 index 0000000..2523914 --- /dev/null +++ b/bores/darray.h @@ -0,0 +1,95 @@ +/* +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef btco_bores_darray_h +#define btco_bores_darray_h + +/* opaque dynamic array type */ +struct DArray_; +typedef struct DArray_ DArray; + +/* creates a new dynamic array of default initial capacity and no + * value destroyer function. */ +DArray* darray_create(); + +/* creates a new dynamic array of initial capacity cap (must be positive) + * and value destroyer function f. The value destroyer is a function + * called whenever a value stored in the array must be destroyed or + * will be overwritten. */ +DArray* darray_create_ex(int cap, void (*vd)(void*)); + +/* destroys the given dynamic array. The value destroyer function will + * be called for all non-NULL values in the array at this point. */ +void darray_destroy(DArray*); + +/* obtains the length of a dynamic array. This is NOT the capacity. The + * length is how many elements are actually there. You should not be + * interested in the capacity, since it is internally managed. */ +int darray_len(DArray*); + +/* obtains the item from the array whose index is i. If i is out of + * bounds, NULL is returned (and no error occurs). PLEASE notice + * that this function is for consultation only, the value will still + * be owned by the darray (and thus can be destroyed at any moment + * by the value destroyer function). If you want to gain ownership + * over the value you get, use darray_snatch instead. */ +void* darray_get(DArray*, int i); + +/* sets the value of item index i to NULL, without calling the value + * destroyer function for it. Returns the value the item had before + * being set to NULL. If the index i is out of bounds, nothing is done + * and NULL is returned. */ +void* darray_snatch(DArray*, int i); + +/* sets the value of item index i to v. If the item had a non-NULL value + * before, the value destroyer function will be called for it before + * it is overwritten. If the index is out of bounds and positive, the + * array will be dynamically expanded to make it valid. If it is + * negative a fatal error occurs. + * + * If i is out of bounds and v is NULL, this function does absolutely + * nothing, because expanding the array to put a NULL value is + * really the same as just leaving it as it is, because darray_get + * returns NULL if you pass it an out-of-bounds index. + * + * Whenever the array expands, the newly created items are set to NULL, + * that is, they are not left with trash in them. + */ +void darray_set(DArray*, int i, const void *v); + +/* Same as darray_set(da, darray_len(da), v) */ +void darray_append(DArray*, const void *v); + +/* removes item i from array, shifting all others up */ +void darray_remove(DArray*, int i); + +#endif + diff --git a/bores/defs.h b/bores/defs.h new file mode 100644 index 0000000..8993ee9 --- /dev/null +++ b/bores/defs.h @@ -0,0 +1,43 @@ +/* +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef btco_bores_defs_h +#define btco_bores_defs_h + +/* libbores version number. Please keep the following defines in sync! + * If the major version is X.Y.Z, the INT version will be 10000X + 100Y + Z + * Thus if the version is 0.5.13, the int version would be 513. */ +#define BORES_VERSION_STR "0.6.1" +#define BORES_VERSION_INT 601 + +#endif + + diff --git a/bores/hashdict.c b/bores/hashdict.c new file mode 100644 index 0000000..165815e --- /dev/null +++ b/bores/hashdict.c @@ -0,0 +1,222 @@ +/* +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "hashdict.h" +#include "util.h" +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#define DEFAULT_BUCKET_COUNT 30 + +struct Node_ { /* each node in the linked lists */ + char *key; + const void *value; + + struct Node_ *next; +}; +typedef struct Node_ Node; + +struct HashDict_ { + int bucketcount; /* how many buckets in this dictionary */ + Node *bucketheads;/* array of head nodes, one for each bucket. + * The data in the head node means nothing. The linked + * list begins with the node that head->next points to */ + void (*value_destroyer)(void*); /* function called to destroy values. + * If NULL, no function is called */ +}; + +/* declaration of private functions -----------------------------*/ +static void _destroy_node(HashDict *hd, Node* n); +static int _which_bucket(const char *key, int bucketcount); +static Node* _node_lookup(HashDict *hd, + const char *key); /* warning: this function has counter-intuitive + (but useful) beheavior (q.v.) */ +/* --------------------------------------------------------------*/ + +HashDict* hashdict_create_ex(int bucketcount, void (*value_destroyer)(void*)) { + HashDict *hd = zalloc(sizeof(struct HashDict_)); + hd->bucketcount = bucketcount; + hd->value_destroyer = value_destroyer; + hd->bucketheads = zalloc(sizeof(Node) * bucketcount); + + return hd; +} + +HashDict* hashdict_create(void) { + return hashdict_create_ex(DEFAULT_BUCKET_COUNT, 0); +} + +void hashdict_destroy(HashDict* hd) { + int i; Node *n; + if (!hd) return; + + /* destroy all nodes */ + for (i = 0; i < hd->bucketcount; i++) { + while ( (n = hd->bucketheads[i].next) ) { + /* delete node n */ + hd->bucketheads[i].next = n->next; + _destroy_node(hd, n); + } + } + + free(hd->bucketheads); + free(hd); +} + +void* hashdict_get(HashDict *hd, const char *key) { + Node *n = _node_lookup(hd, key); + + /* be mindful that _node_lookup returns the node BEFORE + the one we are looking for */ + return (void*) (n->next ? n->next->value : 0); +} + +void hashdict_set(HashDict *hd, const char *key, const void *value) { + Node *n; + if (!value) { hashdict_unset(hd, key); return; } + + n = _node_lookup(hd, key); + if (n->next) { + /* node already exists: replace value */ + if (hd->value_destroyer) (*hd->value_destroyer)((void*)n->next->value); + n->next->value = value; + } + else { + /* does not exist yet: append to list */ + Node *newnode = zalloc(sizeof(Node)); + newnode->key = sstrdup(key); + newnode->value = value; + newnode->next = NULL; + n->next = newnode; + } +} + +bool hashdict_unset(HashDict *hd, const char *key) { + Node *n = _node_lookup(hd, key); + if (n->next) { + _destroy_node(hd, n->next); + n->next = n->next->next; + return true; /* found and deleted */ + } + return false; /* not found */ +} + +void hashdict_write(HashDict *hd, FILE *f, void (*value_writer)(void*, FILE*)) { + /* TODO */ +} + +HashDict* hashdict_read(HashDict *hd, FILE *f, void* (*valuereader)(FILE*)) { + /* TODO */ + return NULL; +} + +HashDictIt hashdict_it_start(HashDict *hd) { + HashDictIt it; + + /* put iterator before beginning */ + it.pastend = false; + it.key = it.value = NULL; + it.dict = hd; + it.nextbucket = 0; + it.nextnode = NULL; + + return it; +} + +bool hashdict_it_advance(HashDictIt *hdi) { + if (hdi->pastend) return false; /* already at the end */ + + if (hdi->nextnode) { + hdi->key = ((Node*)hdi->nextnode)->key; + hdi->value = ((Node*)hdi->nextnode)->value; + hdi->nextnode = ((Node*)hdi->nextnode)->next; + } + else { + /* go to next nonempty bucket */ + HashDict *hd = hdi->dict; + int i = hdi->nextbucket; + while (i < hd->bucketcount && !hd->bucketheads[i].next) i++; + + if (i < hd->bucketcount) { + /* we know hd->buckethead[i].next is not NULL */ + hdi->key = hd->bucketheads[i].next->key; + hdi->value = hd->bucketheads[i].next->value; + hdi->nextbucket = i+1; + hdi->nextnode = hd->bucketheads[i].next->next; + } + else { + /* passed the end */ + hdi->key = hdi->value = NULL; /* for safety */ + hdi->pastend = true; + return false; + } + } + + return true; +} + +/* private functions ----------------------------------------------------- */ +static Node* _node_lookup(HashDict *hd, const char *key) { + /* ATTENTION: return value is not the node you are looking for; + * rather, it is the node BEFORE it. This is useful for a variety + * of reasons, including node deletion and appending */ + + /* returns ptr to node n such that n->next->key is equal to <key>. + * If not found, returns the last node in the bucket that <key> + * hashes into. (in this case, the 'next' field of the return + * value will be NULL, since it is the last node in a list). */ + Node *n = &(hd->bucketheads[_which_bucket(key, hd->bucketcount)]); + while (n->next && strcmp(n->next->key, key)) n = n->next; + return n; +} + +static void _destroy_node(HashDict *hd, Node* n) { + if (n) { + if (hd->value_destroyer && n->value) + (*hd->value_destroyer)((void*)n->value); + zfree(&n->key); + free(n); + } +} + +static int _which_bucket(const char *key, int bucketcount) { + /* this function computes the hashcode of the given key + * in a dictionary with <bucketcount> buckets. If str is non-NULL + * and bucketcount > 0, the return value is guaranteed to be + * nonnegative and smaller than bucketcount. */ + + /* FIXME: write a serious hash function. This one is laughable. */ + + int x = 0; + while (*key) x += *(key++); + return x % bucketcount; +} + diff --git a/bores/hashdict.h b/bores/hashdict.h new file mode 100644 index 0000000..e8be9f3 --- /dev/null +++ b/bores/hashdict.h @@ -0,0 +1,139 @@ +/* +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +/* hashdict.h + * A general purpose dictionary implemented by means of a hashtable. + * This dictionary maps string keys to values of arbitrary type. + * It allows the specification of a value-destroy function that will + * be called whenever values are to be overwritten or deleted. + * + * Restrictions: + * + * - keys must be strings of positive length, and must of course be + * unique. + * + * - values may not be NULL, because NULL is used as a + * return value to indicate absense of keys, and because when writing/reading + * to a file handling of NULL values would complicate things. + * + * Copyright (c) 2003 by Bruno T. C. de Oliveira + * All rights reserved. + * + * 2003.01.07 + */ + +#ifndef btco_bores_hashdict_h +#define btco_bores_hashdict_h + +#include <stdio.h> +#include <stdbool.h> + +/* opaque dictionary handle */ +struct HashDict_; +typedef struct HashDict_ HashDict; + +/* iterator type */ +struct HashDictIt_ { + /* indicates whether this iterator is past the end of the dictionary */ + bool pastend; + + /* key and value of entry iterator is currently pointing to. Read only. */ + const char *key; + const void *value; + + /* internal data. Do not tamper with. */ + HashDict* dict; /* the dictionary this iterator pertains to */ + int nextbucket; /* the next bucket to be visited after this one ends */ + void *nextnode; /* the next node in this bucket to be visited. If + NULL, next advancement will cause the iterator + to go to the next nonempty bucket */ +}; +typedef struct HashDictIt_ HashDictIt; + +/* Creates a new dictionary with default bucketcount and no value destroyer + * function. */ +HashDict* hashdict_create(void); + +/* Creates a new dictionary given bucketcount and a value destroyer function.*/ +HashDict* hashdict_create_ex(int bucketcount, void (*valuedestroyer)(void*)); + +/* Destroy a dictionary previously created by hashdict_create */ +void hashdict_destroy(HashDict* hd); + +/* Look up key <key> in the dictionary. Returns the associated value, + * or NULL if the value is not found. */ +void* hashdict_get(HashDict* hd, const char *key); + +/* Sets the value associated to the given key. If the key already exists, + * the value associated to it will be overwritten (and the value- + * destroyer function will be called); otherwise, a new entry will be added. + * + * As a convenience, if value is NULL, this function is equivalent + * to hashdict_unset(hd, key) */ +void hashdict_set(HashDict* hd, const char *key, const void *value); + +/* Removes from the dictionary the entry whose key is <key>, if it exists. + * If it was removed, returns true; if it was not found, returns false */ +bool hashdict_unset(HashDict* hd, const char *key); + +/* Writes dictionary to file f in a binary format. valuewriter is a + * function that will be used to write the values onto the stream. */ +void hashdict_write(HashDict *hd, FILE *f, void (*valuewriter)(void*, FILE*)); + +/* Reads a dictionary previously saved with hashdict_write. + * valuereader is a function that will be used to read values from + * the stream. If valuereader returns NULL at any time, this + * function will interpret it as an error. If this happens, + * or if any other error occurs, this function will return NULL. */ +HashDict* hashdict_read(HashDict *hd, FILE *f, void* (*valuereader)(FILE*)); + +/* Returns a new hash dict iterator that points BEFORE the first entry + * in the dictionary. Iterators are lightweight objects, i.e., + * they don't need to be deallocated. That's why there is no + * hashdict_it_destroy function. + * + * Please note that the iterator returned is not in a valid position + * (it is BEFORE the start). You must advance it before using the value. + * This behavior is useful because you can write neat loops: + * + * it = hashdict_it_start(hd); + * while (hashdict_it_advance(it)) { + * // use it->key and it->value here + * } + */ +HashDictIt hashdict_it_start(HashDict *hd); + +/* Advances the given iterator. Returns true if advancement was successful, + * or false if the end of the dictionary was reached. */ +bool hashdict_it_advance(HashDictIt *hdi); + +#endif + diff --git a/bores/kurses.c b/bores/kurses.c new file mode 100644 index 0000000..619c963 --- /dev/null +++ b/bores/kurses.c @@ -0,0 +1,293 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "kurses.h" +#include "util.h" +#include <ncurses.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +/* mapping between color codes and curses pairs and attributes: + * + * color pair depends on the three least significant bits of the foreground + * and background. If a pair is (fg, bg), + * let FG = fg % 8 (i.e. the three least significant bits) + * let BG = bg % 8 + * + * the curses pair for it will be BG * 8 + (7 - FG) + * + * Valid curses pairs are 1..63, but the color (7, 0) maps to pair number 0. + * This is no problem, because (7, 0) is the default color so it needs + * no curses color pair. + * + * After the color pair is selected, the most significant bit of + * fg and bg are used to activate A_BOLD and A_BLINK attributes. + */ + +/* --------- internal data and declarations of private functions ---------- */ + +/* current foreground and background colors */ +static int cur_fg, cur_bg; + +/* Given a pair of color codes, returns the corresponding curses pair */ +static int kurses_pair_for(int fg, int bg); + +/* node type for the saved screen linked list (see below) */ +struct SavedScreenNode_ { + WINDOW *win; /* the curses window that holds the screenshot */ + struct SavedScreenNode_* next; +}; +typedef struct SavedScreenNode_ SavedScreenNode; + +/* Stack of saved screens, implemented as a linked list */ +SavedScreenNode *sss_top; /* sss = 'saved screen stack' */ + +/* -------------- implementation of public functions ---------------------- */ + +void kurses_init() { + int fg, bg; + + initscr(); /* enter screen-oriented mode */ + raw(); /* don't treat Ctrl+C, etc. as special. */ + noecho(); /* don't echo typed characters back to terminal */ + keypad(stdscr, TRUE); /* convert ugly escape sequences to more + * palatable curses KEY_* codes */ + + cur_fg = 7; + cur_bg = 0; + sss_top = NULL; + + if (!has_colors()) { + fprintf(stderr, "*** Fatal error: Terminal has no color support.\n"); + exit(1); + } + + start_color(); + + /* initialize all curses pairs */ + for (fg = 0; fg < 8; fg++) for (bg = 0; bg < 8; bg++) { + int pair = kurses_pair_for(fg, bg); + if (!pair) continue; /* don't try to initialize pair 0, + * that corresponds to color (7, 0). */ + + init_pair(pair, fg, bg); + } + + clear(); + refresh(); +} + +void kurses_finalize() { + clear(); + refresh(); + endwin(); +} + +void kurses_color(int fg, int bg) { + int pair; + + if (fg < 0) fg = cur_fg; + if (bg < 0) bg = cur_bg; + + /* see what color pair corresponds to fg, bg */ + pair = kurses_pair_for(fg, bg); + + /* if that maps to 0, just reset attribute; otherwise set color pair */ + if (pair) attrset(COLOR_PAIR(pair)); + else attrset(A_NORMAL); + + /* now turn on A_BOLD and A_BLINK attribute as indicated by the most + * significant bit of fg and bg, respectively */ + if (fg & 0x08) attron(A_BOLD); + if (bg & 0x08) attron(A_BLINK); +} + +/* Same as kurses_color(attr >> 4, attr & 0x0F) */ +void kurses_color_at(int attr) { + kurses_color(attr >> 4, attr & 0x0F); +} + +int kurses_width() { + int maxy, maxx; + getmaxyx(stdscr, maxy, maxx); + return maxx; +} + +int kurses_height() { + int maxy, maxx; + getmaxyx(stdscr, maxy, maxx); + return maxy; +} + +int kurses_pos_valid(int x, int y) { + return (x >= 0 && x < kurses_width() && + y >= 0 && y < kurses_height()); +} + +int kurses_move(int x, int y) { + if (!kurses_pos_valid(x, y)) return 0; + move(y, x); + return 1; +} + +int kurses_line_input(char *buf, int buf_size) { + return kurses_line_input_ex(buf, buf_size, NULL, 0); +} + +int kurses_line_input_ex(char *buf, int buf_size, int *skeys, int flags) { + int pos = 0; + int ch; + const int *p; + + while (1) { + refresh(); + ch = getch(); + if (ch < 0) continue; + + /* first check if character is in skeys */ + if ( (p = skeys) ) while (*p) if (*(p++) == ch) return -ch; + + /* proceed to normal handling */ + switch (ch) { + case 10: buf[pos] = 0; return 1; /* confirm input */ + case 3: + case 7: + case 27: *buf = 0; return 0; /* cancel input */ + case KEY_BACKSPACE: case 8: case 127: /* backspace */ + if (pos > 0) { --pos; addch('\b'); addch(' '); addch('\b'); } + break; + case 'U' - 0x40: /* kill */ + while (pos--) { addch('\b'); addch(' '); addch('\b'); } + pos = 0; + break; + default: + if (pos <= buf_size - 2 && printable_char(ch)) { + /* buffer not full (remember to reserve a byte for the NULL), + * and character is not a control character: append it */ + buf[pos++] = ch; + addch((flags & KURSES_LI_HIDE) ? '*' : ch); + } + } + } +} + +void draw_window(int x0, int y0, int w, int h, const char *title) { + int x, y, x1, y1; + int gr_ch[3][3]; + + gr_ch[0][0]=ACS_ULCORNER, gr_ch[0][1]=ACS_HLINE, gr_ch[0][2]=ACS_URCORNER; + gr_ch[1][0]=ACS_VLINE, gr_ch[1][1]=' ', gr_ch[1][2]=ACS_VLINE; + gr_ch[2][0]=ACS_LLCORNER, gr_ch[2][1]=ACS_HLINE, gr_ch[2][2]=ACS_LRCORNER; + + x1 = x0 + w - 1; + y1 = y0 + h - 1; + + for (y = y0; y < y0 + h; y++) + for (x = x0; x < x0 + w; x++) + if (!kurses_move(x, y)) continue; + else addch(gr_ch [(y == y0) ? 0 : (y == y1) ? 2 : 1] + [(x == x0) ? 0 : (x == x1) ? 2 : 1]); + + if (title) if (kurses_move(x0 + w/2 - strlen(title) / 2, y0)) addstr(title); + kurses_move(x0 + 1, y0 + 1); +} + +void draw_centered_window(int w, int h, const char *title, int *x, int *y) { + int x0 = (kurses_width() - w) / 2; + int y0 = (kurses_height() - h) / 2; + if (x) *x = x0 + 1; + if (y) *y = y0 + 1; + + draw_window(x0, y0, w, h, title); +} + +void draw_hline(int x0, int y0, int w, + int left_endpt, int interim, int right_endpt) +{ + int x; + if (!kurses_move(x0, y0)) return; + for (x = x0; x < x0 + w; x++) + addch( (x == x0) ? left_endpt : + (x == x0 + w - 1) ? right_endpt : interim); +} + +void draw_vline(int x0, int y0, int h, + int upper_endpt, int interim, int lower_endpt) { + int y; + if (!kurses_move(x0, y0)) return; + for (y = y0; y < y0 + h; y++) { + kurses_move(x0, y); + addch( (y == y0) ? upper_endpt : + (y == y0 + h - 1) ? lower_endpt : interim); + } +} + +void push_screen(void) { + SavedScreenNode *n = zalloc(sizeof(SavedScreenNode)); + n->win = newwin(0,0,0,0); + overwrite(stdscr, n->win); + n->next = sss_top; + + sss_top = n; +} + +void restore_screen(void) { + if (!sss_top) { + /* if there are no saved screens, just clear the screen and return. + * Doesn't make much sense, but beats doing nothing or segfaulting. */ + erase(); + return; + } + + overwrite(sss_top->win, stdscr); + touchwin(stdscr); +} + +void pop_screen(void) { + SavedScreenNode *newtop; + if (!sss_top) return; + + newtop = sss_top->next; + free(sss_top); + sss_top = newtop; +} + +/* -------------- implementation of private functions --------------------- */ +static int kurses_pair_for(int fg, int bg) { + fg &= 0x07; bg &= 0x07; /* only keep the three least significant bits */ + return (bg << 3) + (7 - fg); +} + + + diff --git a/bores/kurses.h b/bores/kurses.h new file mode 100644 index 0000000..0f40cde --- /dev/null +++ b/bores/kurses.h @@ -0,0 +1,133 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + + +#ifndef _btco_bores_kurses_h +#define _btco_bores_kurses_h + +/* Color codes are 4-bit values. The bits are SBGR, where B, G and R are + * the blue, green and red components, and the S bit is the bold attribute + * for foreground colors, or the blink attribute for background colors. + * + * Refer to the implementation file for information about how color code + * pairs are mapped to curses pairs */ + +/* Initializes curses, sets screen mode, initializes pairs, and so on. */ +void kurses_init(); + +/* Finalize curses */ +void kurses_finalize(); + +/* Sets the active color to (fg, bg). Either can be -1, in which case + * the previous value is kept. */ +void kurses_color(int fg, int bg); + +/* Same as kurses_color(attr >> 4, attr & 0x0F) */ +void kurses_color_at(int attr); + +/* Returns the screen width */ +int kurses_width(); + +/* Returns the screen height */ +int kurses_height(); + +/* Moves cursor to position (x, y). Returns true if motion was successful, + * false if given coordinates are invalid */ +int kurses_move(int x, int y); + +/* Returns whether position x,y falls within screen bounds */ +int kurses_pos_valid(int x, int y); + +/* Reads a line of input from the keyboard, storing read characters in + * <buf>. At most <buf_size> characters are stored in the buffer. + * Interprets the "backspace" and "kill" keys. Returns true if the + * user ended input by pressing RETURN; false if the user cancelled + * input by means of ESC, Ctrl+C or Ctrl+G. */ +int kurses_line_input(char *buf, int buf_size); + +/* Does the same as kurses_line_input, but with an extended feature: + * the array skeys of ints specifies special keys; when the user + * presses any of those special keys, input will stop and the negative + * of the value of the key will be returned. Character '\0' must + * be at the end the skeys array. The flags parameter are an OR'ed + * combination of the KURSES_LI_* flags defined below. + * + * If the user cancels input, returns 0. + * If the user confirms input without pressing any special key, + * returns 1. + */ +int kurses_line_input_ex(char *buf, int buf_size, int* skeys, int flags); + #define KURSES_LI_HIDE 1 /* echoes '*' instead of characters */ + +/* Draws a window with the specified position, dimensions and title. + * Uses currently active color. After operation, cursor will be + * placed on top-left character of CLIENT AREA of window. */ +void draw_window(int x, int y, int w, int h, const char *title); + +/* Draws a window centered onscreen. Returns in *x and *y the position + * of the top-left character cell within the window's CLIENT AREA, + * which is also where the cursor is located after the call. */ +void draw_centered_window(int w, int h, const char *title, int *x, int *y); + +/* Draws a horizontal row of <w> characters starting at position x0, y0. + * The first character draw will be left_endpt; then character interim + * will be drawn w-2 times, then the right_endpt will be drawn. */ +void draw_hline(int x0, int y0, int w, + int left_endpt, int interim, int right_endpt); + +/* Same idea as draw_hline, but draws a vertical line instead. */ +void draw_vline(int x0, int y0, int h, + int upper_endpt, int interim, int lower_endpt); + +/* Saves a snapshot of the screen (stdscr) onto an internal stack. + * That snapshot can be later restored through a call to + * pop_screen */ +void push_screen(void); + +/* Restores a screen snapshot previously saved with push_screen. + * Does NOT pop it from the stack: it will stay there in case + * you want to restore it again. To discard it from the stack, + * call pop_screen(void) + * + * Does NOT call refresh; you will have to do that yourself. */ +void restore_screen(void); + +/* Removes the top of the internal screen snapshot stack. + * Does NOT paint the removed snapshot to the screen. If you + * want that, call restore_screen() _before_ calling + * pop_screen */ +void pop_screen(void); + + +#endif + diff --git a/bores/util.c b/bores/util.c new file mode 100644 index 0000000..828f4a6 --- /dev/null +++ b/bores/util.c @@ -0,0 +1,270 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "util.h" +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> + +char *dstrset(char **ptr, const char *new_value) { + if (*ptr) free(*ptr); + return (*ptr = new_value ? sstrdup(new_value) : 0); +} + +void *zalloc(int bytes) { + void *buf; + + if (bytes <= 0) return 0; + + if (!(buf = malloc(bytes))) { + fprintf(stderr, "*** FATAL ERROR ***\n" + "zalloc failed to allocate memory.\n" + "Request size: %d bytes.\n\nSorry.\n", bytes); + abort(); + } + + memset(buf, 0, bytes); + return buf; +} + +char* sstrdup(const char *s) { + char *r; + if (!s) return 0; + + if ( !(r = strdup(s)) ) { + fprintf(stderr, "*** FATAL ERROR ***\n" + "sstrdup failed to allocate memory.\n"); + abort(); + } + return r; +} + +void *srealloc(void *buf, int newsize) { + if (!buf) return zalloc(newsize); + if (!(buf = realloc(buf, newsize))) { + fprintf(stderr, "*** FATAL ERROR ***\n" + "srealloc failed to reallocate memory.\n" + "Request size: %d bytes.\n\nSorry.\n", newsize); + abort(); + } + return buf; +} + +int minimum(int a, int b) { return (a < b) ? a : b; } +int maximum(int a, int b) { return (a > b) ? a : b; } +double minimum_d(double a, double b) { return (a < b) ? a : b; } +double maximum_d(double a, double b) { return (a > b) ? a : b; } + + +int printable_char(int ch) { + if (ch < 0 || ch > 255) return 0; /* not in char range */ + if (ch <= 31 || ch == 127) return 0; /* control character */ + return 1; +} + +char *str_fit_ex(const char *orig, int size, int padch) { + char *s; char *p; + if (size <= 0) return 0; + + p = s = zalloc(size + 1); + while (p - s < size) + *(p++) = (*orig) ? *(orig++) : padch; + + *p = 0; + return s; +} + +char *str_fit(const char *orig, int size) { + return str_fit_ex(orig, size, ' '); +} + +float timeval_dif(const struct timeval* a, const struct timeval* b) { + long to_remove; + float af, bf; + if (a->tv_sec > b->tv_sec) to_remove = b->tv_sec; + else to_remove = a->tv_sec; + + af = (float)(a->tv_sec - to_remove) + a->tv_usec / 1000000.0f; + bf = (float)(b->tv_sec - to_remove) + b->tv_usec / 1000000.0f; + return af - bf; +} + +void fsavestr(const char *str, FILE *f) { + int len = strlen(str); + + fwrite(&len, sizeof(int), 1, f); + while (*str) fputc(*(str++), f); +} + +char *floadstr(FILE *f) { + char *str, *p; int len; + + fread(&len, sizeof(int), 1, f); + + p = str = zalloc(len + 1); + while (len--) *(p++) = fgetc(f); + + return str; +} + +void interval_intersect(int a0, int a1, int b0, int b1, int *c0, int *c1) { + *c0 = maximum(a0, b0); + *c1 = minimum(a1, b1); +} + +void interval_intersect_d(double a0, double a1, double b0, double b1, + double *c0, double *c1) { + *c0 = maximum_d(a0, b0); + *c1 = minimum_d(a1, b1); +} + +void sort_two(int v0, int v1, int *r0, int *r1) { + if (v0 <= v1) { + if (r0) *r0 = v0; + if (r1) *r1 = v1; + } + else { + if (r0) *r0 = v1; + if (r1) *r1 = v0; + } +} + +char *dsprintf(const char *fmt, ...) { + /* this function was adapted from the example provided in + * Linux man page for printf(3) */ + int n, size = 100; + char *p; + va_list ap; + + p = zalloc(size); + + while (1) { + /* Try to print in the allocated space. */ + va_start(ap, fmt); n = vsnprintf (p, size, fmt, ap); va_end(ap); + + /* If that worked, return the string. */ + if (n > -1 && n < size) return p; + + /* Else try again with more space. */ + if (n > -1) /* glibc 2.1 */ + size = n+1; /* precisely what is needed */ + else /* glibc 2.0 */ + size *= 2; /* twice the old size */ + + p = srealloc (p, size); + } +} + +void sfree(void *ptr) { + if (ptr) free(ptr); +} + +void zfree(char **str) { + if (*str) { + free(*str); + *str = 0; + } +} + +char *freadline(FILE *f) { + return freadline_ex((void*)f, (int(*)(void*)) fgetc); +} + +char *freadline_ex(void *fh, int (*readch)(void*)) { + int size = 64; + char *buf; + int i; + char ch; + + /* read in the first character */ + ch = readch(fh); + if (ch < 0) return NULL; + + /* allocate buffer */ + buf = zalloc(size + 1); + i = 0; + + /* store and read over and over until \n or EOF */ + while (ch != '\n' && ch != -1) { + buf[i++] = ch; + if (i >= size) buf = srealloc(buf, 1 + (size += size)); + + ch = readch(fh); + } + + buf[i] = 0; /* we know we can write on buf[i] because we know i <= size, + * (remember that buf has capacity is size + 1) */ + return buf; +} + +char *strtrim(const char *s) { + char *t, *u; + while (*s == ' ' || *s == '\t' || *s == '\n') s++; + t = sstrdup(s); + u = t + strlen(t) - 1; + while (u >= t && (*u == ' ' || *u == '\t' || *u == '\n')) u--; + u[1] = 0; + return t; +} + +char *dstrcat(const char *s, const char *t) { + char *u = zalloc(1 + (s ? strlen(s) : 0) + (t ? strlen(t) : 0)); + if (s) strcpy(u, s); + if (t) strcat(u, t); + return u; /* zalloc zeroes out the buffer, so even if s == t == NULL, + * u will be a single '\0', which is a correct result. */ +} + +void chr2hex(int c, char* ret) { + static char hs[] = "0123456789abcdef"; + + if (c <= 0) c = 0; + if (c >= 256) c = 255; + + ret[0] = hs[c / 16]; + ret[1] = hs[c % 16]; + ret[2] = 0; +} + +static int hex_digit_val(char c) { + if (c >= '0' && c <= '9') return c - '0'; + else if (c >= 'a' && c <= 'f') return c - 'a' + 10; + else if (c >= 'A' && c <= 'F') return c - 'A' + 10; + else return 0; +} + +int hex2chr(const char *hex) { + return hex_digit_val(hex[0]) * 16 + hex_digit_val(hex[1]); +} + diff --git a/bores/util.h b/bores/util.h new file mode 100644 index 0000000..8a5605a --- /dev/null +++ b/bores/util.h @@ -0,0 +1,169 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef bores_util_h +#define bores_util_h +#include <sys/time.h> +#include <stdbool.h> +#include <stdio.h> + +#define FMTCALL(x, f) { char *fmts = dsprintf x; f; zfree(&fmts); } + +/* If (*ptr) { free(*ptr), *ptr = NULL; }. Then, makes *ptr = + * strdup(new_value) if new_value is not NULL. Returns the value *ptr + * after the assignment. */ +char *dstrset(char **ptr, const char *new_value); + +/* If *str { free(*str); *str = NULL; } */ +void zfree(char **str); + +/* If ptr, free(ptr) */ +void sfree(void *ptr); + +/* Does what you expect */ +int minimum(int a, int b); + +/* Duh. */ +int maximum(int a, int b); + +/* Does what you expect */ +double minimum_d(double a, double b); + +/* Duh. */ +double maximum_d(double a, double b); + +/* Allocates memory like malloc, with the following differences: (1) exits + * program with a fatal error if memory cannot be allocated; (2) zeroes + * out the newly allocated buffer before returning. This function returns + * NULL if and only if bytes <= 0. */ +void *zalloc(int bytes); + +/* If <buf> is not null, works just like realloc. If <buf> is null, + * calls zalloc instead of realloc. Returns a pointer to the reallocated + * (or newly allocated) buffer; NULL if and only if newsize <= 0. */ +void *srealloc(void *buf, int newsize); + +/* Returns true if the passed character ch is printable */ +int printable_char(int ch); + +/* Returns a dynamically allocated string whose length is exactly <size>. + * If strlen(<orig>) <= <size>, returned string is a copy of <orig> + * padded with padch characters. If strlen(<orig>) > <size>, returned + * string is a copy of <orig> clipped to <size>. + * + * Returns NULL if the fitting cannot be done because <size> is invalid */ +char *str_fit_ex(const char *orig, int size, int padch); + +/* Convenience function that calls + * str_fit_ex(orig, size, ' ') */ +char *str_fit(const char *orig, int size); + +/* Returns difference in seconds between the two passed + * timevals. This difference will be positive if a > b, + * negative if a < b, or zero if a and b are the same */ +float timeval_dif(const struct timeval* a, const struct timeval* b); + +/* Saves the string pointed to by <str> in the file <f>, in a format + * that can later be read back by floadstr() */ +void fsavestr(const char *str, FILE *f); + +/* Loads a string from file <f>, as saved by fsavestr(). Returns a dynamically + * allocated string (which the caller must free) or NULL if there is an + * error. */ +char *floadstr(FILE *f); + +/* Calculates the intersection of two integer intervals with inclusive + * endpoints. Interval [a0..a1], where a0 <= a1, is intersected with + * interval [b0..b1], where b0 <= b1. The resulting interval [c0..c1] is + * stored in variables c0 and c1. An empty interval is denoted by + * c0 > c1. */ +void interval_intersect(int a0, int a1, int b0, int b1, int *c0, int *c1); + +/* Same as interval_intersect, but with doubles */ +void interval_intersect_d(double a0, double a1, double b0, double b1, + double *c0, double *c1); + +/* Does what you expect */ +int minimum(int a, int b); + +/* Duh. */ +int maximum(int a, int b); + +/* Sorts the two values v0 and v1, returning the result in variables + * r0 and r1. Return value has the property that *r0 <= *r1 */ +void sort_two(int v0, int v1, int *r0, int *r1); + +/* Behaves like sprintf, but returns a dynamically allocated string + * as large as necessary to contain the results. Uses zalloc to allocate + * memory, so memory allocation does not fail (a fatal error is produced + * if system has insufficient memory) */ +char *dsprintf(const char *fmt, ...); + +/* Reads a full line from file f, allocating space as needed to contain it. + * Returns a dynamically allocated buffer, or NULL if EOF was read before + * any characters could be read in. The \n will NOT be included in the + * returned string (unlike fgets()). */ +char *freadline(FILE *f); + +/* Same as freadline, but in this function you specify a custom function + * to read characters from your stream, and the file handle is opaque + * (that is, can be anything you want, not necessarily a FILE*). + * When this function needs a character, it will call the readch + * function passing it the file handle fh, and expect it to return + * the next character on the stream or -1 if EOF is reached. */ +char *freadline_ex(void *fh, int (*readch)(void*)); + +/* Returns a new string that results from removing leading and trailing + * spaces from string s */ +char *strtrim(const char *s); + +/* Like strdup(), but aborts the program with a fatal error if memory + * cannot be allocated (rather than return NULL as strdup() does). + * Also, if s is NULL, returns NULL rather than segfaulting (which is + * what strdup() does). */ +char *sstrdup(const char *s); + +/* Returns a dynamically allocated string that results from the concatenation + * of strings s and t. NULL parameters are NOT an error and will be + * equivalent to empty strings. */ +char *dstrcat(const char *s, const char *t); + +/* Returns the hexadecimal representation of the given character + * as a two-digit hexadecimal number stored in the array ret, which + * must be of size 3. A trailing \0 is appended. The hex2chr function + * does the reverse */ +void chr2hex(int c, char* ret); +int hex2chr(const char *hex); + +#endif + @@ -0,0 +1,61 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include <ncurses.h> + +#include "chtr.h" + +int chtr_a2c(unsigned char aewan_ch) { + int mappings[32] = { + ACS_CKBOARD, + ACS_HLINE, + ACS_VLINE, + ACS_ULCORNER, + ACS_TTEE, + ACS_URCORNER, + ACS_LTEE, + ACS_PLUS, + ACS_RTEE, + ACS_LLCORNER, + ACS_BTEE, + ACS_LRCORNER, + ACS_CKBOARD, ACS_CKBOARD, ACS_CKBOARD, ACS_CKBOARD, ACS_CKBOARD, + ACS_CKBOARD, ACS_CKBOARD, ACS_CKBOARD, ACS_CKBOARD, ACS_CKBOARD, + ACS_CKBOARD, ACS_CKBOARD, ACS_CKBOARD, ACS_CKBOARD, ACS_CKBOARD, + ACS_CKBOARD, ACS_CKBOARD, ACS_CKBOARD, ACS_CKBOARD, ACS_CKBOARD + }; + + if (aewan_ch < 32) return mappings[aewan_ch]; + return aewan_ch; +} + @@ -0,0 +1,67 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewan_chtr_h +#define _btco_aewan_chtr_h + +/* Since a control character may never be in a cell, aewan uses some + * values in the 0-31 range to represent special characters. It does + * not use the curses ACS_ characters because their values are + * implementation dependent and are all greater than 255 (so they would + * not fit in an unsigned char anyway) + * + * The chtr in "chtr.h" stands for "character translation" + */ + +/* aewan special values for a cell's character */ +#define AEWAN_CHAR_HLINE 1 +#define AEWAN_CHAR_VLINE 2 +#define AEWAN_CHAR_ULCORNER 3 +#define AEWAN_CHAR_TTEE 4 +#define AEWAN_CHAR_URCORNER 5 +#define AEWAN_CHAR_LTEE 6 +#define AEWAN_CHAR_PLUS 7 +#define AEWAN_CHAR_RTEE 8 +#define AEWAN_CHAR_LLCORNER 9 +#define AEWAN_CHAR_BTEE 10 +#define AEWAN_CHAR_LRCORNER 11 +#define AEWAN_CHAR_CKBOARD 12 + +/* Maps an aewan character to a curses character. This is not restricted + * to special characters: regular characters will map to themselves. + * Control characters that do not have special meanings will map + * to some bogus (but printable) character. */ +int chtr_a2c(unsigned char aewan_ch); + +#endif + diff --git a/clipboard.c b/clipboard.c new file mode 100644 index 0000000..bef9eaa --- /dev/null +++ b/clipboard.c @@ -0,0 +1,70 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include <stdio.h> + +#include "clipboard.h" +#include "document.h" +#include "psd.h" + +void clear_clipboard(void) { + if (_clipboard) layer_destroy(_clipboard); + _clipboard = NULL; +} + +void copy_sel_to_clipboard(void) { + int selwidth, selheight; + int x0, x1, y0, y1; + + /* calculate selection dimensions */ + get_norm_sel(&x0, &y0, &x1, &y1); + selwidth = x1 - x0 + 1; + selheight = y1 - y0 + 1; + + /* size clipboard appropriately */ + clear_clipboard(); + _clipboard = layer_create("clipboard", selwidth, selheight); + + /* blit from currently active document layer to clipboard */ + layer_blit(_doc->layers[_lyr], x0, y0, selwidth, selheight, + _clipboard, 0, 0); + +} + +void paste_clipboard(void) { + if (!_clipboard) return; + layer_blit(_clipboard, 0, 0, _clipboard->width, _clipboard->height, + _doc->layers[_lyr], _x, _y); +} + + diff --git a/clipboard.h b/clipboard.h new file mode 100644 index 0000000..52df428 --- /dev/null +++ b/clipboard.h @@ -0,0 +1,52 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + + +#ifndef _btco_aewan_clipboard_h +#define _btco_aewan_clipboard_h + +#include "layer.h" + +/* Clears clipboard, freeing its memory */ +void clear_clipboard(void); + +/* Copies the current selection to the clipboard layer */ +void copy_sel_to_clipboard(void); + +/* Pastes the clipboard contents onto the document, + placing the top-left corner at the position of the cursor */ +void paste_clipboard(void); + +#endif + + diff --git a/colordlg.c b/colordlg.c new file mode 100644 index 0000000..599b64c --- /dev/null +++ b/colordlg.c @@ -0,0 +1,96 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "bores/bores.h" +#include <ncurses.h> + +#include "colordlg.h" +#include "psd.h" + +static void paint_dlg(void) { + int x0, y0; int i, j; + char hexdigit[] = "0123456789abcdef"; + + kurses_color(7, 0); + draw_centered_window(39, 21, "Choose Color", &x0, &y0); + + /* draw bg color knob */ + kurses_color(12, 0); + kurses_move(x0 + 4 + 2 * _bg, y0); + addch('b'); + + /* draw fg color knob */ + kurses_color(10, 0); + kurses_move(x0, y0 + 2 + _fg); + addch('f'); + + /* draw horizontal (bg) ruler */ + kurses_color(7, 0); + kurses_move(x0 + 4, y0 + 1); + addstr("0 1 2 3 4 5 6 7 8 9 a b c d e f"); + + /* draw vertical (fg) ruler */ + for (i = 0; i < 16; i++) { + kurses_move(x0 + 2, y0 + 2 + i); + addch(hexdigit[i]); + } + + /* draw squares */ + for (i = 0; i < 16; i++) { + kurses_move(x0 + 4, y0 + 2 + i); + for (j = 0; j < 16; j++) { + kurses_color(i, j); + addstr("Aa"); + } + } + + /* place cursor on selected square */ + kurses_move(x0 + 4 + 2 * _bg, y0 + 2 + _fg); +} + +void show_color_dlg(void) { + int ch; + while (1) { + paint_dlg(); + refresh(); + ch = getch(); + switch (ch) { + case 27: case 3: case 7: case 10: return; + case KEY_UP: if (--_fg < 0) _fg = 15; break; + case KEY_DOWN: if (++_fg >= 16) _fg = 0; break; + case KEY_LEFT: if (--_bg < 0) _bg = 15; break; + case KEY_RIGHT: if (++_bg >= 16) _bg = 0; break; + } + } +} + diff --git a/colordlg.h b/colordlg.h new file mode 100644 index 0000000..39e225b --- /dev/null +++ b/colordlg.h @@ -0,0 +1,44 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + + +#ifndef _btco_aewan_colordlg_h +#define _btco_aewan_colordlg_h + +/* invokes the "set color" dialog, which allows the user to interactively + * modify the globals _fg and _bg. Only returns after the user has quit + * the dialog box. Does not restore screen. */ +void show_color_dlg(void); + +#endif + diff --git a/commands.h b/commands.h new file mode 100644 index 0000000..ed7fb3d --- /dev/null +++ b/commands.h @@ -0,0 +1,83 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef btco_aewan_commands_h +#define btco_aewan_commands_h + +/* Commands are what make the editor _do_ things. The keys that the + * user presses are translated to commands and then fed into + * the main command-handling function handle_command() */ +#define COMMAND_UNDEFINED 0 /* special value used as error flag */ +#define COMMAND_ADD_LAYER_DEFAULTS 1 +#define COMMAND_ADD_LAYER_SPECIFY 2 +#define COMMAND_SET_FOREGROUND 3 +#define COMMAND_SET_BACKGROUND 4 +#define COMMAND_SHOW_COLOR_DLG 5 +#define COMMAND_TOGGLE_INSERT 6 +#define COMMAND_SHOW_HELP_DLG 7 +#define COMMAND_LOAD_FILE 8 +#define COMMAND_SAVE_FILE 9 +#define COMMAND_SAVE_FILE_AS 10 +#define COMMAND_EDIT_META 11 +#define COMMAND_MOVE_LEFT 12 +#define COMMAND_MOVE_RIGHT 13 +#define COMMAND_MOVE_UP 14 +#define COMMAND_MOVE_DOWN 15 +#define COMMAND_CARRIAGE_RETURN 16 +#define COMMAND_PAGE_DOWN 17 +#define COMMAND_PAGE_UP 18 +#define COMMAND_START_OF_LINE 19 +#define COMMAND_END_OF_LINE 20 +#define COMMAND_FAST_LEFT 21 +#define COMMAND_FAST_RIGHT 22 +#define COMMAND_PICK_COLOR 23 +#define COMMAND_TINT_CELL 24 +#define COMMAND_TOGGLE_SELECTION 25 +#define COMMAND_CANCEL 26 +#define COMMAND_SHOW_LAYER_DLG 27 +#define COMMAND_NEXT_LAYER 28 +#define COMMAND_PREV_LAYER 29 +#define COMMAND_DUP_LAYER 30 +#define COMMAND_RENAME_LAYER 31 +#define COMMAND_TOGGLE_LINE_MODE 32 +#define COMMAND_TOGGLE_COMPOSITE 33 +#define COMMAND_QUIT 34 +#define COMMAND_NEW_FILE 35 +#define COMMAND_SHOW_ABOUT_DLG 36 +#define COMMAND_RESIZE_LAYER 37 +#define COMMAND_TOTAL 38 /* total number of commands + (for sizing arrays and the like) */ + +#endif + + diff --git a/configure b/configure new file mode 100755 index 0000000..3fc5552 --- /dev/null +++ b/configure @@ -0,0 +1,4558 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.59. +# +# Copyright (C) 2003 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="aewan" +ac_unique_file="aewan.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#if HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#if HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#if STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# if HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#if HAVE_STRINGS_H +# include <strings.h> +#endif +#if HAVE_INTTYPES_H +# include <inttypes.h> +#else +# if HAVE_STDINT_H +# include <stdint.h> +# endif +#endif +#if HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP EXESUF LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have + headers in a nonstandard directory <include dir> + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF + +Copyright (C) 2003 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + +#AC_CONFIG_HEADER([config.h]) + +# Checks for programs. +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 + (eval $ac_compiler --version </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 + (eval $ac_compiler -v </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 + (eval $ac_compiler -V </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include <stdlib.h> +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Check for the standard stdbool header file + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ctype.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +echo "$as_me:$LINENO: checking for stdbool.h that conforms to C99" >&5 +echo $ECHO_N "checking for stdbool.h that conforms to C99... $ECHO_C" >&6 +if test "${ac_cv_header_stdbool_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include <stdbool.h> +#ifndef bool +# error bool is not defined +#endif +#ifndef false +# error false is not defined +#endif +#if false +# error false is not 0 +#endif +#ifndef true +# error true is not defined +#endif +#if true != 1 +# error true is not 1 +#endif +#ifndef __bool_true_false_are_defined +# error __bool_true_false_are_defined is not defined +#endif + + struct s { _Bool s: 1; _Bool t; } s; + + char a[true == 1 ? 1 : -1]; + char b[false == 0 ? 1 : -1]; + char c[__bool_true_false_are_defined == 1 ? 1 : -1]; + char d[(bool) -0.5 == true ? 1 : -1]; + bool e = &s; + char f[(_Bool) -0.0 == false ? 1 : -1]; + char g[true]; + char h[sizeof (_Bool)]; + char i[sizeof s.t]; + +int +main () +{ + return !a + !b + !c + !d + !e + !f + !g + !h + !i; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdbool_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdbool_h=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdbool_h" >&5 +echo "${ECHO_T}$ac_cv_header_stdbool_h" >&6 +echo "$as_me:$LINENO: checking for _Bool" >&5 +echo $ECHO_N "checking for _Bool... $ECHO_C" >&6 +if test "${ac_cv_type__Bool+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((_Bool *) 0) + return 0; +if (sizeof (_Bool)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type__Bool=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type__Bool=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type__Bool" >&5 +echo "${ECHO_T}$ac_cv_type__Bool" >&6 +if test $ac_cv_type__Bool = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE__BOOL 1 +_ACEOF + + +fi + +if test $ac_cv_header_stdbool_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STDBOOL_H 1 +_ACEOF + +fi + + +# Checks for libraries. + +echo "$as_me:$LINENO: checking for initscr in -lncurses" >&5 +echo $ECHO_N "checking for initscr in -lncurses... $ECHO_C" >&6 +if test "${ac_cv_lib_ncurses_initscr+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lncurses $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char initscr (); +int +main () +{ +initscr (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_ncurses_initscr=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_ncurses_initscr=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_ncurses_initscr" >&5 +echo "${ECHO_T}$ac_cv_lib_ncurses_initscr" >&6 +if test $ac_cv_lib_ncurses_initscr = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNCURSES 1 +_ACEOF + + LIBS="-lncurses $LIBS" + +else + { { echo "$as_me:$LINENO: error: Can't find ncurses library. Install it first." >&5 +echo "$as_me: error: Can't find ncurses library. Install it first." >&2;} + { (exit 1); exit 1; }; } +fi + + +echo "$as_me:$LINENO: checking for gzopen in -lz" >&5 +echo $ECHO_N "checking for gzopen in -lz... $ECHO_C" >&6 +if test "${ac_cv_lib_z_gzopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gzopen (); +int +main () +{ +gzopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_z_gzopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_z_gzopen=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_z_gzopen" >&5 +echo "${ECHO_T}$ac_cv_lib_z_gzopen" >&6 +if test $ac_cv_lib_z_gzopen = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + LIBS="-lz $LIBS" + +else + { { echo "$as_me:$LINENO: error: Can't find zlib library. Install it first." >&5 +echo "$as_me: error: Can't find zlib library. Install it first." >&2;} + { (exit 1); exit 1; }; } +fi + + +# Checks for header files. +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ctype.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + + + + + + + +for ac_header in zlib.h fcntl.h limits.h stdlib.h string.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +# Checks for typedefs, structures, and compiler characteristics. +echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 +echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 +if test "${ac_cv_c_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset x; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *ccp; + char **p; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + ccp = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++ccp; + p = (char**) ccp; + ccp = (char const *const *) p; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + } +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_const=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_const=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 +echo "${ECHO_T}$ac_cv_c_const" >&6 +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\_ACEOF +#define const +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for mode_t" >&5 +echo $ECHO_N "checking for mode_t... $ECHO_C" >&6 +if test "${ac_cv_type_mode_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((mode_t *) 0) + return 0; +if (sizeof (mode_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_mode_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_mode_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_mode_t" >&5 +echo "${ECHO_T}$ac_cv_type_mode_t" >&6 +if test $ac_cv_type_mode_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define mode_t int +_ACEOF + +fi + + +# Checks for library functions. + + + +for ac_func in atexit strdup strerror +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# Checks for cygwin +echo "$as_me:$LINENO: checking for cygwin OSTYPE" >&5 +echo $ECHO_N "checking for cygwin OSTYPE... $ECHO_C" >&6 +if test x$OSTYPE == xcygwin; then + EXESUF=.exe + + echo "$as_me:$LINENO: result: it is cygwin, using .exe" >&5 +echo "${ECHO_T}it is cygwin, using .exe" >&6 +else + echo "$as_me:$LINENO: result: not cygwin" >&5 +echo "${ECHO_T}not cygwin" >&6 +fi + + ac_config_files="$ac_config_files Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then we branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +cat >confdef2opt.sed <<\_ACEOF +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g +t quote +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g +t quote +d +: quote +s,[ `~#$^&*(){}\\|;'"<>?],\\&,g +s,\[,\\&,g +s,\],\\&,g +s,\$,$$,g +p +_ACEOF +# We use echo to avoid assuming a particular line-breaking character. +# The extra dot is to prevent the shell from consuming trailing +# line-breaks from the sub-command output. A line-break within +# single-quotes doesn't work because, if this script is created in a +# platform that uses two characters for line-breaks (e.g., DOS), tr +# would break. +ac_LF_and_DOT=`echo; echo .` +DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` +rm -f confdef2opt.sed + + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to <bug-autoconf@gnu.org>." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@CPP@,$CPP,;t t +s,@EGREP@,$EGREP,;t t +s,@EXESUF@,$EXESUF,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..e887013 --- /dev/null +++ b/configure.ac @@ -0,0 +1,42 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_INIT([aewan]) +AC_CONFIG_SRCDIR([aewan.c]) +#AC_CONFIG_HEADER([config.h]) + +# Checks for programs. +AC_PROG_CC + +# Check for the standard stdbool header file +AC_HEADER_STDBOOL + +# Checks for libraries. +AC_CHECK_LIB([ncurses], [initscr], [], + AC_MSG_ERROR([Can't find ncurses library. Install it first.])) +AC_CHECK_LIB([z], [gzopen], [], + AC_MSG_ERROR([Can't find zlib library. Install it first.])) + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([zlib.h fcntl.h limits.h stdlib.h string.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_MODE_T + +# Checks for library functions. +AC_CHECK_FUNCS([atexit strdup strerror]) + +# Checks for cygwin +AC_MSG_CHECKING([for cygwin OSTYPE]) +if test x$OSTYPE == xcygwin; then + AC_SUBST(EXESUF, [.exe]) + AC_MSG_RESULT([it is cygwin, using .exe]) +else + AC_MSG_RESULT([not cygwin]) +fi + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT + diff --git a/debug_aewl.c b/debug_aewl.c new file mode 100644 index 0000000..a47b09a --- /dev/null +++ b/debug_aewl.c @@ -0,0 +1,121 @@ +#include "debug_aewl.h" + +#include "aewl/aewl.h" +#include "aewl/form.h" +#include "aewl/button.h" +#include "aewl/listbox.h" +#include "aewl/field.h" +#include "aewl/label.h" + +#include "keys.h" + +#include <ncurses.h> +#include <stdbool.h> + +static int curses_attr_for_pair(int fg, int bg, bool bold) { + short int cp = bg * 8 + 7 - fg; + if (!cp) return bold ? A_BOLD : A_NORMAL; + return COLOR_PAIR(cp) | (bold ? A_BOLD : 0); +} + +void debug_aewl() { + char *s = filedlg_show("Test Dialog"); + clear(); + + printw("Answer: '%s'\n", s); + getch(); +} + +void debug_aewl_OLD() { + AewlWidget *b1, *b2, *b3, *lbl; + AewlListBox *lb; + AewlWidget *fld; + AewlForm *f; + int r; + + AewlAttrSettings ats = { + { + curses_attr_for_pair(7, 0, false), /* text */ + curses_attr_for_pair(7, 0, true), /* text focus */ + curses_attr_for_pair(1, 0, false), /* text shortcut */ + curses_attr_for_pair(1, 0, true) /* text shortcut focus */ + }, + + { + curses_attr_for_pair(7, 4, false), /* button */ + curses_attr_for_pair(7, 2, true), /* button focus */ + curses_attr_for_pair(1, 4, false), /* button shortcut */ + curses_attr_for_pair(1, 2, true) /* button shortcut focus */ + }, + + { + curses_attr_for_pair(7, 0, false), /* frame */ + curses_attr_for_pair(7, 0, true), /* frame focus */ + curses_attr_for_pair(1, 0, false), /* frame shortcut */ + curses_attr_for_pair(1, 0, true) /* frame shortcut focus */ + }, + + { + curses_attr_for_pair(7, 0, false), /* field */ + curses_attr_for_pair(7, 0, true), /* field focus */ + curses_attr_for_pair(7, 4, false), /* field selection */ + curses_attr_for_pair(7, 1, true) /* field selection focus */ + }, + + curses_attr_for_pair(0, 0, true) /* field pad char */ + }; + + aewl_init(&ats); + + clear(); + refresh(); + f = aewl_form_create(stdscr); + + b1 = aewl_button_create(10, 10, 20, KEY_ALT_A, 1, "Button &Ay One"); + b2 = aewl_button_create(10, 12, 20, KEY_ALT_B, 2, "Button &Bee Two"); + b3 = aewl_button_create(10, 14, 20, KEY_ALT_C, 3, "Button &Cee Three"); + lb = (AewlListBox*) + aewl_listbox_create(40, 10, 30, 10, KEY_ALT_L, "My &List", 123); + fld = aewl_field_create(10, 20, 20, KEY_ALT_T, 4, "Test field"); + lbl = aewl_label_create(4, 20, -1, "&Text:"); + + aewl_listbox_add(lb, "Ut queant laxis"); + aewl_listbox_add(lb, "Resonare fibris"); + aewl_listbox_add(lb, "Mira gestorum"); + aewl_listbox_add(lb, "Famuli tuorum"); + aewl_listbox_add(lb, "Solve polluti"); + aewl_listbox_add(lb, "Labii reatum"); + aewl_listbox_add(lb, "Sancte Ioannes"); + aewl_listbox_add(lb, "Lacrymosa dies illa"); + aewl_listbox_add(lb, "Qua resurget ex favilla"); + aewl_listbox_add(lb, "Iudicandus homo reus"); + aewl_listbox_add(lb, "Huic ergo parce Deus"); + aewl_listbox_add(lb, "Pie iesu domine"); + aewl_listbox_add(lb, "Dona eis requiem"); + aewl_listbox_add(lb, "Stabat mater dolorosa"); + aewl_listbox_add(lb, "Iuxta crucem lacrymosam"); + aewl_listbox_add(lb, "Dum pendebat filius"); + aewl_listbox_add(lb, "Quis est homo qui non fleret"); + aewl_listbox_add(lb, "Matrem Christi se videret"); + aewl_listbox_add(lb, "In tanto suplicio?"); + + aewl_form_add_widget(f, b1); + aewl_form_add_widget(f, b2); + aewl_form_add_widget(f, b3); + aewl_form_add_widget(f, (AewlWidget*) lb); + aewl_form_add_widget(f, fld); + aewl_form_add_widget(f, lbl); + + aewl_form_paint(f, true); + while (0 == (r = aewl_form_dispatch_key(f, getch()))); + aewl_form_destroy(f); + + clear(); + refresh(); + printw("Selected value %d", r); + getch(); + + clear(); + refresh(); +} + diff --git a/debug_aewl.h b/debug_aewl.h new file mode 100644 index 0000000..cb396fb --- /dev/null +++ b/debug_aewl.h @@ -0,0 +1,7 @@ +#ifndef btco_aewn_debug_aewl_h +#define btco_aewn_debug_aewl_h + +void debug_aewl(); + +#endif + diff --git a/document.c b/document.c new file mode 100644 index 0000000..cfd34c0 --- /dev/null +++ b/document.c @@ -0,0 +1,227 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "bores/bores.h" +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "document.h" + +#define DEFAULT_NOM_WIDTH 80 +#define DEFAULT_NOM_HEIGHT 25 + +Document *document_create(void) { + Document *doc = (Document*) zalloc(sizeof(Document)); + return doc; +} + +void document_destroy(Document *doc) { + int i; + if (!doc) return; + if (doc->layers) { + for (i = 0; i < doc->layer_count; i++) + free(doc->layers[i]); + free(doc->layers); + } + + dstrset(&doc->metainfo, 0); + free(doc); +} + +void document_add_layer(Document *doc, Layer *layer) { + (doc->layers = srealloc(doc->layers, (++doc->layer_count) * sizeof(Layer*))) + [doc->layer_count-1] = layer; +} + +void document_insert_layer(Document *doc, int i, Layer *layer) { + int j; + if (i < 0) i = 0; + if (i > doc->layer_count) i = doc->layer_count; + + /* first reallocate the array (and increment doc->layer_count) */ + doc->layers = srealloc(doc->layers, (++doc->layer_count) * sizeof(Layer*)); + + /* now shift layers to make room */ + for (j = doc->layer_count - 1; j > i; j--) + doc->layers[j] = doc->layers[j-1]; + + /* position i is now free */ + doc->layers[i] = layer; +} + +void document_del_layer(Document *doc, int i) { + if (i < 0 || i >= doc->layer_count) return; + + /* FIXME: this doesn't realloc the layers array, so it does not + * reclaim memory allocated by document_add_layer. */ + layer_destroy(doc->layers[i]); + for (; i < doc->layer_count - 1; i++) + doc->layers[i] = doc->layers[i+1]; + + doc->layer_count--; +} + +void document_get_nom_dim(Document *doc, int *w, int *h) { + if (!doc || !doc->layer_count) { + if (w) *w = DEFAULT_NOM_WIDTH; + if (h) *h = DEFAULT_NOM_HEIGHT; + } + else { + if (w) *w = doc->layers[0]->width; + if (h) *h = doc->layers[0]->height; + } +} + +void document_save(Document *doc, AeFile *f) { + int i; + + aeff_write_header(f, "Aewan Document v1"); + aeff_write_int(f, "layer-count", doc->layer_count); + aeff_write_string(f, "meta-info", doc->metainfo ? doc->metainfo : ""); + + for (i = 0; i < doc->layer_count; i++) + layer_save(doc->layers[i], f); + + aeff_write_footer(f, "Aewan Document v1"); +} + +Document *document_load_from(const char *filename) { + static char buf[2]; + int i; + Document *d = NULL; + + FILE *f = fopen(filename, "r"); + if (!f) { + char *msg = dsprintf("%s: %s", filename, strerror(errno)); + aeff_set_error(msg); + zfree(&msg); + return NULL; + } + + /* get first 2 bytes from file and close it */ + for (i = 0; i < 2; i++) buf[i] = fgetc(f); + fclose(f); + + if (!strncmp(buf, "DO", 2)) { + /* old format (binary). */ + d = document_load_OLD(f = fopen(filename, "r")); + if (!d) aeff_set_error("Malformed (old) binary format"); + fclose(f); + return d; + } + else if (!strncmp(buf, "\037\213", 2)) { + /* gzip format: assume new format (aeff) */ + AeFile *aeff = aeff_open(filename, 'r'); + if (!aeff) return NULL; + return document_load(aeff); + } + else { + aeff_set_error("Unrecognized file format."); + return NULL; + } +} + +Document *document_load(AeFile *f) { + int lc; + Document *d = document_create(); + Layer *l = NULL; + + if (!aeff_read_header(f, "Aewan Document v1")) goto exception; + if (!aeff_read_int(f, "layer-count", &lc)) goto exception; + if (!aeff_read_string(f, "meta-info", &d->metainfo)) goto exception; + + + /* load each layer (there are <lc> layers to load) */ + while (lc--) { + if ( ! (l = layer_load(f)) ) goto exception; + document_add_layer(d, l); + l = 0; /* forget about the layer, it now belongs to the document */ + } + + if (!aeff_read_footer(f, "Aewan Document v1")) goto exception; + return d; /* all went well */ + +/* I think exception handling is a pretty legitimate use of goto, + * so don't complain */ +exception: + if (d) document_destroy(d); + if (l) layer_destroy(l); + return NULL; +} + +Document *document_load_OLD(FILE *f) { + /* THIS FUNCTION LOADS THE OLD FORMAT. FOR BACKWARD COMPATIBILITY ONLY */ + int i; int lc; + Document *d; Layer *l; + if ('D' != fgetc(f) || 'O' != fgetc(f)) return NULL; + + fread(&lc, sizeof(int), 1, f); + + d = document_create(); + if ( !(d->metainfo = floadstr(f)) ) { + document_destroy(d); + return NULL; + } + + for (i = 0; i < lc; i++) { + if ( !(l = layer_load_OLD(f)) ) { + document_destroy(d); + return NULL; + } + + document_add_layer(d, l); + } + + return d; +} + +Cell document_calc_effective_cell(Document *doc, int x, int y) { + int i; + Layer *lyr; + Cell result; + result.ch = 0x20, result.attr = 0x70; + + for (i = doc->layer_count - 1; i >= 0; i--) { + lyr = doc->layers[i]; + if (x < 0 || x >= lyr->width || y < 0 || y >= lyr->width) continue; + if (!lyr->visible) continue; + if (lyr->transp && is_cell_transp(&lyr->cells[x][y])) continue; + + result.ch = lyr->cells[x][y].ch; + result.attr = lyr->cells[x][y].attr; + } + + return result; +} + diff --git a/document.h b/document.h new file mode 100644 index 0000000..5d4de51 --- /dev/null +++ b/document.h @@ -0,0 +1,108 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + + +#ifndef _btco_aewan_document_h +#define _btco_aewan_document_h +#include "layer.h" +#include "aeff.h" + +struct _Document { + int layer_count; /* how many layers in document */ + Layer **layers; /* vector of pointers to layers */ + + char *metainfo; /* additional textual information. The program will + * invoke an external editor when the user wants + * to edit the contents of this string. */ +}; +typedef struct _Document Document; + +/* Creates a new, empty document. */ +Document *document_create(void); + +/* Destroys a previously created document */ +void document_destroy(Document *doc); + +/* Adds a new layer to the given document. After the call, the layer + * will belong to the document and no other references to it should + * be kept. */ +void document_add_layer(Document *doc, Layer *layer); + +/* Add a new layer to the given document, inserting it just before + * the layer whose index is i. Prerequsite: 0 <= i <= doc->layer_count. + * Notice that document_add_layer(doc, l) is equivalent to + * document_insert_layer(doc, doc->layer_count, l) */ +void document_insert_layer(Document *doc, int i, Layer *layer); + +/* Deletes layer i from the document. */ +void document_del_layer(Document *doc, int i); + +/* Convenience function that obtains the "nominal width and height" + * of the document, which are the dimensions of the first layer, + * if the document has any layers, or some sensible defaults if + * the document has none */ +void document_get_nom_dim(Document *doc, int *w, int *h); + +/* Saves document to file f */ +void document_save(Document *doc, AeFile *f); + +/* Loads a document from file f. If the loading succeeds, returns + * a dynamically allocated document. If the loading fails, returns NULL. + * This function reads the OLD, binary file format. */ +Document *document_load_OLD(FILE *f); + +/* Loads a document from file f. If the loading succeeds, returns + * a dynamically allocated document. If the loading fails, returns NULL. + * This function reads the NEW, zipped-text format. + * + * On error, this function returns NULL and aeff_get_error can be + * called in order to obtain an error description. + */ +Document *document_load(AeFile *f); + +/* A wrapper that opens the file, detects the format and calls + * either document_load or document_load_OLD. + * + * On error, this function returns NULL and aeff_get_error can + * be called in order to obtain an error description. + */ +Document *document_load_from(const char *filename); + +/* Gets the character and attribute at position x, y when viewing + * the image as a composite. That is, go through all layers and see + * which ones are transparent, visible, etc, and thus calculate the + * resulting char/attr of the given cell. */ +Cell document_calc_effective_cell(Document *doc, int x, int y); + +#endif + diff --git a/editmeta.c b/editmeta.c new file mode 100644 index 0000000..e5f7b6d --- /dev/null +++ b/editmeta.c @@ -0,0 +1,123 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <ncurses.h> +#include <unistd.h> + +#include "document.h" +#include "psd.h" +#include "ui.h" + +void edit_metainfo(void) { + char *editor; + FILE *f; + int fd, ret, size, i; + static char tmpname[64]; + static char buf[128]; + mode_t oldumask; + + editor = getenv("VISUAL"); + if (!editor) editor = getenv("EDITOR"); + if (!editor) editor = "vi"; + + /* create a temporary file */ + strcpy(tmpname, "/tmp/aewan-XXXXXX"); + oldumask = umask(077); /* so that mkstemp creates a file with perms=700 */ + fd = mkstemp(tmpname); + umask(oldumask); + + /* check for error */ + if (fd < 0) { + sprintf(buf, "ERROR creating temp file: %s", strerror(errno)); + ui_message(buf, UIMSG_ERROR); + return; + } + + /* do an fdopen so we can manipulate it via FILE* structure */ + f = fdopen(fd, "w"); + + /* write current contents of metainfo string to the file */ + if (_doc->metainfo) fputs(_doc->metainfo, f); + + /* close file */ + fclose(f); + close(fd); /* is this necessary? */ + + /* fire up editor */ + sprintf(buf, "%s %s", editor, tmpname); + clear(); + refresh(); + endwin(); /* temporarily stop curses */ + if ( (ret = system(buf)) ) { + /* error code returned */ + sprintf(buf, "ERROR: editor (%s) returned error code %d.", editor, ret); + ui_message(buf, UIMSG_ERROR); + return; + } + + /* restore curses */ + touchwin(stdscr); /* force full redraw */ + refresh(); + + /* ok, now read back file contents into metainfo string */ + f = fopen(tmpname, "r"); + if (!f) { + ui_message("ERROR: Failed to read back temp file.", UIMSG_ERROR); + return; + } + + /* calculate file size */ + fseek(f, 0, SEEK_END); + size = ftell(f) + 2; /* +1 b/c size is one more than last position. + We add another byte for the null terminator */ + fseek(f, 0, SEEK_SET); + + /* allocate appropriately */ + dstrset(&_doc->metainfo, NULL); + _doc->metainfo = zalloc(size); + + /* read file data */ + i = fread(_doc->metainfo, 1, size, f); + + /* put the null terminator where it should be */ + _doc->metainfo[i] = 0; + + /* delete temp file */ + unlink(tmpname); +} + diff --git a/editmeta.h b/editmeta.h new file mode 100644 index 0000000..936a827 --- /dev/null +++ b/editmeta.h @@ -0,0 +1,41 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewan_editmeta_h +#define _btco_aewan_editmeta_h + +/* Allows user to edit the document's meta-info in an editor */ +void edit_metainfo(void); + +#endif + diff --git a/export.c b/export.c new file mode 100644 index 0000000..ba79d3d --- /dev/null +++ b/export.c @@ -0,0 +1,86 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include <string.h> +#include "export.h" + +void decode_cell(const Cell* cell, DecodedCell *dc) { + dc->fg = (cell->attr & 0xf0) >> 4; + dc->bg = cell->attr & 0x0f; + dc->ch = cell->ch; + + dc->fg3 = (cell->attr & 0x70) >> 4; + dc->bg3 = cell->attr & 0x07; + dc->bold = (cell->attr & 0x80) ? 1 : 0; + dc->blink = (cell->attr & 0x08) ? 1 : 0; +} + +bool export_vlayer_to_ansi(VirtualLayer *vl, bool use_ansi, bool use_newlines, + bool quotemeta, FILE *f) { + int x, y; + DecodedCell dec; + Cell c; + int cur_fg = -1; + int cur_bg = -1; + const char *must_quote = "\\`$"; + + for (y = 0; y < vl->height; y++) { + for (x = 0; x < vl->width; x++) { + vlayer_get_cell(vl, &c, x, y); + decode_cell(&c, &dec); + + /* set up color if necessary */ + if (use_ansi && (dec.fg != cur_fg || dec.bg != cur_bg)) { + fputs("\e[", f); + fputs(dec.bold ? "1;" : "0;", f); + if (dec.blink) fputs("5;", f); + fprintf(f, "%d;%dm", 30 + dec.fg3, 40 + dec.bg3); + + cur_fg = dec.fg; + cur_bg = dec.bg; + } + + /* output the character */ + if (dec.ch >= 0 && dec.ch <= 32) dec.ch = ' '; + + if (quotemeta && strchr(must_quote, dec.ch)) fputc('\\', f); + fputc(dec.ch, f); + } + + if (use_newlines) fputc('\n', f); + } + + if (use_ansi) fputs("\e[0m", f); + return true; +} + diff --git a/export.h b/export.h new file mode 100644 index 0000000..8774514 --- /dev/null +++ b/export.h @@ -0,0 +1,74 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + + +#ifndef _btco_aewan_export_h +#define _btco_aewan_export_h + +#include <stdio.h> +#include <stdbool.h> +#include "layer.h" +#include "vlayer.h" + +/* Exports the given virtual layer to text format, writing the output to the + * given file. The parameter use_ansi_escape determines whether the function + * should include ANSI escape sequences to reproduce the colors. + * The use_newlines parameter indicates whether a newline character should + * be included after each row of output. The output will be written + * to the file f. The quotemeta parameter indicates that special UNIX + * characters such as backslashes and backticks should be escaped. */ +bool export_vlayer_to_ansi(VirtualLayer *vl, bool use_ansi_escape, + bool use_newlines, + bool quotemeta, FILE *f); + +/* Represents a decoded cell (see decode_cell()) below */ +typedef struct { /* represents a decoded document cell. Returned + * by decode_cell */ + + int fg, bg; /* the foreground and background color codes (4 bit, 0-15) + * for the cell */ + int ch; /* the character in the cell */ + + /* now some of the same information, but in a more broken-down form: */ + bool bold, blink; /* bold and blink attributes */ + int fg3, bg3; /* 3-bit color codes (0-7) for the foreground and + * background of the cell */ +} DecodedCell; + +/* Decodes a cell into a 'decoded cell' structure that gives organized + * information about a cell, such as foreground and background colors + * and such. Returns the decoded cell information in *r_dc. */ +void decode_cell(const Cell *c, DecodedCell *r_dc); + +#endif + diff --git a/filedlg.c b/filedlg.c new file mode 100644 index 0000000..d0b1ce3 --- /dev/null +++ b/filedlg.c @@ -0,0 +1,319 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +/* +DIALOG LAYOUT (FULL SCREEN): + + DIALOG TITLE + File Name: [filename_fld] [ cancel_btn ] [ ok_btn ] + Directory: [directory_lbl] + +--Directories---------+ +--Files-----------------+ + | dirs_box | | files_box | + +----------------------+ +------------------------+ +*/ + +#include <ncurses.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdlib.h> + +#include "bores/bores.h" +#include "aewl/aewl.h" +#include "aewl/allwidgets.h" +#include "keys.h" + +/* widget positions (w, h and screen dimensions) */ +/* btw, STLBL = static label, that is, labels that + * are just there to say things that never change + * (didn't that come out somewhat poetic?) */ +#define FILENAME_STLBL_X 1 +#define FILENAME_STLBL_Y 2 +#define DIRECTORY_STLBL_X 1 +#define DIRECTORY_STLBL_Y 3 +#define CANCEL_BTN_W 11 +#define OK_BTN_W 11 +#define CANCEL_BTN_X (w - CANCEL_BTN_W - OK_BTN_W - 2) +#define CANCEL_BTN_Y 2 +#define OK_BTN_X (w - OK_BTN_W) +#define OK_BTN_Y 2 +#define FILENAME_FLD_X 13 +#define FILENAME_FLD_Y 2 +#define FILENAME_FLD_W (CANCEL_BTN_X - FILENAME_FLD_X - 3) +#define DIRECTORY_LBL_X 13 +#define DIRECTORY_LBL_Y 3 +#define DIRECTORY_LBL_W (w - DIRECTORY_LBL_X) +#define DIRS_BOX_X 1 +#define DIRS_BOX_Y 5 +#define DIRS_BOX_W (w / 3) +#define DIRS_BOX_H (h - 6) +#define FILES_BOX_X (DIRS_BOX_X + DIRS_BOX_W + 2) +#define FILES_BOX_Y 5 +#define FILES_BOX_W (w - FILES_BOX_X - 1) +#define FILES_BOX_H (h - 6) + +/* result codes for internal event handling */ +#define FILENAME_FLD_RES 1001 +#define FILES_BOX_RES 1002 +#define DIRS_BOX_RES 1003 +#define CANCEL_BTN_RES 1004 +#define OK_BTN_RES 1005 + +static AewlWidget *filename_fld, *cancel_btn, *ok_btn, + *directory_lbl, *dirs_box, *files_box, + *filename_stlbl, *directory_stlbl; +static AewlForm *form; + +static char *curdir = NULL; /* the currently selected directory (full path). + * This will persist across invocations of the dialog. */ + +/* fills the dirs listbox with the subdirectories of the current directory, + * updates the file listbox with the files in the current directory and + * all such things */ +static void _update_widgets(void); + +static bool _is_dir_valid(const char *dir) { + DIR *d = opendir(dir); + if (d) { + closedir(d); + return true; + } + + return false; +} + +static char *my_getcwd() { /* returns newly allocated buffer. NULL on error */ + int cap; + char *s = malloc(cap = 32); + + while (!getcwd(s, cap)) { + if (errno != ERANGE) return NULL; + s = malloc(cap += cap); + } + + return s; +} + +static char *_get_canon_dir_path(const char *base, const char *relative) { + /* Warning: this is a ridiculous way to go about this */ + char *oldpwd = my_getcwd(); + char *retval; + + if (!oldpwd) return NULL; + + if (0 != chdir(base)) return NULL; + if (0 != chdir(relative)) return NULL; + + retval = my_getcwd(); + + if (0 != chdir(oldpwd)) { + fprintf(stderr, "PANIC: Can't go back to old wd '%s'\n%s\n", + oldpwd, strerror(errno)); + abort(); + } + + return retval; +} + +char *filedlg_show(const char *title) { + int w, h, r, ch, s; + char *retval = NULL; + + /* if the current directory is unset or is invalid (for example + * has been deleted since the file dialog was last invoked), + * reset it to the application's current working directory */ + if (!curdir || !_is_dir_valid(curdir)) { + curdir = my_getcwd(); + if (!curdir) curdir = strdup("/"); /* last resort -- this will + * happen if the current working + * directory of the application is + * removed, for example. */ + } + + push_screen(); + clear(); + + kurses_color(14, 0); + kurses_move(0, 0); + addstr(title); + + w = kurses_width(); + h = kurses_height(); + + form = aewl_form_create(stdscr); + filename_stlbl = aewl_label_create(FILENAME_STLBL_X, FILENAME_STLBL_Y, 0, + "File &Name:"); + directory_stlbl = aewl_label_create(DIRECTORY_STLBL_X, DIRECTORY_STLBL_Y, 0, + "Directory:"); + filename_fld = aewl_field_create(FILENAME_FLD_X, FILENAME_FLD_Y, + FILENAME_FLD_W, KEY_ALT_N, FILENAME_FLD_RES, ""); + directory_lbl = aewl_label_create(DIRECTORY_LBL_X, DIRECTORY_LBL_Y, + DIRECTORY_LBL_W, ""); + cancel_btn = aewl_button_create(CANCEL_BTN_X, CANCEL_BTN_Y, CANCEL_BTN_W, + 0, CANCEL_BTN_RES, "Cancel"); + ok_btn = aewl_button_create(OK_BTN_X, OK_BTN_Y, OK_BTN_W, + 0, OK_BTN_RES, "OK"); + files_box = aewl_listbox_create(FILES_BOX_X, FILES_BOX_Y, + FILES_BOX_W, FILES_BOX_H, + KEY_ALT_F, "&Files", FILES_BOX_RES); + dirs_box = aewl_listbox_create(DIRS_BOX_X, DIRS_BOX_Y, + DIRS_BOX_W, DIRS_BOX_H, + KEY_ALT_D, "&Directory", DIRS_BOX_RES); + + /* set widget focus peers */ + aewl_label_set_focus_peer((AewlLabel*) filename_stlbl, filename_fld); + + /* add all widgets to the form */ + aewl_form_add_widget(form, filename_stlbl); + aewl_form_add_widget(form, directory_stlbl); + aewl_form_add_widget(form, filename_fld); + aewl_form_add_widget(form, directory_lbl); + aewl_form_add_widget(form, cancel_btn); + aewl_form_add_widget(form, ok_btn); + aewl_form_add_widget(form, dirs_box); + aewl_form_add_widget(form, files_box); + + /* show the form */ + _update_widgets(); + aewl_form_paint(form, true); + while (1) { + /* if files box has focus, set the field's text to match current + * selection */ + if (aewl_form_get_focus_widget(form) == files_box) { + const char *s = aewl_listbox_get((AewlListBox*) files_box, + aewl_listbox_get_sel((AewlListBox*) files_box)); + if (s) aewl_field_set_text((AewlField*) filename_fld, s); + aewl_form_paint(form, true); + } + + /* get next key and dispatch it */ + ch = getch(); + r = aewl_form_dispatch_key(form, ch); + + /* interpret returned result code */ + if (r == CANCEL_BTN_RES || ch == 27 || ch == 3 || ch == 7) { + /* if user pressed the cancel button, pressed ESC or Ctrl+C or Ctrl+G, + * cancel dialog */ + retval = NULL; + break; + } + else if (r == FILENAME_FLD_RES || r == OK_BTN_RES || r == FILES_BOX_RES) { + /* if user confirmed selection, quit dialog and return the + * currently selected file, that is, the current directory + * plus the field's contents (remember that it will already have + * been updated to match the filebox's selection, if appropriate) */ + const char *fieldtext = aewl_field_get_text((AewlField*)filename_fld); + + /* TODO: work needs to be done here to enable the user to, + * for example, type a full path to save the file, or + * type the name of a directory to jump to it. At the very + * least, this should disallow slashes in the file name! */ + + retval = malloc(strlen(fieldtext) + strlen(curdir) + 6); + sprintf(retval, "%s/%s", curdir, fieldtext); + break; + } + else if (r == DIRS_BOX_RES && + (s = aewl_listbox_get_sel((AewlListBox*) dirs_box)) >= 0) { + /* user pressed enter in the directories box, so change into that + * directory */ + const char *d = aewl_listbox_get((AewlListBox*) dirs_box, s); + + /* get the canonicalized name of the new directory */ + char *canon_path = _get_canon_dir_path(curdir, d); + + if (!canon_path) return NULL; /* FIXME: error message? */ + + if (_is_dir_valid(canon_path)) { + if (curdir) free(curdir); + curdir = canon_path; + + /* clear file name text field */ + aewl_field_set_text((AewlField*) filename_fld, ""); + + _update_widgets(); + aewl_form_paint(form, true); + } + else + free(canon_path); + /* FIXME: Should't we display a message if the directory is invalid? */ + } + } + + aewl_form_destroy(form); + pop_screen(); + + return retval; /* return filename if user pressed ok */ +} + +static void _update_widgets(void) { + DIR *d; + struct dirent *dent; + struct stat st; + + d = opendir(curdir); + + if (!d) { + fprintf(stderr, "ERROR in opendir(\"%s\"): %s\n", curdir, + strerror(errno)); + abort(); + } + + aewl_listbox_clear((AewlListBox*) dirs_box); + aewl_listbox_clear((AewlListBox*) files_box); + while ( (dent = readdir(d)) ) { + char *compname = zalloc(strlen(dent->d_name) + strlen(curdir) + 2); + sprintf(compname, "%s/%s", curdir, dent->d_name); + + if (0 != stat(compname, &st)) continue; /* broken links and such */ + + free(compname); + + if (S_ISDIR(st.st_mode)) + aewl_listbox_add((AewlListBox*) dirs_box, dent->d_name); + else + aewl_listbox_add((AewlListBox*) files_box, dent->d_name); + } + aewl_listbox_sort((AewlListBox*) dirs_box); + aewl_listbox_sort((AewlListBox*) files_box); + + closedir(d); + + /* update the directory label */ + aewl_label_set_text((AewlLabel*)directory_lbl, curdir); +} + diff --git a/filedlg.h b/filedlg.h new file mode 100644 index 0000000..74d25ac --- /dev/null +++ b/filedlg.h @@ -0,0 +1,49 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewan_filedlg_h +#define _btco_aewan_filedlg_h + +/* Shows a file dialog onscreen and returns the filename + * that the user selected. Caller is responsibile for + * freeing the returned buffer. + * + * title is the title that will be shown across the + * top of the screen + * + * Returns NULL if the user cancels the dialog + */ +char *filedlg_show(const char *title); + +#endif + diff --git a/handlekey.c b/handlekey.c new file mode 100644 index 0000000..0d900a3 --- /dev/null +++ b/handlekey.c @@ -0,0 +1,624 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + + +#include <stdbool.h> +#include "bores/bores.h" +#include <limits.h> +#include <stdlib.h> +#include <ncurses.h> +#include <string.h> +#include <errno.h> +#include <pwd.h> /* For getpwuid() */ +#include <unistd.h> + +#include "handlekey.h" +#include "document.h" +#include "psd.h" +#include "ui.h" +#include "keys.h" +#include "clipboard.h" +#include "colordlg.h" +#include "layerdlg.h" +#include "helpdlg.h" +#include "chtr.h" +#include "editmeta.h" +#include "keybind.h" +#include "commands.h" +#include "menubar.h" +#include "welcomedlg.h" +#include "filedlg.h" + +#define FAST_MOVE_AMOUNT 8 /* how much the cursor moves each time the fast + * movent keys (Ctrl+Z, Ctrl+X) are pressed */ + +/* Interacts with the user in order to allow him to add a new layer to the + * document. If <interactive>, asks user for parameters; else just + * adds using the defaults. */ +static void u_add_layer(bool interactive) { + int width, height; int nom_width, nom_height; + char *name; Layer *lyr; + + document_get_nom_dim(_doc, &nom_width, &nom_height); + if (interactive) { + width = ui_ask_i("NEW LAYER: Enter width", + nom_width, 2, INT_MAX); if (ui_cancel) return; + height = ui_ask_i("NEW LAYER: Enter height", + nom_height, 2, INT_MAX); if (ui_cancel) return; + name = ui_ask_s("NEW LAYER: Name", "unnamed"); if (ui_cancel) return; + } + else { + width = nom_width; + height = nom_height; + name = strdup("unnamed"); + } + + lyr = layer_create(name, width, height); + + /* if this is the first layer we are adding, make it opaque; + * otherwise make it transparent */ + if (_doc->layer_count) lyr->transp = true; + else lyr->transp = false; + + document_insert_layer(_doc, 0, lyr); + + free(name); +} + +/* Interacts with the user in order to allow him to rename the current + * layer */ +static void u_rename_layer(void) { + Layer *l = _doc->layers[_lyr]; + char *new_name; + + new_name = ui_ask_s("Rename layer to", l->name); + if (!ui_cancel) + dstrset(&l->name, new_name); + + if (new_name) free(new_name); +} + +/* Interacts with the user in order to allow him to resize the current + * layer */ +static void u_resize_layer(void) { + Layer *l = _doc->layers[_lyr]; + Layer *new_l; + int h, w, x, y; + + w = ui_ask_i("RESIZE LAYER: Enter new width", + l->width, 2, INT_MAX); if (ui_cancel) return; + h = ui_ask_i("RESIZE LAYER: Enter new height", + l->height, 2, INT_MAX); if (ui_cancel) return; + + new_l = layer_create(l->name, w, h); + + w = l->width > new_l->width ? new_l->width : l->width; + h = l->height > new_l->height ? new_l->height : l->height; + + for (y = 0; y < h; y++) + for (x = 0; x < w; x++) { + new_l->cells[x][y].ch = l->cells[x][y].ch; + new_l->cells[x][y].attr = l->cells[x][y].attr; + } + + layer_destroy(l); + _doc->layers[_lyr] = new_l; +} + +/* Duplicates current layer, adding a duplicate to the end of the + * layer stack. */ +static void u_dup_layer(void) { + char buf[32]; + Layer *l; + sprintf(buf, "copy of %d", _lyr); + + l = _doc->layers[_lyr]; + document_add_layer(_doc, layer_dup(buf, l)); + switch_to_layer(_doc->layer_count - 1); +} + +/* Return home directory of specified user name. + * If name is omitted, returns current user's home dir. */ +char *get_home_dir(char *name) { + char msg[128]; + char *home_dir; + struct passwd *pw; + + if(name) { + pw = getpwnam(name); + if(!pw) + goto doesnt_have; + return pw->pw_dir; + } else { + home_dir = getenv("HOME"); + if(home_dir) { + return home_dir; + } else { + /* $HOME isn't set. Get directory from /etc/passwd. */ + pw = getpwuid(getuid()); + if(!pw) + goto doesnt_have; + return pw->pw_dir; + } + } + + /* Only reached with goto. */ +doesnt_have: + sprintf(msg, "ERROR: User '%s' doesn't have a home directory.", name); + ui_message(msg, UIMSG_ERROR); + return NULL; +} + +/* Returns filename with '~' replaced with the user's + * home directory. */ +static char *expand_tilde(char *filename) { + char *home_dir; + char *slash; + + if(filename[1]) { + char *username, *filename_dup; + char *ret; + + filename_dup = strdup(filename); + slash = strchr(filename_dup, '/'); + username = filename_dup + 1; + + if(!slash) { + /* Only "~user" was given, use it as a filename. */ + free(filename_dup); + return filename; + } + + *slash = '\0'; + + if(!strlen(username)) + username = NULL; + home_dir = get_home_dir(username); + if(!home_dir) + return NULL; + + slash++; /* Everything after the tilde and possible username. */ + ret = malloc(strlen(home_dir) + strlen(slash) + 1); + sprintf(ret, "%s/%s", home_dir, slash); + free(filename_dup); + return ret; + } else { + /* Only a tilde was given, use it as a filename. */ + return filename; + } +} + +/* Interacts with the user in order to allow him to load a different + * file into the editor. If the <filename> argument is not NULL, + * this routine will not ask the user for the filename but will + * rather use the supplied filename as the file to load. */ +void u_load_file(const char *supplied_filename) { + char *filename; + FILE *f = NULL; + char msg[128]; + Document *newdoc; + + if (!supplied_filename) { + filename = filedlg_show("Load File"); + if (!filename) return; + } + else filename = strdup(supplied_filename); + + if ( !(newdoc = document_load_from(filename)) ) { + sprintf(msg, "ERROR: Failed to load file. -- More --"); + ui_message(msg, UIMSG_ERROR); + ui_message(aeff_get_error(), UIMSG_ERROR); + goto cleanup; + } + + /* now that we have the new document, do the actual replacement */ + document_destroy(_doc); + _doc = newdoc; + + /* set the filename of the loaded file */ + dstrset(&_filename, filename); + +cleanup: + if (f) fclose(f); + if (filename) free(filename); +} + +/* Interacts with the user allowing him to save current file */ +static void u_save_file(bool forceAsk) { + char *filename, *expanded_filename; + FILE *tmpf; + AeFile *f = 0; + char msg[128]; + + if (forceAsk || !_filename || !strlen(_filename)) { + filename = filedlg_show("Save File As"); + if (!filename) return; + } + else filename = strdup(_filename); + + if (filename[0] == '~') { + expanded_filename = expand_tilde(filename); + if (!expanded_filename) return; + + /* Comparing pointers. */ + if (expanded_filename != filename) { + free(filename); + filename = expanded_filename; + } + } + + if ( _filename && strcmp(_filename, filename) && + (tmpf = fopen(filename, "r")) ) { + /* file exists. Ask if user wants to overwrite */ + fclose(tmpf); tmpf = 0; + if (!ui_ask_yn("FILE EXISTS. Overwrite?", 0) || ui_cancel) { + ui_message("File was NOT saved!", UIMSG_INFORM); + goto cleanup; + } + } + + if ( !(f = aeff_open(filename, 'w')) ) { + sprintf(msg, "ERROR: Can't write to file. %s.", aeff_get_error()); + ui_message(msg, UIMSG_ERROR); + goto cleanup; + } + + document_save(_doc, f); + + dstrset(&_filename, filename); + + sprintf(msg, "File saved: %s.", filename); + ui_message(msg, UIMSG_INFORM); + +cleanup: + if (f) aeff_close(f); + if (filename) free(filename); +} + +/* erases current selection */ +static void erase_sel() { + int x, y; + int x0, x1, y0, y1; + + get_norm_sel(&x0, &y0, &x1, &y1); + for (x = x0; x <= x1; x++) + for (y = y0; y <= y1; y++) + _doc->layers[_lyr]->cells[x][y] = BLANK_CELL; +} + +/* if <fg>, sets foreground color of selection to current foreground + * color. Else, sets background color of selection to current background. */ +static void tint_sel(bool fg) { + int x0, y0, x1, y1, x, y; + get_norm_sel(&x0, &y0, &x1, &y1); + + for (x = x0; x <= x1; x++) + for (y = y0; y <= y1; y++) + if (fg) + _doc->layers[_lyr]->cells[x][y].attr = + (_fg << 4) | (_doc->layers[_lyr]->cells[x][y].attr & 0x0F); + else + _doc->layers[_lyr]->cells[x][y].attr = + _bg | (_doc->layers[_lyr]->cells[x][y].attr & 0xF0); +} + +/* Remaps character ch to its lgmode equivalent. When in _lgmode == true, + * this function is executed for every character typed. */ +static int lgmode_map_ch(int ch) { + switch (ch) { + case '7': return AEWAN_CHAR_ULCORNER; + case '8': return AEWAN_CHAR_TTEE; + case '9': return AEWAN_CHAR_URCORNER; + case '4': return AEWAN_CHAR_LTEE; + case '5': return AEWAN_CHAR_PLUS; + case '6': return AEWAN_CHAR_RTEE; + case '1': return AEWAN_CHAR_LLCORNER; + case '2': return AEWAN_CHAR_BTEE; + case '3': return AEWAN_CHAR_LRCORNER; + case '-': return AEWAN_CHAR_HLINE; + case '|': return AEWAN_CHAR_VLINE; + case '0': return AEWAN_CHAR_CKBOARD; + default : return ch; + } +} + +/* handle special keys for SM_SELECT mode */ +static void sm_select_handle_key(int ch) { + int x0, y0, x1, y1; + int tmp; + get_norm_sel(&x0, &y0, &x1, &y1); + + /* we are in SM_SELECT mode */ + switch (ch) { + case 'm': + _selmode = SM_FLOAT; + copy_sel_to_clipboard(); + erase_sel(); + _x = x0; _y = y0; + break; + case 'c': + _selmode = SM_FLOAT; + copy_sel_to_clipboard(); + _x = x0; _y = y0; + break; + case 'e': + _selmode = SM_NONE; + erase_sel(); + break; + case 'f': + tint_sel(true); + break; + case 'b': + tint_sel(false); + break; + case 'o': + /* swap the anchor with the cursor position * + * that will enable the user to manipulate the "other edge" + * of the rectangle */ + tmp = _x; _x = _ax; _ax = tmp; + tmp = _y; _y = _ay; _ay = tmp; + break; + } +} + +/* handle special keys for SM_FLOAT mode */ +static void sm_float_handle_key(int ch) { + switch (ch) { + case 's': /* stamp */ + paste_clipboard(); + break; + case 'x': case 'X': /* flip x */ + layer_flip_x(_clipboard, ch == 'x'); + break; + case 'y': case 'Y': /* flip y */ + layer_flip_y(_clipboard, ch == 'y'); + break; + case 't': case 'T': /* toggle transparency */ + _clipboard->transp = !_clipboard->transp; + break; + } +} + +/* Warns the user that he will be taken into an editor to edit the + * document's meta-info, then fires up the editor */ +void u_edit_meta(void) { + int x0, y0, x, y, ch; + kurses_color(7, 0); + draw_centered_window(40, 5, "Edit Metainfo", &x0, &y0); + + x = x0, y = y0; + kurses_move(x, y++); + addstr("You will now be taken into an editor"); + kurses_move(x, y++); + addstr("in which you will be able to edit this"); + kurses_move(x, y++); + addstr("document's metainfo (arbitrary text)."); + + ch = getch(); + if (ch == 7 || ch == 27) return; + + edit_metainfo(); +} + +static void correct_coords(void) { + Layer *lyr; + int scr_width = kurses_width(); + int scr_height = kurses_height(); + + if (!_doc->layer_count) return; + lyr = _doc->layers[_lyr]; + + /* clamp coordinates to bounds */ + if (_x < 0) _x = 0; + if (_x >= lyr->width) _x = lyr->width - 1; + if (_y < 0) _y = 0; + if (_y >= lyr->height) _y = lyr->height - 1; + + /* now correct scrolling */ + if (_x >= _svx + scr_width) _svx = _x - scr_width + 1; + else if (_x < _svx) _svx = _x; + if (_y >= _svy + scr_height - 1) _svy = _y - scr_height + 2; + else if (_y < _svy) _svy = _y; +} + + +void handle_key(int ch) { + int command; + Layer *lyr; + + /* ENABLE THIS TO DEBUG AEWL... */ + #if 0 + if (ch == KEY_F(10)) { + debug_aewl(); + return; + } + #endif + + /* first check for function keys (they open the menu) */ + if (ch > KEY_F0 && ch <= KEY_F(12)) { + /* show menu and perform command mandated by it */ + command = menubar_show(ch - KEY_F0 - 1); + if (command != COMMAND_UNDEFINED) handle_command(command); + return; + } + + if ( (command = keybind_translate(ch)) ) { + /* key triggers a command: execute command */ + handle_command(command); + if (ch != 27) return; /* we also want to handle 27 (escape) ourselves + * below */ + } + + /* key does not trigger a command; handle it normally if there are + * layers in the document; ignore it if there aren't */ + if (!_doc->layer_count) return; + lyr = _doc->layers[_lyr]; + + /* interpret character keys for no-selection mode */ + if (printable_char(ch) && _selmode == SM_NONE) { + int ch_to_put = _lgmode ? lgmode_map_ch(ch) : ch; + + if (_insmode) { + int x; + for (x = lyr->width - 1; x > _x; x--) + lyr->cells[x][_y] = lyr->cells[x-1][_y]; + } + + lyr->cells[_x][_y].ch = ch_to_put; + lyr->cells[_x][_y].attr = _fg << 4 | _bg; + _x++; + } + + /* interpret character keys for SM_SELECT and SM_FLOAT modes */ + if (_selmode == SM_SELECT) sm_select_handle_key(ch); + else if (_selmode == SM_FLOAT) sm_float_handle_key(ch); + + /* interpret the backspace and delete keys, also for no-sel mode */ + if (_selmode == SM_NONE && + ((_x > 0 && (ch == 8 || ch == KEY_BACKSPACE || ch == 127)) + || ch == KEY_DC)) { + int x; + _selmode = false; + if (ch != KEY_DC) _x--; /* we know this can't make _x negative, the + * condition on the "if" above guarantees that */ + for (x = _x; x < lyr->width - 1; x++) + lyr->cells[x][_y] = lyr->cells[x+1][_y]; + + lyr->cells[lyr->width - 1][_y] = BLANK_CELL; + } + + correct_coords(); +}; + +void handle_command(int command) { + int newfg, newbg; + int ret; + Layer *lyr; + + /* handle commands that work regardless of whether document is empty */ + switch (command) { + case COMMAND_QUIT: + ret = ui_ask_yn("Really quit aewan?", 0); + if (!ui_cancel && ret) exit(0); + break; + case COMMAND_ADD_LAYER_DEFAULTS: + case COMMAND_ADD_LAYER_SPECIFY: + u_add_layer(command == COMMAND_ADD_LAYER_SPECIFY); + if (!doc_empty()) _lyr = 0; /* now we have a layer, so correct _lyr + * so that it makes sense */ + return; + case COMMAND_SET_FOREGROUND: + newfg = ui_ask_color("Foreground color"); + if (!ui_cancel) _fg = newfg; + return; + case COMMAND_SET_BACKGROUND: + newbg = ui_ask_color("Background color"); + if (!ui_cancel) _bg = newbg; + return; + case COMMAND_SHOW_COLOR_DLG: show_color_dlg(); return; + case COMMAND_TOGGLE_INSERT: _insmode = !_insmode; return; + case COMMAND_SHOW_HELP_DLG: show_help_dlg(); return; + case COMMAND_SHOW_ABOUT_DLG: show_welcome_dlg(); return; + case COMMAND_LOAD_FILE: u_load_file(NULL); return; + case COMMAND_SAVE_FILE: u_save_file(false); return; + case COMMAND_SAVE_FILE_AS: u_save_file(true); return; + case COMMAND_NEW_FILE: + if (_doc->layer_count > 0) { + ret = ui_ask_yn("Really start a new document?", 0); + if (ui_cancel || !ret) break; + } + document_destroy(_doc); + zero_state(); + return; + case COMMAND_EDIT_META: u_edit_meta(); return; + } + + /* from this point on, we handle the keys that only work if the document + * is not empty */ + if (doc_empty()) return; + lyr = _doc->layers[_lyr]; + + /* if clipboard exists and we are not in SM_FLOAT mode, delete it */ + if (_clipboard && _selmode != SM_FLOAT) clear_clipboard(); + + switch (command) { + case COMMAND_MOVE_LEFT: _x--; break; + case COMMAND_MOVE_RIGHT: _x++; break; + case COMMAND_MOVE_UP: _y--; break; + case COMMAND_MOVE_DOWN: _y++; break; + case COMMAND_CARRIAGE_RETURN: _y++; _x = 0; break; + case COMMAND_PAGE_DOWN: _y += kurses_height() - 1; break; + case COMMAND_PAGE_UP: _y -= kurses_height() - 2; break; + case COMMAND_START_OF_LINE: _x = 0; break; + case COMMAND_END_OF_LINE: _x = lyr->width - 1; break; + case COMMAND_FAST_RIGHT: _x += FAST_MOVE_AMOUNT; break; + case COMMAND_FAST_LEFT: _x -= FAST_MOVE_AMOUNT; break; + case COMMAND_PICK_COLOR: /* pick up color from current position */ + if (_selmode != SM_NONE) break; + _fg = lyr->cells[_x][_y].attr >> 4; + _bg = lyr->cells[_x][_y].attr & 0x0F; + break; + case COMMAND_TINT_CELL: /* tint cell under cursor with current color */ + if (_selmode != SM_NONE) break; + lyr->cells[_x][_y].attr = _fg << 4 | _bg; + _x++; + break; + + case COMMAND_TOGGLE_SELECTION: /* start or stop selection mode */ + if (_selmode == SM_NONE) { + _selmode = SM_SELECT; + _ax = _x; + _ay = _y; + } + else _selmode = SM_NONE; + break; + + case COMMAND_CANCEL: _selmode = SM_NONE; break; + case COMMAND_SHOW_LAYER_DLG: + show_layer_dlg(); /* bring up layer manager dialog */ + /* make sure current layer is still valid */ + if (_lyr > _doc->layer_count) _lyr = _doc->layer_count - 1; + break; + case COMMAND_NEXT_LAYER: switch_to_layer(_lyr+1); break; + case COMMAND_PREV_LAYER: switch_to_layer(_lyr-1); break; + case COMMAND_DUP_LAYER: u_dup_layer(); break; + case COMMAND_RENAME_LAYER: u_rename_layer(); break; + case COMMAND_RESIZE_LAYER: u_resize_layer(); break; + + case COMMAND_TOGGLE_LINE_MODE: _lgmode = !_lgmode; break; + case COMMAND_TOGGLE_COMPOSITE: _compmode = !_compmode; break; + } + + correct_coords(); +} + diff --git a/handlekey.h b/handlekey.h new file mode 100644 index 0000000..3379f54 --- /dev/null +++ b/handlekey.h @@ -0,0 +1,50 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewan_handlekey_h +#define _btco_aewan_handlekey_h + +/* Reacts to keypress. <ch> is the code of the key that was pressed */ +void handle_key(int ch); + +/* Reacts to the command <cmd>. Called from handle_key. */ +void handle_command(int cmd); + +/* Interacts with the user in order to allow him to load a file into + * the editor. If the supplied_filename parameter is not NULL, the + * user will not be asked for the filename; rather, the supplied + * filename will identify the file to be loaded */ +void u_load_file(const char *supplied_filename); + +#endif + diff --git a/helpdlg.c b/helpdlg.c new file mode 100644 index 0000000..3d8fbb5 --- /dev/null +++ b/helpdlg.c @@ -0,0 +1,127 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "bores/bores.h" +#include <ncurses.h> + +#include "helpdlg.h" + +static char *helptext[2] = { +/* 345678901234567890123456789012345 */ +"\001Legend\002\n" +"^ means the Ctrl key and % means\n" +"the Alt key. Thus, ^A means \n" +"Ctrl+A and %A means Alt-A.\n" +"\n" +"\001General keys\002\n" +"^X,^Z fast horizontal movement\n" +"^O open a file\n" +"^S save file\n" +"\n" +"\001Layers\002\n" +"^W go to next layer\n" +"^Q go to previous layer\n" +"^L bring up Layer Manager\n" +"^A add layer (defaults)\n" +"%A add layer (specify)\n" +"^D add copy of current layer\n" +"^R rename this layer\n" +"%R resize this layer\n" +"\n" +"\001Selection\002\n" +"%S enter select mode.\n" +, +"\001Colors\002\n" +"TAB bring up color dialog\n" +"%P pick color from cell\n" +" under the cursor\n" +"%Z apply color to cell\n" +" under the cursor\n" +"\n" +"\001Mode toggles\002\n" +"INS toggle insert mode\n" +"^G toggle line-drawing mode\n" +" (0-9,|,- will draw lines)\n" +"^P toggle composite view\n" +"\n" +"\001Others\002\n" +"^E edit document metainfo\n" +"^C quit program\n" +"F1-Fn show menu\n" +"\n*************************************\n" /* will become ACS_HLINE */ +"Copyright (c) 2003 by\n" +"Bruno T. C. de Oliveira\n" +"All rights reserved." +}; + +void show_help_dlg(void) { + int x0, y0; int x, y; int i; + const char *p; + + clear(); + refresh(); + kurses_color(4, 0); + addstr("Keys Quick Reference\n\n"); + kurses_color(7, 0); + + x0 = 0; + y0 = 2; + + x = x0; + y = y0; + for (i = 0; i < 2; i++) { + x = x0 + i * 40; + y = y0; + p = helptext[i]; + + while (*p) { + kurses_move(x, y); + switch (*p) { + case 1: kurses_color(4, 0); break; + case 2: kurses_color(7, 0); break; + case '\n': x = x0 + i * 40; y++; break; + case '*': addch(ACS_HLINE); x++; break; + default: addch(*p); x++; + } + + p++; + } + } + + /* draw vertical line separating the two columns */ + draw_vline(x0 + 37, y0, 24 - y0, ACS_VLINE, ACS_VLINE, ACS_VLINE); + + refresh(); + getch(); +} + diff --git a/helpdlg.h b/helpdlg.h new file mode 100644 index 0000000..ef7bc59 --- /dev/null +++ b/helpdlg.h @@ -0,0 +1,42 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + + +#ifndef _btco_aewan_helpdlg_h +#define _btco_aewan_helprdlg_h + +/* invokes the "help" dialog */ +void show_help_dlg(void); + +#endif + diff --git a/init_aewl.c b/init_aewl.c new file mode 100644 index 0000000..76db64d --- /dev/null +++ b/init_aewl.c @@ -0,0 +1,79 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "aewl/aewl.h" +#include <ncurses.h> +#include <stdbool.h> + +static int curses_attr_for_pair(int fg, int bg, bool bold) { + short int cp = bg * 8 + 7 - fg; + if (!cp) return bold ? A_BOLD : A_NORMAL; + return COLOR_PAIR(cp) | (bold ? A_BOLD : 0); +} + +void init_aewl() { + AewlAttrSettings ats = { + { + curses_attr_for_pair(7, 0, false), /* text */ + curses_attr_for_pair(7, 0, true), /* text focus */ + curses_attr_for_pair(1, 0, false), /* text shortcut */ + curses_attr_for_pair(1, 0, true) /* text shortcut focus */ + }, + + { + curses_attr_for_pair(7, 4, false), /* button */ + curses_attr_for_pair(7, 2, true), /* button focus */ + curses_attr_for_pair(1, 4, false), /* button shortcut */ + curses_attr_for_pair(1, 2, true) /* button shortcut focus */ + }, + + { + curses_attr_for_pair(7, 0, false), /* frame */ + curses_attr_for_pair(7, 0, true), /* frame focus */ + curses_attr_for_pair(1, 0, false), /* frame shortcut */ + curses_attr_for_pair(1, 0, true) /* frame shortcut focus */ + }, + + { + curses_attr_for_pair(7, 0, false), /* field */ + curses_attr_for_pair(7, 0, true), /* field focus */ + curses_attr_for_pair(7, 4, false), /* field selection */ + curses_attr_for_pair(7, 1, true) /* field selection focus */ + }, + + curses_attr_for_pair(0, 0, true) /* field pad char */ + }; + + aewl_init(&ats); +} + diff --git a/init_aewl.h b/init_aewl.h new file mode 100644 index 0000000..d23f1e5 --- /dev/null +++ b/init_aewl.h @@ -0,0 +1,42 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef btco_aewan_init_aewl_h +#define btco_aewan_init_aewl_h + +/* initializes the aewl widget library by passing to it + * our application-specific settings */ +void init_aewl(); + +#endif + diff --git a/keybind.c b/keybind.c new file mode 100644 index 0000000..e7b799e --- /dev/null +++ b/keybind.c @@ -0,0 +1,97 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include <stdlib.h> +#include <ncurses.h> +#include "bores/bores.h" + +#include "keybind.h" +#include "keys.h" +#include "commands.h" + +/* This array represents the current key map: cmdforkey[key] is + * the command the key is bound to (0 if the key is not bound) */ +#define KEYCODE_MAX 512 +static int *cmdforkey; + +void keybind_init(void) { + /* allocate it (remember that zalloc() already zeroes it out) */ + cmdforkey = zalloc(sizeof(int) * KEYCODE_MAX); + + /* assign defaults */ + cmdforkey[KEY_CTRL_C] = COMMAND_QUIT; + cmdforkey[KEY_CTRL_A] = COMMAND_ADD_LAYER_DEFAULTS; + cmdforkey[KEY_ALT_A] = COMMAND_ADD_LAYER_SPECIFY; + cmdforkey[KEY_ALT_F] = COMMAND_SET_FOREGROUND; + cmdforkey[KEY_ALT_B] = COMMAND_SET_BACKGROUND; + cmdforkey[KEY_CTRL_I] = COMMAND_SHOW_COLOR_DLG; + cmdforkey[KEY_CTRL_O] = COMMAND_LOAD_FILE; + cmdforkey[KEY_CTRL_S] = COMMAND_SAVE_FILE; + cmdforkey[KEY_CTRL_E] = COMMAND_EDIT_META; + cmdforkey[KEY_LEFT] = COMMAND_MOVE_LEFT; + cmdforkey[KEY_UP] = COMMAND_MOVE_UP; + cmdforkey[KEY_DOWN] = COMMAND_MOVE_DOWN; + cmdforkey[KEY_RIGHT] = COMMAND_MOVE_RIGHT; + cmdforkey[10] = COMMAND_CARRIAGE_RETURN; + cmdforkey[KEY_NPAGE] = COMMAND_PAGE_DOWN; + cmdforkey[KEY_PPAGE] = COMMAND_PAGE_UP; + cmdforkey[KEY_HOME] = COMMAND_START_OF_LINE; + cmdforkey[KEY_END] = COMMAND_END_OF_LINE; + cmdforkey[KEY_CTRL_Z] = COMMAND_FAST_LEFT; + cmdforkey[KEY_CTRL_X] = COMMAND_FAST_RIGHT; + cmdforkey[KEY_ALT_P] = COMMAND_PICK_COLOR; + cmdforkey[KEY_ALT_Z] = COMMAND_TINT_CELL; + cmdforkey[KEY_ALT_S] = COMMAND_TOGGLE_SELECTION; + cmdforkey[27] = COMMAND_CANCEL; + cmdforkey[KEY_CTRL_L] = COMMAND_SHOW_LAYER_DLG; + cmdforkey[KEY_CTRL_W] = COMMAND_NEXT_LAYER; + cmdforkey[KEY_CTRL_Q] = COMMAND_PREV_LAYER; + cmdforkey[KEY_CTRL_D] = COMMAND_DUP_LAYER; + cmdforkey[KEY_CTRL_R] = COMMAND_RENAME_LAYER; + cmdforkey[KEY_CTRL_G] = COMMAND_TOGGLE_LINE_MODE; + cmdforkey[KEY_CTRL_P] = COMMAND_TOGGLE_COMPOSITE; + cmdforkey[KEY_IC] = COMMAND_TOGGLE_INSERT; + cmdforkey[KEY_ALT_R] = COMMAND_RESIZE_LAYER; +} + +int keybind_translate(int key) { + /* do special 'untranslation' of keys for the cases when curses + * is a little _too_ helpful and gives us key codes that are much + * more abstract than we need. */ + if (key == KEY_SUSPEND) key = KEY_CTRL_Z; + + /* now translate */ + return cmdforkey[key]; +} + + diff --git a/keybind.h b/keybind.h new file mode 100644 index 0000000..a8413aa --- /dev/null +++ b/keybind.h @@ -0,0 +1,50 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef btco_aewan_keybind_h +#define btco_aewan_keybind_h + +/* Initializes the keybindings to "factory default". This must be called + * on startup, since the keymap will contain trash unless it is explicitly + * initialized. */ +void keybind_init(void); + +/* TODO: insert functions for loading user's custom keybinding from + * his .aewanrc file or something */ + +/* Returns which command the given key corresponds to. Returns + * COMMAND_UNDEFINED if it does not correspond to any command. */ +int keybind_translate(int key); + +#endif + @@ -0,0 +1,64 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include <ncurses.h> + +#include "keys.h" + +void keys_init() { + int i; + char seq[] = "\ex"; + for (i = KEY_ALT_A; i <= KEY_ALT_Z; i++) { + seq[1] = i - KEY_ALT_A + 'a'; + define_key(seq, i); + } + + /* xterm, support */ + define_key("\e[1;2A", KEY_UP); /* shift + up */ + define_key("\e[1;2B", KEY_DOWN); /* shift + down */ + define_key("\e[1;2C", KEY_RIGHT); /* shift + right */ + define_key("\e[1;2D", KEY_LEFT); /* shift + left */ + + /* rxvt support */ + define_key("\e[[a", KEY_UP); /* shift + up */ + define_key("\e[[b", KEY_DOWN); /* shift + down */ + define_key("\e[[c", KEY_RIGHT); /* shift + right */ + define_key("\e[[d", KEY_LEFT); /* shift + left */ + define_key("\e[7~", KEY_HOME); /* home key */ + define_key("\e[8~", KEY_END); /* end key */ + define_key("\e[11~", KEY_F(1)); + define_key("\e[12~", KEY_F(2)); + define_key("\e[13~", KEY_F(3)); + define_key("\e[14~", KEY_F(4)); +} + @@ -0,0 +1,99 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + + +#ifndef _btco_aewan_keys_h +#define _btco_aewan_keys_h + +/* If you are going to change this, please keep in mind that KEY_ALT_A thru + * KEY_ALT_Z must have contiguous values. */ +#define KEY_ALT_A 400 +#define KEY_ALT_B 401 +#define KEY_ALT_C 402 +#define KEY_ALT_D 403 +#define KEY_ALT_E 404 +#define KEY_ALT_F 405 +#define KEY_ALT_G 406 +#define KEY_ALT_H 407 +#define KEY_ALT_I 408 +#define KEY_ALT_J 409 +#define KEY_ALT_K 410 +#define KEY_ALT_L 411 +#define KEY_ALT_M 412 +#define KEY_ALT_N 413 +#define KEY_ALT_O 414 +#define KEY_ALT_P 415 +#define KEY_ALT_Q 416 +#define KEY_ALT_R 417 +#define KEY_ALT_S 418 +#define KEY_ALT_T 419 +#define KEY_ALT_U 420 +#define KEY_ALT_V 421 +#define KEY_ALT_W 422 +#define KEY_ALT_X 423 +#define KEY_ALT_Y 424 +#define KEY_ALT_Z 425 + +#define KEY_CTRL_A 1 +#define KEY_CTRL_B 2 +#define KEY_CTRL_C 3 +#define KEY_CTRL_D 4 +#define KEY_CTRL_E 5 +#define KEY_CTRL_F 6 +#define KEY_CTRL_G 7 +#define KEY_CTRL_H 8 +#define KEY_CTRL_I 9 +#define KEY_CTRL_J 10 +#define KEY_CTRL_K 11 +#define KEY_CTRL_L 12 +#define KEY_CTRL_M 13 +#define KEY_CTRL_N 14 +#define KEY_CTRL_O 15 +#define KEY_CTRL_P 16 +#define KEY_CTRL_Q 17 +#define KEY_CTRL_R 18 +#define KEY_CTRL_S 19 +#define KEY_CTRL_T 20 +#define KEY_CTRL_U 21 +#define KEY_CTRL_V 22 +#define KEY_CTRL_W 23 +#define KEY_CTRL_X 24 +#define KEY_CTRL_Y 25 +#define KEY_CTRL_Z 26 + + +/* register keys in curses */ +void keys_init(void); + +#endif + @@ -0,0 +1,314 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "bores/bores.h" +#include <stdlib.h> +#include <string.h> +#include <ncurses.h> + +#include "layer.h" +#include "chtr.h" + +const Cell BLANK_CELL = { ' ', 0x70 }; + +Layer *layer_create(const char *layer_name, int width, int height) { + int i, j; + Layer *layer = (Layer *) zalloc(sizeof(Layer)); + + layer->name = 0; + dstrset(&layer->name, layer_name); + layer->width = width; + layer->height = height; + layer->visible = true; + layer->transp = false; + + layer->cells = (Cell**) zalloc(width * sizeof(Cell*)); + for (i = 0; i < width; i++) { + layer->cells[i] = (Cell*) zalloc(height * sizeof(Cell)); + for (j = 0; j < height; j++) { + layer->cells[i][j].ch = ' '; + layer->cells[i][j].attr = 0x70; + } + } + + return layer; +} + +void layer_destroy(Layer *layer) { + int i; + if (!layer) return; + dstrset(&layer->name, 0); + + for (i = 0; i < layer->width; i++) free(layer->cells[i]); + free(layer->cells); +} + +bool is_cell_transp(const Cell *c) { + return c->ch == ' ' && c->attr == 0x70; +} + +void layer_blit(Layer *src, int xsrc, int ysrc, int width, int height, + Layer *dst, int xdst, int ydst) { + int dx, dy; + int src_x, src_y, dst_x, dst_y; + + /* brace your self to read the most inefficient blit code you have + * ever read in your life. The following algorithm makes bubble-sort + * look blazing fast. */ + for (dx = 0; dx < width; dx++) { + for (dy = 0; dy < height; dy++) { + src_x = xsrc + dx; + src_y = ysrc + dy; + dst_x = xdst + dx; + dst_y = ydst + dy; + + if (!layer_valid_cell(src, src_x, src_y) || + !layer_valid_cell(dst, dst_x, dst_y)) continue; + + if (src->transp && + is_cell_transp(&src->cells[src_x][src_y])) continue; + + dst->cells[dst_x][dst_y] = src->cells[src_x][src_y]; + } + } +} + + +bool layer_valid_cell(Layer *layer, int x, int y) { + return (x >= 0 && x < layer->width && y >= 0 && y < layer->height); +} + +void layer_paint(Layer *layer, int x0, int y0, int xclip, int yclip, + int wclip, int hclip, + void (*modify)(int x, int y, int *ch, int *attr)) { + + int x, xi, xf; int y, yi, yf; int ch, attr; + + interval_intersect(x0 , x0 + layer->width - 1, + xclip, xclip + wclip - 1, &xi, &xf); + interval_intersect(y0 , y0 + layer->height - 1, + yclip, yclip + hclip - 1, &yi, &yf); + + for (x = xi; x <= xf; x++) for (y = yi; y <= yf; y++) { + if (!kurses_move(x, y)) continue; + ch = layer->cells[x - x0][y - y0].ch; + attr = layer->cells[x - x0][y - y0].attr; + + if (modify) (*modify)(x - x0, y - y0, &ch, &attr); + + if (layer->transp && + is_cell_transp(&layer->cells[x - x0][y - y0])) continue; + + kurses_color(attr >> 4, attr & 0x0F); + addch(chtr_a2c(ch)); + } +} + +void layer_paint_opaque(Layer *layer, int x0, int y0, int xclip, int yclip, + int wclip, int hclip, + void (*modify)(int x, int y, int *ch, int *attr)) { + bool backup = layer->transp; + layer->transp = false; + layer_paint(layer, x0, y0, xclip, yclip, wclip, hclip, modify); + layer->transp = backup; + + /* I agree, this is a monument to sloppiness. + * But it works, and does what is promised by the documentation. */ +} + +Layer *layer_dup(const char *layer_name, Layer *model) { + Layer *l; + if (!model) return NULL; + + l = layer_create(layer_name, model->width, model->height); + l->transp = model->transp; + layer_blit(model, 0, 0, model->width, model->height, l, 0, 0); + return l; +} + +/* table is a vector of two strings. If ch is found in table[0] at position n, + * return value is table[1][n]. Else, return value is ch. + * table[0] and table[1] are assumed to be of the same size. */ +static char tbl_lookup(char **table, int ch) { + const char *s = table[0], *p = table[1]; + while (*s) { + if (*(s++) == ch) return *p; + p++; + } + return ch; +} + +void layer_flip_x(Layer *layer, bool flipchars) { + Layer *tmp; + int x, y; + static char *flip_table[2] = { + "`'()/\\<>[]{}\x03\x05\x06\x08\x09\x0b", /* funny hex chars are line */ + "'`)(\\/><][}{\x05\x03\x08\x06\x0b\x09" /* drawing chars (see chtr.h) */ + }; + + tmp = layer_dup("tmp", layer); + for (y = 0; y < layer->height; y++) { + for (x = 0; x < layer->width; x++) { + Cell c = tmp->cells[x][y]; + if (flipchars) c.ch = tbl_lookup(flip_table, c.ch); + + layer->cells[layer->width - x - 1][y] = c; + } + } + + layer_destroy(tmp); +} + +void layer_flip_y(Layer *layer, bool flipchars) { + Layer *tmp; + int x, y; + static char *flip_table[2] = { + "/\\\x03\x09\x04\x0a\x05\x0b", + "\\/\x09\x03\x0a\x04\x0b\x05" + }; + + tmp = layer_dup("tmp", layer); + for (y = 0; y < layer->height; y++) { + for (x = 0; x < layer->width; x++) { + Cell c = tmp->cells[x][y]; + if (flipchars) c.ch = tbl_lookup(flip_table, c.ch); + + layer->cells[x][layer->height - y - 1] = c; + } + } + + layer_destroy(tmp); +} + +void layer_save(Layer *lyr, AeFile *f) { + int x, y; + char *buf = zalloc(lyr->width * 4 + 1); + + aeff_write_header(f, "Layer"); + aeff_write_string(f, "name", lyr->name ? lyr->name : "unnamed"); + aeff_write_int(f, "width", lyr->width); + aeff_write_int(f, "height", lyr->height); + aeff_write_bool(f, "visible", lyr->visible); + aeff_write_bool(f, "transparent", lyr->transp); + + for (y = 0; y < lyr->height; y++) { + /* fill in buf with current line (decoded into hex duplets) */ + for (x = 0; x < lyr->width; x++) { + chr2hex(lyr->cells[x][y].ch, &buf[x * 4]); + chr2hex(lyr->cells[x][y].attr, &buf[x * 4 + 2]); + } + + /* save line to file */ + aeff_write_string(f, "layer-line", buf); + } + + aeff_write_footer(f, "Layer"); + zfree(&buf); +} + +Layer *layer_load(AeFile *f) { + int x, y; + char *buf = 0; + Layer *lyr = NULL; + char *name = 0; + int width, height; + + if (!aeff_read_header(f, "Layer")) goto exception; + if (!aeff_read_string(f, "name", &name)) goto exception; + if (!aeff_read_int(f, "width", &width)) goto exception; + if (!aeff_read_int(f, "height", &height)) goto exception; + + lyr = layer_create(name, width, height); + zfree(&name); + + if (!aeff_read_bool(f, "visible", &lyr->visible)) goto exception; + if (!aeff_read_bool(f, "transparent", &lyr->transp)) goto exception; + + for (y = 0; y < lyr->height; y++) { + if (!aeff_read_string(f, "layer-line", &buf)) goto exception; + + if (strlen(buf) != lyr->width * 4) { + aeff_set_error("layer-line line has incorrect width"); + goto exception; + } + + /* interpret buf as width*4 hex duplets specifying char and attribute + * for each cell in the line */ + for (x = 0; x < lyr->width; x++) { + lyr->cells[x][y].ch = hex2chr(&buf[x * 4]); + lyr->cells[x][y].attr = hex2chr(&buf[x * 4 + 2]); + } + + zfree(&buf); + } + + aeff_read_footer(f, "Layer"); + + return lyr; + +exception: + if (lyr) layer_destroy(lyr); + if (buf) zfree(&buf); + return NULL; +} + +Layer *layer_load_OLD(FILE *f) { + char *lyr_name; + char signature[3]; + int width, height, x, y; + bool v, t; + Layer *l; + + signature[0] = fgetc(f); + signature[1] = fgetc(f); + signature[2] = 0; + + if (strcmp(signature, "L3")) return NULL; /* unknown format */ + if ( !(lyr_name = floadstr(f)) ) return NULL; + fread(&width, sizeof(int), 1, f); + fread(&height, sizeof(int), 1, f); + v = fgetc(f) ? true : false; + t = fgetc(f) ? true : false; + + l = layer_create(lyr_name, width, height); + l->visible = v; + l->transp = t; + + for (x = 0; x < width; x++) for (y = 0; y < height; y++) { + l->cells[x][y].ch = fgetc(f); + l->cells[x][y].attr = fgetc(f); + } + + return l; +} + @@ -0,0 +1,144 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + + +#ifndef _btco_aewan_layer_h +#define _btco_aewan_layer_h + +#include <stdbool.h> +#include "bores/bores.h" +#include <stdio.h> +#include "aeff.h" + +struct _Cell { + unsigned char ch; /* character that occupies this cell. + * Since a control character may never be in a cell, + * aewan uses some characters in the 0-31 range to + * represent vt100 line graphics characters and + * other special characters. See the chtr.h + * file for more details. */ + + unsigned char attr; /* attribute of the character */ +}; +typedef struct _Cell Cell; + +struct _Layer { + char *name; /* name of this layer */ + int width, height; /* width and height of layer, in cells */ + Cell **cells; /* indexed cells[0][0] to cells[width-1][height-1] */ + bool visible; /* whether visibility for this layer is enabled */ + bool transp; /* whether this layer has transparency enabled. + * Upon blit and paint operations, transparent + * cells will not be drawn. */ +}; +typedef struct _Layer Layer; + +/* A blank cell. */ +extern const Cell BLANK_CELL; + +/* Creates a new, empty layer with the specified dimensions. + * Sets the layer name to <layer_name>. Returns a pointer to the newly + * created layer. */ +Layer *layer_create(const char *layer_name, int width, int height); + +/* Creates a new layer that is an exact copy of the given layer, + * except possibly for the name. Returns a pointer to the newly created + * layer */ +Layer *layer_dup(const char *layer_name, Layer *model); + +/* Destroys a layer previously created with layer_create */ +void layer_destroy(Layer *layer); + +/* Copies part of or the totality of the contents of the source layer onto + * the destination layer. The source rectangle for the copy is given + * by xsrc, ysrc, width and height; the destination rectangle is given + * by xdst, ydst, width and height. */ +void layer_blit(Layer *src, int xsrc, int ysrc, int width, int height, + Layer *dst, int xdst, int ydst); + +/* Paints the given layer on the screen, placing its top-left corner + * at the given coordinates x0, y0, which may be negative. The clipping + * rectangle is given by xclip, yclip, wclip and hclip. + * + * Painting code allows custom modification of output through + * a call to the modify function. If <modify> is not NULL, it + * will be called for every cell drawn, and it can modify the + * color. + * + * Please note that this function pays no attention to the layer's + * 'visible' flag: it draws it regardless. It DOES pay attention + * to the 'transparent' flag. + */ +void layer_paint(Layer *layer, int x0, int y0, int xclip, int yclip, + int wclip, int hclip, + void (*modify)(int x, int y, int *ch, int *attr)); + +/* Same as layer_paint, but forces opaque rendering, that is, transparent + * cells will be rendered as white-foreground, black-background spaces. */ +void layer_paint_opaque(Layer *layer, int x0, int y0, int xclip, int yclip, + int wclip, int hclip, + void (*modify)(int x, int y, int *ch, int *attr)); + +/* Returns whether the given (x, y) coordinates are valid within + * layer lyr, that is, returns true if and only if 0 <= x <= lyr->width + * and 0 <= y <= lyr->height */ +bool layer_valid_cell(Layer *layer, int x, int y); + +/* Performs a vertical mirroring operation on the given layer. + * The <flipchars> parameter indicates whether characters themselves + * should be "flipped" to their mirrored counterparts (e.g. + * change '>' to '<', etc). */ +void layer_flip_x(Layer *layer, bool flipchars); + +/* Performs a horizontal mirroring operation on the given layer. + * The <flipchars> parameter indicates whether characters themselves + * should be "flipped" to their mirrored counterpars (e.g. + * change '\' to '/' */ +void layer_flip_y(Layer *layer, bool flipchars); + +/* Writes layer's data to file f */ +void layer_save(Layer *lyr, AeFile *f); + +/* Attempts to load layer from file f; if loading succeeds, returns + * a pointer to a dynamically allocated layer that corresponds + * to the loaded data; if an error occurs, returns NULL. */ +Layer *layer_load(AeFile *f); + +/* Loads a layer in the OLD binary format */ +Layer *layer_load_OLD(FILE *f); + +/* Returns whether the given cell is considered transparent or not */ +bool is_cell_transp(const Cell* c); + +#endif + diff --git a/layerdlg.c b/layerdlg.c new file mode 100644 index 0000000..ffddb5d --- /dev/null +++ b/layerdlg.c @@ -0,0 +1,168 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "bores/bores.h" +#include <ncurses.h> + +#include "document.h" +#include "colordlg.h" +#include "psd.h" +#include "absmenu.h" + +/* DLG_W +- ,---------------------------, +D | - | +L | : LIST_H | +G | : | +| | : | +H | - | +: +---------------------------+ +: | A | +: | | +: | | +: | | +- `---------------------------' +*/ + +#define DLG_W 42 +#define DLG_H 19 +#define LIST_H 11 + +static AbsMenu *menu = 0; + +static void painter(int i, AbsMenu *m) { + Layer *l = _doc->layers[i]; + printw("%2d: %c%c (%3d x %3d) %s", i, + l->visible ? 'v' : ' ', + l->transp ? 't' : ' ', + l->width, l->height, (l->name ? l->name : "(untitled)")); +} + +static void paint_dlg(void) { + int x0, y0; int x, y; + + kurses_color(7, 0); + draw_centered_window(DLG_W, DLG_H, "Layer Manager", &x0, &y0); + + if (!menu) { + menu = menu_create(&(_doc->layer_count), x0, + y0, DLG_W - 2, LIST_H, + 0x71, 0x70, painter); + menu_select_item(menu, _lyr); + } + + draw_hline(x0 - 1, y0 + LIST_H, DLG_W, ACS_LTEE, ACS_HLINE, ACS_RTEE); + + /* print instructions */ + kurses_move(x = x0 + 1, y = y0 + LIST_H + 1); + + kurses_color(2, 0); addch('<'); addch(ACS_LRCORNER); addch(' '); + kurses_color(7, 0); + printw(": go to layer"); + + kurses_move(x, ++y); + kurses_color(2, 0); addstr("d "); kurses_color(7, 0); + printw(": delete layer"); + + kurses_move(x, ++y); + kurses_color(2, 0); addstr("+/-"); kurses_color(7, 0); + printw(": move layer up/down"); + + kurses_move(x, ++y); + kurses_color(2, 0); addstr("v "); kurses_color(7, 0); + printw(": toggle visibility"); + + kurses_move(x, ++y); + kurses_color(2, 0); addstr("t "); kurses_color(7, 0); + printw(": toggle transparency"); + + menu_paint(menu); +} + +void show_layer_dlg(void) { + int ch; int quit = 0; + Layer *lyr; + + menu = 0; + + while (!quit) { + paint_dlg(); + refresh(); + ch = getch(); + switch (ch) { + case 10: switch_to_layer(menu->sel_item); + /* fall through */ + case 27: case 3: case 7: quit = 1; break; + case 'd': /* delete layer */ + document_del_layer(_doc, menu->sel_item); + if (_doc->layer_count == 0) /* no layers, so close dialog */ + quit = 1; + else if (menu->sel_item >= _doc->layer_count) + menu->sel_item = _doc->layer_count - 1; + break; + case '+': case '=': /* move layer up */ + if (menu->sel_item > 0) { + int i = menu->sel_item; Layer **ls = _doc->layers; + Layer* l = ls[i-1]; + ls[i-1] = ls[i]; + ls[i] = l; + + menu->sel_item--; + } + break; + case '-': case '_': + if (menu->sel_item < _doc->layer_count - 1) { + int i = menu->sel_item; Layer **ls = _doc->layers; + Layer* l = ls[i+1]; + ls[i+1] = ls[i]; + ls[i] = l; + + menu->sel_item++; + } + break; + case 'v': /* toggle layer visibility */ + lyr = _doc->layers[menu->sel_item]; + lyr->visible = !lyr->visible; + break; + case 't': /* toggle layer transparency */ + lyr = _doc->layers[menu->sel_item]; + lyr->transp = !lyr->transp; + break; + + default: if (menu) menu_handle_key(menu, ch); + } + } + + if (menu) menu_destroy(menu); +} + diff --git a/layerdlg.h b/layerdlg.h new file mode 100644 index 0000000..424e540 --- /dev/null +++ b/layerdlg.h @@ -0,0 +1,45 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + + +#ifndef _btco_aewan_layerdlg_h +#define _btco_aewan_layerdlg_h + +/* Shows the layer management dialog. Through it, the user will be able + * to switch to a different layer, delete layers, swap layers, + * toggle the transparency flag in layers, etc. Returns when the user + * is done. */ +void show_layer_dlg(void); + +#endif + diff --git a/make-package.sh b/make-package.sh new file mode 100644 index 0000000..f697209 --- /dev/null +++ b/make-package.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +if ! [ -f configure ]; then + echo "./configure does not exist. Run autoconf." + exit 1 +fi + +/bin/rm -rf autom4te.cache + +X=`tempfile` +/bin/rm -f $X +mkdir $X + +BASENAME=aewan-`cat version.h | grep AEWAN_PROGRAM_VERSION | grep -v AEWAN_PROGRAM_VERSION_NAME | cut -d\" -f2` + +(cd .. && cp -a aewan $X/$BASENAME) +(cd $X && find $X -name CVS -type d -exec rm -rf {} \; 2>/dev/null ) + +(cd $X && tar -zc $BASENAME) > ../$BASENAME.tar.gz + +/bin/rm -rf $X +echo "../$BASENAME.tar.gz generated." + diff --git a/man/man1/aecat.1 b/man/man1/aecat.1 new file mode 100644 index 0000000..36dfabd --- /dev/null +++ b/man/man1/aecat.1 @@ -0,0 +1,63 @@ +.TH aecat "1" "March 2005" "aecat (Aewan Ascii Art Editor)" +.SH NAME +aecat \- display an aewan document +.SH SYNOPSIS +.B aecat +[-b] [-c] [-{n|N}] [{-p | -l <layer_num>}] [-f <format>] [-o <output_file>] inputfile + +.SH DESCRIPTION +This is an utility program that will convert an aewan document +to ANSI escape sequences so that it can be rendered on a standard +terminal. Alternatively, it can also generate HTML code for displaying +the document in a web page. Any particular layer of the document +may be converted, or you may request a composite of all layers. + +.SH OPTIONS +.TP +\fB\-f\fR +specifies output format - can "text", "html" or "comment". Default is "text". +The "comment" format extracts document metadata. +.TP +\fB\-c\fR +prepend a 'clear screen' escape sequence (only valid when outputting +text). +.TP +\fB\-o\fR\fI<file>\fR +writes output to specified file rather than stdout +.TP +\fB\-b\fR +disables output of color (only characters will be printed). +.TP +\fB\-l\fR\fI<layer_no>\fR +specifies which layer of the document is to be used +(must be an index, not a layer name). By default, layer 0 will be used. +.TP +\fB\-L\fR +displays the number of layers in the file. +.TP +\fB\-p\fR +exports a composite, that is, overlays all visible layers, +paying attention to layer transparency, etc. The size of the +composite will be the size of the first layer +.TP +\fB\-n\fR +suppress output of newlines +.TP +\fB\-h\fR +prints a short help text + +.SH AUTHORS +This program is part of the Aewan Ascii Art Editor package. +See aewan(1) for author information. + +.SH LICENSE +Copyright (c) 2004-2005 Bruno Takahashi C. de Oliveira. All rights reserved. + +This program is licensed under the GNU General Public License, +version 2 or, at your option, any later version. For full license +information, please refer to the COPYING file that accompanies +the program. + +.SH SEE ALSO +\fBaewan\fR(1), \fBaewan\fR(5), \fBaemakeflic\fR(1) + diff --git a/man/man1/aemakeflic.1 b/man/man1/aemakeflic.1 new file mode 100644 index 0000000..b5cdd95 --- /dev/null +++ b/man/man1/aemakeflic.1 @@ -0,0 +1,50 @@ +.TH aemakeflic "1" "September 2005" "aemakeflic (Aewan Ascii Art Editor)" +.SH NAME +aemakeflic \- produce an animation from an aewan document +.SH SYNOPSIS +.B aemakeflic +[-f {less|sh}] [-N] [-b] [-d <delay>] input.ae [outputfile.ext] + +.SH DESCRIPTION +This utility will make an ascii animation out of an aewan document. It +can currently produce animations in two formats: a shellscript which, +when executed, will display the animation and a "less movie" intended +to be "played" on the very popular 'less' output pager -- that is, the +user will see the animation as he pages down through the file in an +appropriate window size. + +Each layer in the aewan document is interpreted as one frame of the animation. +Layer transparency and compositing are not used: each layer becomes a frame. + +.SH OPTIONS +.TP +\fB\-f\fR +specifies output format - can "sh" for a shellscript or "less" for a +"less movie" +.TP +\fB\-N\fR +omit the initial instructions that are normally included in the resulting +file. The instructions will orient the user as to how to play the file. +.TP +\fB\-b\fR +disables output of color (only characters will be printed). +.TP +\fB\-d delay\fR +specifies the delay between frames (for shellscript only), given in +milliseconds. + +.SH AUTHORS +This program is part of the Aewan Ascii Art Editor package. +See aewan(1) for author information. + +.SH LICENSE +Copyright (c) 2004-2005 Bruno Takahashi C. de Oliveira. All rights reserved. + +This program is licensed under the GNU General Public License, +version 2 or, at your option, any later version. For full license +information, please refer to the COPYING file that accompanies +the program. + +.SH SEE ALSO +\fBaewan\fR(1), \fBaewan\fR(5), \fBaecat\fR(1) + diff --git a/man/man1/aewan.1 b/man/man1/aewan.1 new file mode 100644 index 0000000..d50b64e --- /dev/null +++ b/man/man1/aewan.1 @@ -0,0 +1,50 @@ +.TH aewan "1" "August 2004" "aewan (Aewan Ascii Art Editor)" + +.SH NAME +aewan \- An ascii-art editor + +.SH SYNOPSIS +.B aewan [\fIfilename\fR] +.SH DESCRIPTION +.PP +Aewan is a multi-layered ascii-art/animation editor that produces both +stand-alone cat-able art files and an easy-to-parse format for integration in +your terminal applications (for information about the file format, +see the aewan(5) manpage). + +If you invoke the program without a command-line argument, it will +open an untitled document for you to edit. If you supply an argument, +it must be the name of an aewan file you wish to open. That file +must exist, or an error will occur. + +.SH PROJECT HOME PAGE +The Aewan Project's official homepage is the following: + + + \fBhttp://aewan.sourceforge.net\fR + +There you will find author information, FAQ, links to the latest +version of the program, etc. + +.SH AUTHORS +The developers can be contacted through the following e-mail address: + + \fBaewan-devel@lists.sf.net\fR + +People who have worked or are currently working on this project: + + * Bruno T. C. de Oliveira (brunotc@gmail.com) + * Peep Pullerits (http://solicit.estprog.ee; solicit@estprog.ee) + * Praveen Kurup <praveen_kurup@jasubhai.com> + * Gerfried Fuchs <alfie@ist.org> + +.SH LICENSE INFORMATION +Copyright (c) 2004 Bruno Takahashi C. de Oliveira. All rights reserved. + +This program is licensed under the GNU General Public License, +version 2 or, at your option, any later version. For full license +information, please refer to the COPYING file that accompanies +the program. + +.SH SEE ALSO +\fBaecat\fR(1), \fBaewan\fR(5) diff --git a/man/man5/aewan.5 b/man/man5/aewan.5 new file mode 100644 index 0000000..d4d3cee --- /dev/null +++ b/man/man5/aewan.5 @@ -0,0 +1,108 @@ +.TH aewan "5" "August 2005" "aewan (Aewan Ascii Art Editor)" + +.SH NAME +aewan \- File format documentation + +.SH INTRODUCTION +Starting with version 0.9.0, Aewan features an all-new, easier to parse +file format. Prior versions used a binary (largely undocumented) file +format, and relied on a program (ae2aes) to convert it to a readable +format. With the new format, the ae2aes utility became unnecessary +and was deprecated. + +An aewan document is a gzipped file. Therefore, you must first gunzip +it in order to be able to parse its contents. On the command line, you +could use \fIzcat\fR or something of the sort. On a program, you will +probably want to use the \fIzlib\fR library. + +In the future it might be better for Aewan to supply a shared library +to enable parsing of aewan files with minimal effort. Such a library would +have to be integrated with the editor in order not to have to duplicate +code (i.e. the editor itself would be just a client of the library). +But for the time being, you have to read and parse the format +on your own. + +.SH FILE FORMAT + +In the description below, the items in between brackets are NOT literal, +they are placeholders. [S] is a placeholder for a string and [N] is a +placeholder for a decimal integer, and [B] is a placeholder for a boolean +value ('true' or 'false'). A line with "..." is not literal either, it +just means that the lines above repeat a certain number of times. + +.nf +<Aewan Document v1 + layer-count: int: [N] + meta-info: str: [S] + <Layer + name: str: [S] + width: int: [N] + height: int: [N] + visible: bool: [B] + transparent: bool: [B] + layer-line: str: [S] + layer-line: str: [S] + layer-line: str: [S] + (...there are <height> such lines...) + >Layer + (...there are <layer-count> such blocks...) +>Aewan Document v1 +.ff + +Indentation is ignored, but all other whitespace is significant. +In particular, you can't omit the space that immediately follows +the ':' field delimiters, or supply more than one space there. +Notice that the file format does not use any quotation marks +for the values, not even strings. + +.SH REPRESENTATION OF STRINGS +Strings are represented almost literally in the file (where the [S] +placeholders are in the blueprint above), and are not put in between +quotes or anything. However, special characters (ASCII codes 1 to 31) +are escaped: the escape code is a backslash, followed by the +character '0' + ch, where ch is the special character. Thus, a newline +character would be represented by "\\:", since ":" is '0' + 10. + +.SH REPRESENTATION OF INTEGERS AND BOOLEANS +Integers use just the plain old decimal representation. The booleans +are represented as strings: either "true" or "false" (without quotes). + +.SH REPRESENTATION OF LAYER LINES +Each layer-line is a string, but it is specially formatted in order +to convey the characters and attibutes in that line. In order to +understand the format of a layer-line string, it is first necessary +to introduce the concept of cells. A cell in an aewan layer is each +of the spaces that can contain a character. A cell has two pieces +of data: the character that is in it, and a color attribute. +The character is just that: an 8-bit value represing the character +drawn there. The color attribute is an 8-bit unsigned value that packs the +foreground and background color of a given cell, as well as standout +and blink attributes. + +The following color codes are used: 0=black, 1=red, 2=green, +3=yellow, 4=blue, 5=magenta, 6=cyan, 7=white. + +The 8 bits of the attribute have the following meanings: SFFFLBBB. +Where S is the standout bit, FFF is the 3-bit color code for +the foreground color, L is the blink bit, and BBB is the +3-bit color code for the background color. + +The layer-line string is composed of the hexadecimal representation +of layer_width*2 bytes. Each 2 bytes is the information for one +cell of the line: the first byte is the character, and the second +is the attribute. For example, the hex representation for 'A' is +0x41, so a line with five 'A's each of them in a different foreground +color (but all with black background) would be represented as +41104120413041404150. + +.SH LICENSE INFORMATION +Copyright (c) 2004-2005 Bruno Takahashi C. de Oliveira. All rights reserved. + +This program is licensed under the GNU General Public License, +version 2 or, at your option, any later version. For full license +information, please refer to the COPYING file that accompanies +the program. + +.SH SEE ALSO +\fBaecat\fR(1), \fBaewan\fR(1) + diff --git a/menubar-items.inc b/menubar-items.inc new file mode 100644 index 0000000..a1b4a6d --- /dev/null +++ b/menubar-items.inc @@ -0,0 +1,77 @@ +static Menu menu[] = { + { "[F1] File", 1, 0, 0, + 7, + { + { 'N', "&New", COMMAND_NEW_FILE, + "Clears everything and starts from scratch" }, + { 'L', "&Load...", COMMAND_LOAD_FILE, + "Loads a file into the editor" }, + { 'S', "&Save", COMMAND_SAVE_FILE, + "Saves the current drawing" }, + { 'A', "Save &As...", COMMAND_SAVE_FILE_AS, + "Saves the current drawing in a specified file" }, + { 'M', "Edit &Meta...", COMMAND_EDIT_META, + "Opens an editor for you to edit this document's metadata" }, + { ' ', "", COMMAND_UNDEFINED, NULL }, + { 'Q', "&Quit", COMMAND_QUIT, + "Quits program" }, + } + }, + + { "[F2] Edit", 16, 0, 0, + 8, + { + { 'C', "Drawing &color...", COMMAND_SHOW_COLOR_DLG, + "Brings up the color selection dialog" }, + { 'I', "Toggle &Insert", COMMAND_TOGGLE_INSERT, + "Toggles insert/overwrite mode" }, + { 'K', "Pic&k color", COMMAND_PICK_COLOR, + "Picks color under cursor to use as current color" }, + { 'T', "&Tint cell", COMMAND_TINT_CELL, + "Applies current color to cell under cursor" }, + { ' ', "", COMMAND_UNDEFINED, NULL }, + { 'S', "Toggle &select mode", COMMAND_TOGGLE_SELECTION, + "Toggles select mode on/off" }, + { 'L', "Toggle &line-drawing", COMMAND_TOGGLE_LINE_MODE, + "Toggles line-drawing mode on/off. Use 0-9 to draw lines" }, + { 'P', "Toggle com&posite", COMMAND_TOGGLE_COMPOSITE, + "Toggles composite (all-layer) view on/off" }, + } + }, + + { "[F3] Layer", 32, 0, 0, + 9, + { + { 'A', "&Add layer (defaults)", COMMAND_ADD_LAYER_DEFAULTS, + "Adds a layer with default parameters" }, + { 'L', "Add &layer (specify)...", COMMAND_ADD_LAYER_SPECIFY, + "Adds a layer with custom parameters" }, + { 'D', "&Duplicate layer", COMMAND_DUP_LAYER, + "Duplicates current layer. Copy is added to the bottom of the stack." }, + { 'R', "&Rename layer...", COMMAND_RENAME_LAYER, + "Renames the current layer" }, + { 'Z', "Resi&ze layer...", COMMAND_RESIZE_LAYER, + "Resizes the current layer" }, + { 'M', "&Manage layers...", COMMAND_SHOW_LAYER_DLG, + "Shows a dialog in which you can manipulate layers" }, + { ' ', "", COMMAND_UNDEFINED, NULL }, + { 'N', "Go to &next layer", COMMAND_NEXT_LAYER, + "Goes to the next layer" }, + { 'P', "Go to &previous layer", COMMAND_PREV_LAYER, + "Goes to the previous layer" }, + } + }, + + { "[F4] Help", 64, 0, 0, + 3, + { + { 'K', "&Key reference", COMMAND_SHOW_HELP_DLG, + "Shows a table of keys and their functions" }, + { ' ', "", COMMAND_UNDEFINED, NULL }, + { 'A', "&About Aewan", COMMAND_SHOW_ABOUT_DLG, + "Shows information about the program" }, + } + }, +}; +static int menu_count = 4; + diff --git a/menubar.c b/menubar.c new file mode 100644 index 0000000..ec059b3 --- /dev/null +++ b/menubar.c @@ -0,0 +1,228 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "bores/bores.h" +#include <stdbool.h> +#include <ncurses.h> +#include <string.h> + +#include "commands.h" +#include "menubar.h" + +/* menu colors */ +#define MENU_ATT_NORMAL 0x07 +#define MENU_ATT_SEL 0xF1 +#define MENU_ATT_ACCEL_NORMAL 0x17 +#define MENU_ATT_ACCEL_SEL 0xE1 + +#define MAX_ITEMS_PER_MENU 32 + +typedef struct MenuItem_ { + char accel; /* accelerator (shortcut) char */ + const char *caption; /* text of the item. If text is "", it is a separator + * In that case all remaining fields have no meaning */ + int command; /* the command that this item triggers when + * selected - this value will be returned by + * menubar_show */ + const char *desc; /* description of the item, which will appear at + * the bottom part of the screen when the item + * is highlighted */ +} MenuItem; + +typedef struct Menu_ { + const char *caption; /* text */ + int startcol; /* column at which the left edge of this menu is + * placed onscreen */ + int menu_h, menu_w; /* menu dimensions. If 0, calculated at run-time */ + + int item_count; /* how many items this menu has */ + MenuItem item[MAX_ITEMS_PER_MENU]; /* vector of items */ + +} Menu; + +/* menu data (included as a separate file for better organization) */ +#include "menubar-items.inc" +/* defines menu[] as an array of menu's, and menu_count. */ + +/* menu state */ +static int open_menu; /* which menu is open */ +static int menu_sel; /* which item is currently selected on the + * currently open menu */ + +/* declaration of internal functions */ +static void menubar_paint(); /* paints menu onscreen */ +static void menuitem_print(const char *caption, bool sel, int minlen); +static void menu_calc_dims(Menu *m); +static bool chr_icomp(char c1, char c2); /* compares characters, + * case-insensitive */ + +int menubar_show(int startm) { + int ch, i; + int cmd = 0; bool quit = false; + Menu *omenu; + menu_sel = 0; + + open_menu = startm; + if (open_menu < 0) open_menu = 0; + if (open_menu >= menu_count) open_menu = menu_count - 1; + + push_screen(); + + while (!quit) { + omenu = &menu[open_menu]; + menubar_paint(); + ch = getch(); + + switch (ch) { + case KEY_LEFT: if (--open_menu < 0) open_menu = menu_count-1; + menu_sel = 0; + break; + case KEY_RIGHT: if (++open_menu >= menu_count) open_menu = 0; + menu_sel = 0; + break; + case KEY_UP: + do { + if (--menu_sel < 0) menu_sel = omenu->item_count-1; + } while (!*(omenu->item[menu_sel].caption)); + break; + case KEY_DOWN: + do { + if (++menu_sel >= omenu->item_count) menu_sel = 0; + } while (!*(omenu->item[menu_sel].caption)); + break; + case 10: quit = true; cmd = omenu->item[menu_sel].command; + break; + case 27: quit = true; cmd = COMMAND_UNDEFINED; + break; + } + + if (ch > KEY_F0 && ch <= KEY_F(12) && (ch - KEY_F0 - 1) < menu_count) { + open_menu = ch - KEY_F0 - 1; + menu_sel = 0; + } + + /* handle accelerator keys */ + for (i = 0; i < omenu->item_count; i++) { + if (chr_icomp(omenu->item[i].accel, ch)) { + /* item selected by accelerator key */ + cmd = omenu->item[i].command; + quit = true; + break; + } + } + } + + restore_screen(); + pop_screen(); + refresh(); + return cmd; +} + +static bool chr_icomp(char c1, char c2) { + c1 = (c1 >= 'A' && c1 <= 'Z') ? c1 - 'A' + 'a' : c1; + c2 = (c2 >= 'A' && c2 <= 'Z') ? c2 - 'A' + 'a' : c2; + return (c1 == c2); +} + +static void menubar_paint() { + int i; + Menu *omenu; + restore_screen(); + /* paint the bar at the top of the screen */ + kurses_color_at(MENU_ATT_NORMAL); + draw_hline(0, 0, kurses_width(), ' ', ' ', ' '); + + for (i = 0; i < menu_count; i++) { + kurses_move(menu[i].startcol, 0); + menuitem_print(menu[i].caption, i == open_menu, -1); + } + + omenu = &menu[open_menu]; + + /* if open menu's dimensions have not yet been calculated, do so */ + if (!omenu->menu_h) menu_calc_dims(omenu); + + /* paint the open menu */ + kurses_color_at(MENU_ATT_NORMAL); + draw_window(omenu->startcol, 1, omenu->menu_w + 2, omenu->menu_h + 2, ""); + for (i = 0; i < omenu->item_count; i++) { + kurses_move(omenu->startcol+1, i + 2); + menuitem_print(omenu->item[i].caption, i == menu_sel, omenu->menu_w); + } + + /* paint the description line */ + kurses_move(0, kurses_height()-1); + kurses_color_at(MENU_ATT_NORMAL); + i = strlen(omenu->item[menu_sel].desc); + addstr(omenu->item[menu_sel].desc); + while (i++ < kurses_width()) addch(' '); + + kurses_move(kurses_width()-1, kurses_height()-1); + refresh(); +} + +static void menuitem_print(const char *s, bool sel, int minlen) { + bool next_is_accel = false; + int printed = 0; + while (*s || (printed < minlen)) { + if (*s == '&') { + next_is_accel = true; + s++; + continue; + } + + kurses_color_at(sel ? + ( next_is_accel ? MENU_ATT_ACCEL_SEL : MENU_ATT_SEL ) : + ( next_is_accel ? MENU_ATT_ACCEL_NORMAL : MENU_ATT_NORMAL )); + + addch(*s ? *s : ' '); + printed++; + + next_is_accel = false; + if (*s) s++; + } +} + +static void menu_calc_dims(Menu *m) { + int i; + int width = 1, len = 0; + + for (i = 0; i < m->item_count; i++) { + len = strlen(m->item[i].caption); + if (len > width) width = len; + } + + m->menu_h = m->item_count; + m->menu_w = width; +} + diff --git a/menubar.h b/menubar.h new file mode 100644 index 0000000..64e924c --- /dev/null +++ b/menubar.h @@ -0,0 +1,51 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewan_menubar_h +#define _btco_aewan_menubar_h + +/* Shows the menu onscreen and lets the user interact with it. + * Returns the command number (as in command.h) of the selected item. + * This function will restore the screen contents to their previous + * state before returning (a most unusual courtesy, mind you). + * + * If the user cancels the menu, returns COMMAND_UNDEFINED. + * + * startopen gives the index of the menu that should be rolled down + * by default. If 0, the leftmost menu will start rolled down; if 1, + * the next one to the right will and so on. + */ +int menubar_show(int startopen); + +#endif + @@ -0,0 +1,82 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "bores/bores.h" + +#include "psd.h" +#include "document.h" + +/* global program state data definitions */ +struct _Document *_doc; +char *_filename; +int _lyr; +int _x, _y; +int _svx, _svy; +int _fg, _bg; +int _selmode; +int _ax, _ay; +bool _insmode; +bool _lgmode; +bool _compmode; +struct _Layer *_clipboard; + + +void get_norm_sel(int *x0, int *y0, int *x1, int *y1) { + sort_two(_x, _ax, x0, x1); + sort_two(_y, _ay, y0, y1); +} + +bool doc_empty() { return 0 >= _doc->layer_count; } + +void zero_state() { + _doc = document_create(); + _filename = 0; + _lyr = _x = _y = _svx = _svy = _ax = _ay = 0; + _selmode = SM_NONE; + _fg = 7; + _bg = 0; + _insmode = false; + _clipboard = 0; + _lgmode = false; + _compmode = false; +} + +void switch_to_layer(int l) { + Layer *lyr; + if (l < 0 || l >= _doc->layer_count) return; + + lyr = _doc->layers[_lyr = l]; + if (_x >= lyr->width) _x = lyr->width - 1; + if (_y >= lyr->height) _y = lyr->height - 1; +} + @@ -0,0 +1,98 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + + +#ifndef _btco_aewan_psd_h +#define _btco_aewan_psd_h + +#include "bores/bores.h" + +#include "version.h" + +/* selection modes: */ +#define SM_NONE 0 /* no selection */ +#define SM_SELECT 1 /* grow/shrink selection box */ +#define SM_FLOAT 2 /* paste mode: clipboard floats around screen */ + +struct _Document; + +/* global program state data declarations */ +extern struct _Document *_doc; + /* the current document. Must ALWAYS be non-null. */ + +extern char *_filename; /* the name of the file from which it was loaded; + * NULL if new file */ + +extern int _lyr; /* currently active layer. This is a valid layer + * index if and only if _doc->layer_count >= 1 */ +extern int _x, _y; /* cursor position (logical coordinates) */ +extern int _svx, _svy;/* "smallest visible x" and "smallest visible y" + * These are used in order to convert logical coordinates + * to screen coordinates. Logical coordinates _svx,_svy + * are mapped to screen (0,0). */ +extern int _fg, _bg; /* currently selected foreground and background colors */ +extern int _selmode; /* selection mode: SM_NONE, SM_SELECT, SM_FLOAT */ +extern int _ax, _ay; /* the anchor-point (i.e. where the selection begins). + * Valid only if _selmode == true */ +extern bool _insmode;/* whether insert mode is on. In insert mode, typing + * a character on a line shifts the other characters + * to the right. */ + +extern bool _lgmode; /* line graphics mode. When this mode is active, + certain keystrokes produce different characters */ + +extern bool _compmode; /* composite mode. In this mode, all layers will + * be visible. */ + +extern struct _Layer *_clipboard; + /* clipboard layer. NULL if nothing in clipboard. */ + +/* --- functions that operate on psd ------------------------------------- */ + +/* Zeroes program state data */ +void zero_state(void); + +/* Convenience function that returns whether document is empty or not */ +bool doc_empty(void); + +/* Obtains normalized selection coordinates. Returned coordinates x0, y0, + * x1, y1 represent the selection rectangle, with the property that + * x0 <= x1 and y0 <= y1 */ +void get_norm_sel(int *x0, int *y0, int *x1, int *y1); + +/* Switches active layer to l. Does appropriate coordinate bound + * checking and other administrative tasks */ +void switch_to_layer(int l); + +#endif + diff --git a/python/NOTICE b/python/NOTICE new file mode 100644 index 0000000..f5e4b00 --- /dev/null +++ b/python/NOTICE @@ -0,0 +1,6 @@ +The python module for loading AES files is +out of date, since the AES format is now +obsolete. + +Hey, maybe YOU could code it! + diff --git a/python/aewan.py b/python/aewan.py new file mode 100644 index 0000000..e5a9962 --- /dev/null +++ b/python/aewan.py @@ -0,0 +1,185 @@ +# Copyright (c) 2004 Bruno T. C. de Oliveira +# +# LICENSE INFORMATION: +# 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 +# Copyright (c) 2002 Bruno T. C. de Oliveira +# +# INFORMAÇÕES DE LICENÇA: +# Este programa é um software de livre distribuição; você pode +# redistribuí-lo e/ou modificá-lo sob os termos da GNU General +# Public License, conforme publicado pela Free Software Foundation, +# pela versão 2 da licença ou qualquer versão posterior. +# +# Este programa é distribuído na esperança de que ele será útil +# aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +# a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +# QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +# License para obter mais detalhes (uma cópia acompanha este +# programa, armazenada no arquivo COPYING). + +import sys, os, string +import gzip +import curses + +class AeError(Exception): + def __init__(self, arg): + Exception.__init__(self, arg) + +class AeDoc: + """ + Represents an aewan document loaded from a file. + Attributes: + + layers[] - list of layers (AeLayer objects) + """ + def __init__(self, file): + """ + Creates a new aewan document object by loading it from the + specified file. The file must be in AES format, as generated + by the ae2aes conversion utility. The file may be gzip-compressed. + + If there is a format-related error while loading the document, + raises an AeError. If there is an I/O related error, raises an IOError. + """ + self.layers = [] + + f = gzip.open(file, 'r') + _read_marker(f, "AES v1.0") + _read_marker(f, "begin document") + + layercount = _read_field_int(f, "layer-count") + for i in range(layercount): + self.layers.append(AeLayer(f)) + + _read_marker(f, "end document") + + +class AeLayer: + """ + Represents each of the layers in an aewan document. Attributes: + + name + width + height + visible - 1 if layer is marked as visible, 0 otherwise + transparent - 1 if layer is marked as transparent, 0 otherwise + + char[height][width] - the character at each position in the layer + attr[height][width] - the attribute of each position in the layer + + Please note that the char and attr matrices are addressed + with indexes [y][x], NOT the more intuitive [x][y]. + """ + def __init__(self, f): + """ + Initializes a new layer by loading its data from file object f. + Raises an AeError if a format-related error occurs, or an IOError + if an i/o-related error occurs. + """ + _read_marker(f, "begin layer") + self.name = _read_field(f, "name") + self.width = _read_field_int(f, "width") + self.height = _read_field_int(f, "height") + self.visible = _read_field_int(f, "visible") + self.transparent = _read_field_int(f, "transparent") + _read_marker(f, "begin canvas") + + self.char = [] + self.attr = [] + for y in range(self.height): + a = string.split(string.strip(f.readline())) + if len(a) != self.width * 2: + raise AeError("Canvas line with insufficient cells:\n" + a) + + char_row = [] + attr_row = [] + for x in range(self.width): + try: + char_row.append(int(a[x * 2], 16)) + attr_row.append(int(a[x * 2 + 1], 16)) + except ValueError: + raise AeError("Error: map cell x=%d, y=%d has invalid data\n" + "(not a hexadecimal number)" % (x,y)) + + self.char.append(char_row) + self.attr.append(attr_row) + + _read_marker(f, "end canvas") + _read_marker(f, "end layer") + + def render(self, wnd, dest_x, dest_y, dest_w, dest_h, src_x, src_y, \ + setattr_cb): + """ + Render the contents of this layer using curses. The image will + be rendered on the curses window identified by wnd, and will + be confined to the rectangle defined by the dest_* arguments. + The image will be translated in such a way that the left-top + corner of the destination rectangle will show the layer cell + whose coordinates are src_x, src_y. + + In order to set curses attributes for each cell, this function + will call setattr_cb passing it the window and the attribute as + parameters. + """ + for y in range(dest_h): + wnd.move(y + dest_y, dest_x) + for x in range(dest_w): + sx = x + src_x + sy = y + src_y + if 0 <= sx < self.width and 0 <= sy < self.height: + ch = self.char[sy][sx] + if 0 <= ch < 32: ch = 32 # don't display control chars + # FIXME: this doesn't display special line-graphics + # characters. Ideally, we should convert special + # characters into the appropriate ACS_* characters + # at this point. + + at = self.attr[sy][sx] + else: + ch = 0x20 + at = 0x70 + + setattr_cb(wnd, at) + wnd.addch(chr(ch)) + + +# ------------------------------------------------------------------------ +def _read_marker(f, str): + line = string.strip(f.readline()) + if line == str: return + raise AeError("Incorrectly formatted AES document.\n" + "Expected marker: '%s'\nBut found: '%s'\n" % (str,line)) + +def _read_field(f, fieldname): + line = string.strip(f.readline()) + a = string.split(line, maxsplit=1) + + if len(a) != 2: + raise AeError("Incorrect field syntax in AES document:\n%s\n" % line) + + if a[0] != fieldname: + raise AeError("AES field name mismatch.\nExpected: '%s'\nFound: '%s'" \ + % (fieldname, a[0])) + + return a[1] + +def _read_field_int(f, fieldname): + x = _read_field(f, fieldname); + try: + return int(x) + except ValueError: + raise AeError("AES field type mismatch: expected an integer\n" + "Field name: '%s'\nValue: '%s'" % (fieldname, x)) + diff --git a/python/test.py b/python/test.py new file mode 100644 index 0000000..a7f618d --- /dev/null +++ b/python/test.py @@ -0,0 +1,54 @@ +from aewan import AeDoc, AeLayer +import curses +import sys + +def setattr(wnd, at): + at = int(at) + fg = at >> 4 + bg = at & 0x0f + bold = 0 + blink = 0 + + if fg > 7: + bold = 1 + fg = fg - 8 + + if bg > 7: + blink = 1 + bg = bg - 8 + + if fg == 7 and bg == 0: wnd.attrset(curses.A_NORMAL) + elif fg == 0 and bg == 0: wnd.attrset(curses.color_pair(7)) + else: wnd.attrset(curses.color_pair(bg * 8 + fg)) + + if bold: wnd.attron(curses.A_BOLD) + if blink: wnd.attron(curses.A_BLINK) + +stdscr = curses.initscr() +curses.noecho() +curses.start_color() + +for bg in range(8): + for fg in range(8): + if bg > 0 or fg > 0: curses.init_pair(bg*8 + fg, fg, bg) + +curses.init_pair(7, 0, 0) + + +stdscr.clear() + +d = AeDoc("/tmp/ut.aes.gz") + +sx = sy = 0 +while 1: + d.layers[0].render(stdscr, 20, 8, 40, 10, sx, sy, setattr) + stdscr.refresh() + ch = chr(stdscr.getch()) + if ch == 'h': sx = sx - 1 + elif ch == 'l': sx = sx + 1 + elif ch == 'k': sy = sy - 1 + elif ch == 'j': sy = sy + 1 + elif ch == 'q': + curses.endwin() + sys.exit(0) + @@ -0,0 +1,141 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "bores/bores.h" +#include <ncurses.h> +#include <string.h> +#include <stdlib.h> + +#include "ui.h" + +int ui_cancel; /* global cancel flag */ + +/* clears bottom line of screen and puts cursor at the beginning of that line. + * Also lowers the global ui_cancel flag. */ +static void ui_prepare_ex(int fg, int bg) { + int w = kurses_width(); + kurses_move(0, kurses_height() - 1); + kurses_color(fg, bg); + while (w--) addch(' '); + kurses_move(0, kurses_height() - 1); + ui_cancel = 0; +} + +static void ui_prepare(void) { + ui_prepare_ex(15, 4); +} + + +int ui_ask_i(const char *prompt, int def, int min, int max) { + static char buf[32]; int ans; + + do { + ui_prepare(); + printw("%s [%d]: ", prompt, def); + if (!kurses_line_input(buf, 32)) return (ui_cancel = -1); + if (!*buf) return def; /* user just pressed ENTER, so use default */ + ans = atoi(buf); + } while (!(ans >= min && ans <= max)); + + return ans; +} + +char *ui_ask_s(const char *prompt, const char *def) { + static char buf[256]; + ui_prepare(); + + if (def) printw("%s [%s]: ", prompt, def); + else printw("%s: ", prompt); + + if (!kurses_line_input(buf, 256)) { ui_cancel = -1; return NULL; } + + /* if user didn't type anything and there is a default, return default; + * otherwise just return whatever it is the user typed (even if it's an + * empty string) */ + if (!*buf && def) return strdup(def); + else return strdup(buf); +} + +int ui_ask_color(const char *prompt) { + int i; + static char hexdigit[] = "0123456789abcdef"; + ui_prepare(); + printw("%s ", prompt); + + /* print the colors */ + for (i = 0; i <= 15; i++) { + kurses_color(i, i ? 0 : 7); + printw(" %c ", hexdigit[i]); + } + + kurses_color(0, 7); + printw(": "); + + while (1) { + int ch, color_code; + ch = getch(); color_code = (ch >= 'a' && ch <= 'f') ? ch - 'a' + 10 : + (ch >= 'A' && ch <= 'F') ? ch - 'A' + 10 : + ch - '0'; + if (ch == 27 || ch == 3 || ch == 7) return (ui_cancel = -1); + if (color_code >= 0 && color_code <= 15) return color_code; + } +} + +int ui_ask_yn(const char *prompt, int defyes) { + ui_prepare(); + printw("%s [%s] ", prompt, defyes ? "Yes" : "No"); + while (1) { + int ch = getch(); + switch (ch) { + case 10: return defyes; + + case 'y': case 'Y': return 1; + case 'n': case 'N': return 0; + + case 27: + case 3: + case 7: return (ui_cancel = -1); + } + } +} + +void ui_message(const char *msg, int error) { + if (error) + ui_prepare_ex(15, 1); + else + ui_prepare(); + + addstr(msg); + getch(); +} + @@ -0,0 +1,80 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + + +#ifndef _btco_aewan_ui_h +#define _btco_aewan_ui_h + +#include <stdbool.h> +#include "bores/bores.h" + +extern int ui_cancel; /* raised if the user cancels input in any of the + * ui_* functions. */ + +/* Asks the user to input an integer number. Presents the given prompt. + * If the user just presses ENTER, returns <def>. Otherwise, returns + * the user's input if min <= input <= max. If the user input is not + * in the [min,max] interval, keeps asking again until the user inputs + * a valid value. If the user presses ESC, or Ctrl+C or any such thing, + * the return value is undefined and the global flag ui_cancel is raised. + * The ui_cancel flag is lowered at the beginning of the operation, so + * there is no need to lower it before calling this function. */ +int ui_ask_i(const char *prompt, int def, int min, int max); + +/* Asks the user to input a string. Behavior is similar to ui_ask_i. + * The returned string is dynamically allocated and should be free()'d + * by the caller. Even if the default value is returned, the return value + * is an strdup()'ed value, so it should be free()'d by caller even in + * that case. */ +char *ui_ask_s(const char *prompt, const char *def); + +/* Asks the user a color. Similar to the other ui_ask_ functions. + * Returns the selected color code, between 0 and 15 inclusive. */ +int ui_ask_color(const char *prompt); + +/* Asks a yes/no question. If <defyes>, the default is yes, otherwise + * the default is no. Returns whether the user chose yes or not. + * If the user cancels, ui_cancel is set to true and return value + * is undefined. */ +int ui_ask_yn(const char *prompt, int defyes); + +/* Presents a message to the user and awaits for a keypress. + * If <level> is UIMSG_ERROR, message will be shown as an error condition + * (i.e. in red and possibly accompanied by a beep). */ +void ui_message(const char *msg, int level); + #define UIMSG_INFORM 0 + #define UIMSG_ERROR 1 + + +#endif + diff --git a/version.h b/version.h new file mode 100644 index 0000000..ecb252a --- /dev/null +++ b/version.h @@ -0,0 +1,41 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewan_version_h +#define _btco_aewan_version_h + +#define AEWAN_PROGRAM_VERSION "1.0.01" +#define AEWAN_PROGRAM_VERSION_NAME "novae" + +#endif + diff --git a/vlayer.c b/vlayer.c new file mode 100644 index 0000000..02689d2 --- /dev/null +++ b/vlayer.c @@ -0,0 +1,48 @@ +#include "bores/bores.h" +#include "vlayer.h" + +/* callback that returns a cell from a given layer */ +static void _get_cell_LYR(Cell *r_cell, int x, int y, void *ud) { + Layer *l = (Layer*) ud; + *r_cell = l->cells[x][y]; +} + +/* callback that returns a cell from a document composite */ +static void _get_cell_COMPOSITE(Cell *r_cell, int x, int y, void *ud) { + Document *doc = (Document*) doc; + *r_cell = document_calc_effective_cell(doc, x, y); +} + +VirtualLayer *vlayer_create(int width, int height, vlayer_get_cell_t get_cell, + void *user_data){ + VirtualLayer *vl = zalloc(sizeof(VirtualLayer)); + vl->width = width; + vl->height = height; + vl->get_cell = get_cell; + vl->user_data = user_data; + return vl; +} + +VirtualLayer *vlayer_create_from_layer(Layer *l) { + return vlayer_create(l->width, l->height, _get_cell_LYR, (void*) l); +} + +VirtualLayer *vlayer_create_from_composite(Document *doc) { + if (doc->layer_count <= 0) return NULL; + return vlayer_create(doc->layers[0]->width, doc->layers[0]->height, + _get_cell_COMPOSITE, (void*) doc); +} + +void vlayer_destroy(VirtualLayer *vl) { + if (!vl) return; + sfree(vl); +} + +void vlayer_get_cell(VirtualLayer *vl, Cell *r_cell, int x, int y) { + if (x < 0 || x >= vl->width || y < 0 || y >= vl->height) { + r_cell->ch = ' '; + r_cell->attr = 0x70; + } + else vl->get_cell(r_cell, x, y, vl->user_data); +} + diff --git a/vlayer.h b/vlayer.h new file mode 100644 index 0000000..36f6b16 --- /dev/null +++ b/vlayer.h @@ -0,0 +1,80 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewan_vlayer_h +#define _btco_aewan_vlayer_h + +#include "document.h" + +typedef void (*vlayer_get_cell_t)(Cell *r_cell, int x, int y, void *ud); + +/* A virtual layer. A virtual layer is a structure used when one wishes + * to represent a layer abstractly, where a callback function is responsible + * for returning the content of any given cell upon request. The layer + * does not exist physically (or perhaps it does, but we don't know), + * and we only rely on the function to retrieve the virtual layer's content. + * It is primarily used for export and display purposes where one wishes + * to have a unified interface to deal with actual layers, composites + * and all such things that are implemented differently but have the + * same "outside appearance". */ +typedef struct VirtualLayer_ { + int width, height; /* dimensions of the virtual layer */ + vlayer_get_cell_t get_cell; /* the callback that + * retrieves what is at cell (x,y) and records that + * in the structure pointed by r_cell */ + void *user_data; /* arbitrary data passed as the ud parameter of get_cell */ +} VirtualLayer; + +/* Creates a virtual layer with the given dimensions, callback function, + * and user data */ +VirtualLayer *vlayer_create(int width, int height, vlayer_get_cell_t get_cell, + void *user_data); + +/* Creates a virtual layer based on the physical layer l. You MUST NOT DESTROY + * the layer l while the virtual layer exists. */ +VirtualLayer *vlayer_create_from_layer(Layer *l); + +/* Creates a virtual layer formed by making a composite from all the layers + * of the given document. You MUST NOT DESTROY the document while the + * virtual layer exists. */ +VirtualLayer *vlayer_create_from_composite(Document *doc); + +/* Destroys a virtual layer previously created with one of the creator + * functions */ +void vlayer_destroy(VirtualLayer *vl); + +/* Gets a cell from a virtual layer. The cell is filled in r_cell. */ +void vlayer_get_cell(VirtualLayer *vl, Cell *r_cell, int x, int y); + +#endif + diff --git a/welcomedlg.c b/welcomedlg.c new file mode 100644 index 0000000..708f631 --- /dev/null +++ b/welcomedlg.c @@ -0,0 +1,130 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#include "bores/bores.h" +#include <ncurses.h> + +#include "welcomedlg.h" +#include "psd.h" + +#define LOGO_WIDTH 11 +#define LOGO_HEIGHT 5 + +static char* logo[] = { + "79 ", + "|| ", + "46799 97979", + "||43|||||||", + "311-1231231", + NULL +}; + +static int logo_colors[LOGO_HEIGHT] = { 4, 6, 7, 6, 4 }; + +void show_welcome_dlg(void) { + int x0, y0, x, y, ch, *clr; + char **p, *q; + int acschars[10] = { + ACS_CKBOARD, /* 0 */ + ACS_LLCORNER, /* 1 */ + ACS_BTEE, /* 2 */ + ACS_LRCORNER, /* 3 */ + ACS_LTEE, /* 4 */ + ACS_PLUS, /* 5 */ + ACS_RTEE, /* 6 */ + ACS_ULCORNER, /* 7 */ + ACS_TTEE, /* 8 */ + ACS_URCORNER /* 9 */ + }; + + kurses_color(4, 0); + draw_centered_window(46, 18, "Welcome to AEWAN", &x0, &y0); + y = y0 + 1; + + /* draw logo */ + for (p = logo, clr = logo_colors; *p; p++, clr++) { + kurses_color(*clr, 0); + kurses_move(x0, y++); + for (q = *p; *q; q++) { + if (*q >= '0' && *q <= '9') ch = acschars[*q - '0']; + else if (*q == '-') ch = ACS_HLINE; + else if (*q == '|') ch = ACS_VLINE; + else ch = ' '; + addch(ch); + } + } + + /* draw program name next to logo */ + x = x0 + LOGO_WIDTH + 2; + y = y0 + 1; + + kurses_move(x, y++); + kurses_color(4+8, 0); + addstr("AEWAN ascii art editor"); + + kurses_move(x, y++); + kurses_color(7, 0); + addstr("Copyright (c) 2003"); + + kurses_move(x, y++); + addstr("Bruno T. C. de Oliveira"); + + kurses_move(x, y++); + addstr("All rights reserved."); + + y+=2; x = x0 + 1; + kurses_move(x, y++); + kurses_color(4+8, 0); + addstr("Program version: "); + kurses_color(7, 0); + addstr(AEWAN_PROGRAM_VERSION " (" AEWAN_PROGRAM_VERSION_NAME ")"); + + y++; + kurses_move(x, y++); + addstr("This program is licensed under the GNU"); + + kurses_move(x, y++); + addstr("General Public License. Please refer to"); + + kurses_move(x, y++); + addstr("the COPYING file for more information."); + + y++; + kurses_move(x, y++); + addstr("Press RETURN to continue. When in the"); + kurses_move(x, y++); + addstr("program, press <F1> to display a menu."); + + getch(); +} + diff --git a/welcomedlg.h b/welcomedlg.h new file mode 100644 index 0000000..c257978 --- /dev/null +++ b/welcomedlg.h @@ -0,0 +1,42 @@ +/* +Copyright (c) 2003 Bruno T. C. de Oliveira + +LICENSE INFORMATION: +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 +Copyright (c) 2002 Bruno T. C. de Oliveira + +INFORMAÇÕES DE LICENÇA: +Este programa é um software de livre distribuição; você pode +redistribuí-lo e/ou modificá-lo sob os termos da GNU General +Public License, conforme publicado pela Free Software Foundation, +pela versão 2 da licença ou qualquer versão posterior. + +Este programa é distribuído na esperança de que ele será útil +aos seus usuários, porém, SEM QUAISQUER GARANTIAS; sem sequer +a garantia implícita de COMERCIABILIDADE ou DE ADEQUAÇÃO A +QUALQUER FINALIDADE ESPECÍFICA. Consulte a GNU General Public +License para obter mais detalhes (uma cópia acompanha este +programa, armazenada no arquivo COPYING). +*/ + +#ifndef _btco_aewan_welcomedlg_h +#define _btco_aewan_welcomedlg_h + +/* invokes the welcome dialog, that shows the program name, version, + * copyright information and such. Does not restore screen. */ +void show_welcome_dlg(void); + +#endif + |