Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial import of ncurses-ruby-1.1 from BerliOS.

  • Loading branch information...
commit dfba26ad9ca0dee0262b483202715040c865ced6 0 parents
@eclubb eclubb authored
515 COPYING
@@ -0,0 +1,515 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 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.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+ When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+^L
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+^L
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, 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 library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete 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 distribute a copy of this License along with the
+Library.
+
+ 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 Library or any portion
+of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+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 Library, 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 Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+^L
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you 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.
+
+ If distribution of 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 satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+^L
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be 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.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+^L
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library 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.
+
+ 9. 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 Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+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 with
+this License.
+^L
+ 11. 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 Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library 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 Library.
+
+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.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library 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.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser 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 Library
+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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+^L
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+^L
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+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 library's name and a brief idea of what it
+does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; 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.
+
+You should also get your employer (if you work as a programmer) or
+your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James
+Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
53 Changes
@@ -0,0 +1,53 @@
+ncurses-ruby-1.1
+* Bugfixes by T. Sutherland in _tracef and _tracedump.
+
+ncurses-ruby-1.0
+* Mousemask bugfix from P.Duncan.
+* Solved timing problems that affected visual smoothness of reactions
+ to user input
+* Each SCREEN got back its own "halfdelay" and "cbreak" settings
+
+ncurses-ruby-0.9.2
+ * Preventing getch and wgetch functions from blocking other ruby threads.
+ * Previously ncurses-ruby installed two files named "ncurses.rb" and
+ "ncurses.so". The "ncurses.so" is now renamed to "ncurses_bin.so"
+ to prevent "require 'ncurses'" from accidentally loading only the
+ binary file in case that this is found first in ruby's load path.
+ * Reintroduced ability to "include" Ncurses functions:
+ Use "include Ncurses::Namespace" for that. This is implemented via
+ method_missing, so that ncurses functions (some of which have very
+ common names) will not hide other functions defined in the extended
+ scope. (Any existing method_missing function is properly aliased and
+ called after an unsuccessful lookup.)
+
+ncurses-ruby-0.9.1
+ * Bugfix in *in*str functions (Hiroshi Sainohira)
+ * Fix linking error on Mac OS X and some other platforms (Andreas Schwarz)
+
+ncurses-ruby-0.9:
+ * Forms wrapper contributed by Simon Kaczor
+ * ncurses-ruby now also works with ncurses-4.2
+ (an old release from 1998, needed for Zaurus-port)
+ * First binary package for Sharp Zaurus (arm-linux)
+
+ncurses-ruby-0.8:
+ * Bugfix: Calls into the ncurses library prior to calling
+ Ncurses::initscr or Ncurses::newterm had previously crashed
+ the Ruby interpreter.
+ Fixed by delaying the binding of most Ncurses functions
+ until after Ncurses::initscr or Ncurses::newterm have been
+ called.
+ * Replaced module functions with singleton functions. This
+ means that
+ include Ncurses
+ initscr
+ is no longer possible. Instead, use
+ Ncurses.initscr
+ Reasons: - Consistency. The shortcut has never been possible
+ with all ncurses functions.
+ - Namespace pollution. Some ncurses functions have
+ too common names.
+
+ncurses-ruby-0.7.2:
+ * reintroduced Ncurses::pechochar and Ncurses::redrawwin in the ncurses build.
+ These had been removed by mistake because they did not work with PDCurses.
26 MANIFEST
@@ -0,0 +1,26 @@
+Changes
+COPYING
+MANIFEST
+README
+THANKS
+TODO
+VERSION
+examples/example.rb
+examples/form.rb
+examples/form2.rb
+examples/hello_ncurses.rb
+examples/LICENSES_for_examples
+examples/rain.rb
+examples/tclock.rb
+examples/read_line.rb
+examples/test_scanw.rb
+extconf.rb
+form_wrap.c
+form_wrap.h
+make_dist.rb
+ncurses_wrap.c
+ncurses_wrap.h
+lib/ncurses.rb
+panel_wrap.c
+panel_wrap.h
+
318 README
@@ -0,0 +1,318 @@
+$Id: README,v 1.14 2006/06/19 09:43:58 t-peters Exp $
+------------------------------------------------------------------------
+This directory contains a ruby module for accessing the FSF's ncurses
+library.
+(C) 2002, 2003, 2004 Tobias Peters <t-peters@users.berlios.de>
+(C) 2004 Simon Kaczor <skaczor@cox.net>
+(C) 2005 2006 Tobias Herzke <t-peters@users.berlios.de>
+
+This module is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This module 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+------------------------------------------------------------------------
+
+Overview
+========
+
+This README file explains how to use the ncurses ruby interface. It is
+assumed that the reader has a rough understanding of what the ncurses
+library is and how to use it from the C language. It then goes into
+detail, explaining what is covered by the ruby interface, and the
+rules that were followed in translating the C interface into a ruby
+interface.
+
+This ncurses interface provides access to the functions, macros,
+global variables and constants of the ncurses library. These are
+mapped to a Ruby Module named "Ncurses": Functions and external
+variables are implemented as singleton functions of the Module
+Ncurses.
+
+This README is organized into the following parts:
+- Overview
+- Installation and Usage
+- External Variables
+- Constants
+- Functions (and their Interfaces)
+- Module / Class Hierarchie
+- The WINDOW class
+- The panel Library
+- The form Library
+- Ncurses and Ruby Threads
+- Example programs
+- Applications using ncurses-ruby
+
+General Ncurses Literature
+--------------------------
+
+If you don't know how to use ncurses from C, then please read an
+introduction to ncurses before continuing with this README. Eric
+Raymond has written an introduction that should be part of the ncurses
+development package installed on your computer.
+If you'd like a gentler introduction, then you have two options:
+(1) there is a part of a chapter in "The Linux Programmer's Guide" dealing
+ with ncurses, available from www.tldp.org. It is quite old by now,
+ but the ncurses interface has not changed since then, regarding the
+ scope of covered functions, so it is still a very good read.
+(2) There is also an up-to-date "NCURSES-Programming-HOWTO" in the HOWTO
+ collection of the Linux Documentation Project, also available at
+ www.tldp.org, which is worth a read.
+
+You will also appreciate the extensive man-pages of ncurses, a useful
+reference while coding.
+
+
+Installation and Usage
+======================
+
+ruby extconf.rb
+make
+make install
+
+In your programs:
+require "ncurses.rb"
+
+If your programs use the scanw functions (most unlikely) you will have to
+install the scanf library for ruby (http://www.rubyhacker.com/code/scanf).
+
+Most ncurses functions are only available after either Ncurses.initscr or
+Ncurses.newterm has returned successfully.
+
+External Variables
+==================
+
+External variables are accessed read-only, by module functions taking no
+arguments. They are spelled exactly like their C counterparts. Sometimes, this
+leads to module functions beginning with an uppercase letter (e.g.
+Ncurses.LINES).
+
+One of these external variables, ESCDELAY, is also settable with a ruby method
+(Ncurses.ESCDELAY=).
+
+Another external variable, Ncurses.RESIZEDELAY is introduced by this wrapper.
+It contains the maximum milliseconds delay with which terminal resizesings are
+recognized.
+
+Constants
+=========
+(static C Preprocessor macros)
+
+Constants are implemented as module constants in the Ncurses module, if
+possible. Ruby constants can not start with an underscore, so these constants
+have been renamed (they lost the leading underscore). There are,however,
+module functions with the same name as these constants, that also return
+the constant's value, when invoked (e.g. "Ncurses._ENDLINE" returns the value
+of the constant "Ncurses::ENDLINE", which has the same value as the C constant
+"_ENDLINE").
+
+Note: The ncurses macros starting with ACS_ are not constants, their value
+depends on the terminal in use. Nevertheless, they are implemented as
+constants of the Ncurses module, but since they depend on the terminal, they
+are not initialized before initscr() has been called. If you need more than
+one terminal in a single program, you can access the ACS_ values through member
+functions of class SCREEN.
+
+
+Functions (and their Interfaces)
+================================
+
+Functions (also those only implemented by macros in C) can be accessed
+as module functions of the Module Ncurses. They take exactly the same
+arguments as their C counterparts. Some of the C functions return additional
+arguments through pointer arguments. These are implemented as follows:
+
+
+Functions expecting pointers to integer types
+---------------------------------------------
+
+When the C-function expects a pointer to int, short, chtype, or attr_type,
+You should use a variable containing an empty array as the argument to the ruby
+function. This is because ruby passes these types (ints) "by value" instead of
+"by reference"; but arrays are passed by reference, so that you can see the
+changes to them.
+Attention: some macro-only functions like getsyx accept variables of type int,
+but, being macros, they write values to their arguments. Thus, they also need
+empty array arguments when called from ruby.
+Example:
+ color_pair_number = 4
+ foreground_color = []
+ background_color = []
+ if (Ncurses.pair_content(color_pair_number, foreground_color,
+ background_color) != Ncurses::ERR)
+ "color pair number #{color_pair_number} contains color number " +
+ "#{foreground_color[0]} as the foreground color, and color " +
+ "number #{background_color[0]} as the background color")
+ end
+
+There are 2 functions that read a value from the location pointed to by a
+pointer to int, and store another value at those locations. These functions are
+mouse_trafo and wmouse_trafo. When calling these functions, you have to provide
+2 arrays, each filled with exacly one Integer. The values contained in these
+arrays will then be changed by the ruby module function.
+
+
+Functions expecting (non-const) pointers to char
+------------------------------------------------
+
+When the C-function expects a pointer to char, you should use a variable
+containing an empty string as the argument to the ruby function.
+Example:
+ line2 = ""
+ if (Ncurses.mvwinnstr(Ncurses.stdscr, y=2, x=0, line2,
+ Ncurses.getmaxx(Ncurses.stdscr)) == Ncurses::ERR)
+ raise "could not scan 3rd line"
+ else
+ Ncurses.beep if line2.index("|")
+ end
+The string that the C function would store at the pointer-to-char location
+will be appended to the given string.
+
+Functions expecting const pointers to char do not modify the string they
+receive, you can pass any string to them.
+
+
+
+Functions expecting pointers to structs
+---------------------------------------------------
+
+When the C-function expects a pointer to WINDOW, SCREEN, MEVENT,
+PANEL, FORM, FIELD or FIELDTYPE then simply pass it the corresponding,
+already existing ruby object.
+
+
+scanf style functions expecting various pointers
+---------------------------------------------------
+
+namely scanw, mvscanw, wscanw, mvwscanw. Use an array after the format string.
+The scanned values will be placed there. Remember, you need scanf for ruby
+installed for these functions to work.
+
+Module / Class Hierarchie
+=========================
+
+module Ncurses
+ class WINDOW; end
+ class SCREEN; end
+ class MEVENT; end
+ module Panel
+ class PANEL; end
+ end
+ module Form
+ class FORM; end
+ class FIELD; end
+ class FIELDTYPE; end
+ end
+end
+
+
+The WINDOW class
+================
+
+The class WINDOW implements method_missing and tries to map invoked
+methods to Ncurses module functions using a simple heuristic:
+
+If the method name starts with "mv", it looks for a Ncurses module
+function that starts with "mvw", and if it exists, adds itself to the
+argument list and calls this function.
+If no such module function exists, or the name of the invoked method
+does not start with "mv", it looks if there is a module function with
+the name "w" + methodname, and if it exists, adds itself again to the
+argument list and calls this function.
+If this module function did not exist either, then, as a last step, it
+invokes a module function with the same name as the method, adding
+itself to the argument list.
+
+Example: If you invoke win.mvaddch(y,x,ch) on an Ncurses::WINDOW
+object, it will delegate the method call to
+Ncurses.mvwaddch(win,y,x,ch).
+
+Other examples:
+
+ win.printw("hello") => Ncurses.wprintw(win, "hello")
+
+ win.getmaxyx(y=[],
+ x=[]) => Ncurses.getmaxyx(win,y,x)
+
+ win.delwin() => Ncurses.delwin(win) # win cannot be used
+ # after this call
+
+
+The panel Library
+=================
+
+The panel library has also been wrapped. All panel functions are
+implemented as module functions of the module Ncurses::Panel.
+
+Most of these functions are also implemented as methods of class
+Ncurses::Panel::PANEL, once with their original name and once with the
+subword "panel" and an adjacent underscore removed.
+
+The form Library
+================
+
+The form library was wrapped inside the Ncurses:Form module. All
+form functions are implemented as module functions on the module
+Ncurses::Form. In addition, all function for which the first
+parameter is one of the objects are also implemented as an instance
+method of the respective class. For example, instead of calling
+post_form(form), you can use form.post_form().
+
+Three objects are defined in the Ncurses:Form module:
+ 1. FORM
+ 2. FIELD
+ 3. FIELDTYPE
+
+They are wrapping actual ncurses pointers and should be use whenever a
+pointer to one of these types is expected in function calls.
+
+All form constants are defined in the module as Ruby constants with
+the same name as the curses constants.
+
+Constructors for FORM, FIELD and FIELDTYPE objects are also provided,
+and they expect the same parameters as new_form, new_field and
+new_fieldtype curses functions.
+
+Field validation is implemented using Ruby Proc objects. You must
+provide a Ruby block whenever a function pointer is expected in curses
+function arguments. See the example form2.rb for more details.
+
+The functions form_userptr and field_userptr are not supported. Use
+form.user_object and field.user_object to store Ruby objects instead.
+
+Ncurses and Ruby Threads
+========================
+
+The ncurses library is not thread-safe. Your application must properly
+serialize calls into ncurses.
+
+Prior to release 0.9.2, the getch and wgetch calls used to block the
+complete ruby interpreter, all threads. This is no longer so. Other
+threads should now continue to run during blocking calls to getch and
+wgetch.
+
+Example programs
+================
+
+Directory "examples" contains a few example programs demonstrating how
+to use the ncurses library with ruby. Be sure to read the file
+"examples/LICENSES_for_examples".
+
+
+Applications using ncurses-ruby
+===============================
+
+aeditor (v. 0.x) - Pair programming editor, http://metaeditor.sourceforge.net/
+raggle - RSS aggregator, http://www.raggle.org/about/
+ruvi - Editor, http://ruvi.rubyforge.org/
+diakonos - Editor, http://purepistos.net/diakonos/
+tpp - text-based presentation program, http://synflood.at/tpp/
+yapo - ports overview for CRUX linux distribution, http://jue.li/crux/yapo/
14 THANKS
@@ -0,0 +1,14 @@
+$Id: THANKS,v 1.8 2006/06/19 09:39:40 t-peters Exp $
+
+A list of people that helped me with ncurses-ruby
+
+Akinori MUSHA (knu at idaemons dot org)
+Jan Becvar (jan dot becvar at solnet dot cz)
+Juergen Daubert
+Doug Kearns
+Simon Kaczor (skaczor at cox dut net)
+Hiroshi Sainohira
+Andreas Schwarz
+Simon Strandgaard
+Paul Duncan
+Tim Sutherland
15 TODO
@@ -0,0 +1,15 @@
+$Id: TODO,v 1.6 2003/03/22 22:55:27 t-peters Exp $
+
+This is the complete list of functions present in ncurses that have not yet
+been wrapped by ncurses-ruby:
+
+terminfo functions: setupterm, setterm, set_curterm, del_curterm, restartterm,
+ tparm, tputs, vidputs
+
+termcap fuctions: tgetent, tgetflag, tgetnum, tgetstr, tgoto
+
+ncurses
+kernel functions: ripoffline
+
+No sense in
+wrapping these: vw_printw, vwprintw, vwscanw
1  VERSION
@@ -0,0 +1 @@
+1.1
26 examples/LICENSES_for_examples
@@ -0,0 +1,26 @@
+$Id: LICENSES_for_examples,v 1.6 2004/05/13 21:55:17 t-peters Exp $
+
+Ideally, an example program on how to use a library should be in the public
+domain.
+
+Some of the example programs contained in this dircectory have not been put in
+the public domain, however.
+
+The reason is because I did not write all programs completely myself -- I've
+adapted the following example programs from ncurses programs in other
+programming languages, or I have included example programs contributed by
+other authors, and I have to respect their original licenses:
+- rain.rb is adapted from rain.c from the ncurses library distribution.
+- example.rb is adapted from an example program for the python ncurses binding.
+- tclock.rb is adapted from tclock.c from the ncurses library distribution.
+- form.rb anf form2.rb have been written by Simon Kaczor, who has adapted them
+ from sample code from the NCurses Programming HOWTO.
+
+See the comments in the source files for restrictions imposed on copying and
+modifying these.
+
+That said, I suppose you may still look at their source code and learn how
+ncurses programs generally work, as long as you dont start your own programs
+by loading the example program into your editor and modify it to your needs.
+
+Tobias Peters <t-peters@users.berlios.de>
129 examples/example.rb
@@ -0,0 +1,129 @@
+#!/usr/bin/env ruby
+
+# $Id: example.rb,v 1.4 2002/03/04 13:24:29 t-peters Exp $
+
+# This file provides an example for the usage of the ncurses-ruby module.
+# Copyright (C) 2002 Tobias Peters <t-peters@users.berlios.de>
+#
+# The following license applys only to this file. It is less restrictive
+# than the license for the rest of the ncurses-ruby distribution.
+# I've adapted this file from someone else, see below.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this file
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+
+# this file is adapted from an example of the python ncurses binding
+# pyncurses (http://pyncurses.sf.net/), which has the following copyright
+# statement:
+
+# Copyright (c) 2000 by Harry Henry Gebel
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+
+
+require "ncurses"
+
+def moving(scr)
+ scr.clear() # clear screen
+ scr.move(5,5) # move cursor
+ scr.addstr("move(5,5)")
+ scr.refresh() # update screen
+ sleep(2)
+ scr.move(2,2)
+ scr.addstr("move(2,2)")
+ scr.refresh()
+ sleep(2)
+ scr.move(10, 2)
+ scr.addstr("Press a key to continue")
+ scr.getch()
+end
+
+def border(scr)
+ scr.clear()
+ scr.border(*([0]*8)) # calls WINDOW#border(0, 0, 0, 0, 0, 0, 0, 0)
+ scr.move(3,3)
+ scr.addstr("Press a key to continue")
+ scr.getch()
+end
+
+def two_borders()
+ # make a new window as tall as the screen and half as wide, in the left half
+ # of the screen
+ one = Ncurses::WINDOW.new(0, Ncurses.COLS() / 2, 0, 0)
+ # make one for the right half
+ two = Ncurses::WINDOW.new(0, Ncurses.COLS() - (Ncurses.COLS() / 2),
+ 0, Ncurses.COLS() / 2)
+ one.border(*([0]*8))
+ two.border(*([0]*8))
+ one.move(3,3)
+ two.move(2,5)
+ one.addstr("move(3,3)")
+ two.addstr("move(2,5)")
+ two.move(5,3)
+ two.addstr("Press a key to continue")
+ one.noutrefresh() # copy window to virtual screen, don't update real screen
+ two.noutrefresh()
+ Ncurses.doupdate() # update read screen
+ two.getch()
+end
+
+begin
+ # initialize ncurses
+ Ncurses.initscr
+ Ncurses.cbreak # provide unbuffered input
+ Ncurses.noecho # turn off input echoing
+ Ncurses.nonl # turn off newline translation
+ Ncurses.stdscr.intrflush(false) # turn off flush-on-interrupt
+ Ncurses.stdscr.keypad(true) # turn on keypad mode
+
+ Ncurses.stdscr.addstr("Press a key to continue") # output string
+ Ncurses.stdscr.getch # get a charachter
+
+ moving(Ncurses.stdscr) # demo of moving cursor
+ border(Ncurses.stdscr) # demo of borders
+ two_borders() # demo of two windows with borders
+
+ensure
+ Ncurses.echo
+ Ncurses.nocbreak
+ Ncurses.nl
+ Ncurses.endwin
+end
82 examples/form.rb
@@ -0,0 +1,82 @@
+#!/usr/bin/ruby
+# Copyright (c) 2004 by Simon Kaczor <skaczor@cox.net>
+# Example from the NCurses Programming HOWTO
+# This example uses module functions that are documented in the ncurses man page.
+# For a more rubyish approach that uses Ruby objects see form2.rb
+#
+# The original example contained the following copyright:
+# Copyright (c) 2001 by Pradeep Padala. This document may be distributed
+# under the terms set forth in the LDP license at linuxdoc.org/COPYRIGHT.html.
+
+require 'ncurses.rb'
+
+begin
+ scr = Ncurses.initscr()
+ Ncurses.cbreak()
+ Ncurses.noecho()
+ Ncurses.keypad(scr, true)
+
+ #create some fields
+ fields = Array.new
+ fields.push(Ncurses::Form.new_field(1,10,4,18,0,0))
+ fields.push(Ncurses::Form.new_field(1,10,6,18,0,0))
+
+ # set field options
+ Ncurses::Form.set_field_back(fields[0], Ncurses::A_UNDERLINE)
+ Ncurses::Form.field_opts_off(fields[0], Ncurses::Form::O_AUTOSKIP)
+
+ Ncurses::Form.set_field_back(fields[1], Ncurses::A_UNDERLINE)
+ Ncurses::Form.field_opts_off(fields[1], Ncurses::Form::O_AUTOSKIP)
+
+
+ # create a form
+ form = Ncurses::Form.new_form(fields)
+
+ # post the form and refresh the screen
+ Ncurses::Form.post_form(form)
+ scr.refresh()
+
+ Ncurses.mvprintw(4, 10, "Value 1:")
+ Ncurses.mvprintw(6, 10, "Value 2:")
+ scr.refresh()
+
+ # Loop through to get user requests
+ while((ch = scr.getch()) != Ncurses::KEY_F1) do
+ case(ch)
+ when Ncurses::KEY_DOWN
+ # Go to next field
+ Ncurses::Form.form_driver(form, Ncurses::Form::REQ_NEXT_FIELD)
+ # Go to the end of the present buffer
+ # Leaves nicely at the last character
+ Ncurses::Form.form_driver(form, Ncurses::Form::REQ_END_LINE)
+
+ when Ncurses::KEY_UP
+ #Go to previous field
+ Ncurses::Form.form_driver(form, Ncurses::Form::REQ_PREV_FIELD)
+ Ncurses::Form.form_driver(form, Ncurses::Form::REQ_END_LINE);
+ else
+ # If this is a normal character, it gets Printed
+ Ncurses::Form.form_driver(form, ch)
+ end
+ end
+
+ # unpost and free form
+ Ncurses::Form.unpost_form(form);
+ Ncurses::Form.free_form(form)
+ Ncurses::Form.free_field(fields[0]);
+ Ncurses::Form.free_field(fields[1]);
+
+
+ #using class methods this time
+# form = Ncurses::Form::FORM.new(fields)
+# puts "Created form: #{form.inspect}\n"
+# form.free()
+
+ensure
+ # put the screen back in its normal state
+ Ncurses.echo()
+ Ncurses.nocbreak()
+ Ncurses.nl()
+ Ncurses.endwin()
+end
+
184 examples/form2.rb
@@ -0,0 +1,184 @@
+#!/usr/bin/ruby
+# Copyright (c) 2004 by Simon Kaczor <skaczor@cox.net>
+# Simple example of a form in action, based on the NCURSES Programming HOWTO:
+# http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/
+#
+# All standard field types are created in the form.
+# Additionnally a custom field is created to illustrate
+# custom field validation using Ruby Proc objects, as shown in the example.
+#
+# The original example contained the following copyright:
+# Copyright (c) 2001 by Pradeep Padala. This document may be distributed
+# under the terms set forth in the LDP license at linuxdoc.org/COPYRIGHT.html.
+
+require 'ncurses'
+
+include Ncurses
+include Ncurses::Form
+
+def print_in_middle(win, starty, startx, width, string, color)
+
+ if(win == nil)
+ win = stdscr;
+ end
+ x = Array.new
+ y = Array.new
+ Ncurses.getyx(win, y, x);
+ if(startx != 0)
+ x[0] = startx;
+ end
+ if(starty != 0)
+ y[0] = starty;
+ end
+ if(width == 0)
+ width = 80;
+ end
+ length = string.length;
+ temp = (width - length)/ 2;
+ x[0] = startx + temp.floor;
+ win.attron(color);
+ win.mvprintw(y[0], x[0], "%s", string);
+ win.attroff(color);
+ Ncurses.refresh();
+end
+
+fields = Array.new
+
+states = {"MI" => "Michigan",
+ "VA" => "Virginia",
+ "VE" => "Vermont"}
+fieldcheck = proc { |afield|
+ val = afield.field_buffer(0)
+ val.strip!
+ if (states[val] != nil)
+ afield.set_field_buffer(0,states[val])
+ return true
+ else
+ return false
+ end
+}
+charcheck = proc { |ch|
+ if (('A'..'Z').include?(ch))
+ return true
+ else
+ return false
+ end
+}
+
+# Initialize curses
+begin
+ stdscr = Ncurses.initscr();
+ Ncurses.start_color();
+ Ncurses.cbreak();
+ Ncurses.noecho();
+ Ncurses.keypad(stdscr, true);
+
+ # Initialize few color pairs
+ Ncurses.init_pair(1, COLOR_RED, COLOR_BLACK);
+ Ncurses.init_pair(2, COLOR_BLACK, COLOR_WHITE);
+ Ncurses.init_pair(3, COLOR_BLACK, COLOR_BLUE);
+ stdscr.bkgd(Ncurses.COLOR_PAIR(2));
+
+ # Initialize the fields
+ (1..9).each { |i|
+ field = FIELD.new(1, 10, i*2, 1, 0, 0)
+ field.set_field_back(A_UNDERLINE)
+ fields.push(field)
+ }
+
+ customtype = FIELDTYPE.new(fieldcheck, charcheck);
+
+ fields[1].set_field_type(TYPE_ALNUM, 0);
+ fields[2].set_field_type(TYPE_ALPHA, 0);
+ fields[3].set_field_type(TYPE_INTEGER, 0, 0, 1000);
+ fields[4].set_field_type(TYPE_NUMERIC, 2, 0, 1000);
+ fields[5].set_field_type(TYPE_ENUM, ["one","two","three"], false, false);
+ fields[6].set_field_type(TYPE_REGEXP, "^ *[0-9]* *$");
+ fields[7].set_field_type(TYPE_IPV4);
+ fields[8].set_field_type(customtype);
+
+
+ # Create the form and post it
+ my_form = FORM.new(fields);
+
+ my_form.user_object = "My identifier"
+
+ # Calculate the area required for the form
+ rows = Array.new()
+ cols = Array.new()
+ my_form.scale_form(rows, cols);
+
+ # Create the window to be associated with the form
+ my_form_win = WINDOW.new(rows[0] + 3, cols[0] + 14, 1, 1);
+ my_form_win.bkgd(Ncurses.COLOR_PAIR(3));
+ my_form_win.keypad(TRUE);
+
+ # Set main window and sub window
+ my_form.set_form_win(my_form_win);
+ my_form.set_form_sub(my_form_win.derwin(rows[0], cols[0], 2, 12));
+
+ # Print a border around the main window and print a title */
+ my_form_win.box(0, 0);
+ print_in_middle(my_form_win, 1, 0, cols[0] + 14, "My Form", Ncurses.COLOR_PAIR(1));
+
+ my_form.post_form();
+
+ # Print field types
+ my_form_win.mvaddstr(4, 2, "No Type")
+ my_form_win.mvaddstr(6, 2, "Alphanum")
+ my_form_win.mvaddstr(8, 2, "Alpha")
+ my_form_win.mvaddstr(10, 2, "Integer")
+ my_form_win.mvaddstr(12, 2, "Numeric")
+ my_form_win.mvaddstr(14, 2, "Enum")
+ my_form_win.mvaddstr(16, 2, "Regexp")
+ my_form_win.mvaddstr(18, 2, "IP")
+ my_form_win.mvaddstr(20, 2, "Custom")
+
+ my_form_win.wrefresh();
+
+ stdscr.mvprintw(Ncurses.LINES - 2, 28, "Use UP, DOWN arrow keys to switch between fields");
+ stdscr.mvprintw(Ncurses.LINES - 1, 28, "Press F1 to quit");
+ stdscr.refresh();
+
+ # Loop through to get user requests
+ while((ch = my_form_win.getch()) != KEY_F1)
+ case ch
+ when KEY_DOWN
+ # Go to next field */
+ my_form.form_driver(REQ_VALIDATION);
+ my_form.form_driver(REQ_NEXT_FIELD);
+ # Go to the end of the present buffer
+ # Leaves nicely at the last character
+ my_form.form_driver(REQ_END_LINE);
+
+ when KEY_UP
+ # Go to previous field
+ my_form.form_driver(REQ_VALIDATION);
+ my_form.form_driver(REQ_PREV_FIELD);
+ my_form.form_driver(REQ_END_LINE);
+
+ when KEY_LEFT
+ # Go to previous field
+ my_form.form_driver(REQ_PREV_CHAR);
+
+ when KEY_RIGHT
+ # Go to previous field
+ my_form.form_driver(REQ_NEXT_CHAR);
+
+ when KEY_BACKSPACE
+ my_form.form_driver(REQ_DEL_PREV);
+ else
+ # If this is a normal character, it gets Printed
+ my_form.form_driver(ch);
+ end
+ end
+ # Un post form and free the memory
+ my_form.unpost_form();
+ my_form.free_form();
+ fields.each {|f| f.free_field()}
+
+
+ensure
+ Ncurses.endwin();
+end
+
57 examples/hello_ncurses.rb
@@ -0,0 +1,57 @@
+#!/usr/bin/env ruby
+
+# $Id: hello_ncurses.rb,v 1.3 2002/02/28 13:50:03 t-peters Exp $
+
+# this ncurses-ruby program follows an ancient tradition of example
+# computer programs: When invoked, it prints a friendly greeting on the
+# screen and exits.
+#
+# Copyright (C) 2002 Tobias Peters <t-peters@users.berlios.de>
+#
+# You may use, modify, and redistribute this file without restriction.
+
+
+
+# First, we have to tell Ruby to use the Ncurses extension module:
+
+require "ncurses"
+
+
+
+# Second, every program using ncurses must initialize the ncurses library
+# before the first call to any ncurses function:
+
+Ncurses.initscr
+
+
+
+# Now the program can use ncurses facilities for screen output. It will print
+# a greeting to the 5th line on the screen, starting at column 20
+
+Ncurses.mvaddstr(4, 19, "Hello, world!");
+
+# Note that ncurses counts lines and columns starting from 0, and that it
+# expects the line number first and the column number second every time it
+# expects a coordinate pair.
+
+
+
+# The previous function call did not alter the screen at all. Ncurses makes
+# all changes first to an internal buffer. The contents of this buffer is
+# copied to the screen with the following function call:
+
+Ncurses.refresh
+
+
+# Now pause for a short while, enough time for the program user to read the
+# greeting and greet back.
+
+sleep(2.5)
+
+
+# The program has almost finished its task. It only needs to put the screen
+# back to its normal state:
+
+Ncurses.endwin
+
+
219 examples/rain.rb
@@ -0,0 +1,219 @@
+#!/usr/bin/env ruby
+
+# $Id: rain.rb,v 1.6 2005/08/22 21:41:49 t-peters Exp $
+
+# This program is a translation of the popular rain.c demo program from the
+# ncurses library distribution.
+#
+# Copyright (C) 2002 Tobias Peters <t-peters@users.berlios.de>
+#
+# I do not impose any additional restrictions over the copyright of the
+# ncurses library distribution. It has the following Copyright notice
+
+#/****************************************************************************
+# * Copyright (c) 1998 Free Software Foundation, Inc. *
+# * *
+# * Permission is hereby granted, free of charge, to any person obtaining a *
+# * copy of this software and associated documentation files (the *
+# * "Software"), to deal in the Software without restriction, including *
+# * without limitation the rights to use, copy, modify, merge, publish, *
+# * distribute, distribute with modifications, sublicense, and/or sell *
+# * copies of the Software, and to permit persons to whom the Software is *
+# * furnished to do so, subject to the following conditions: *
+# * *
+# * The above copyright notice and this permission notice shall be included *
+# * in all copies or substantial portions of the Software. *
+# * *
+# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
+# * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
+# * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
+# * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
+# * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
+# * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
+# * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+# * *
+# * Except as contained in this notice, the name(s) of the above copyright *
+# * holders shall not be used in advertising or otherwise to promote the *
+# * sale, use or other dealings in this Software without prior written *
+# * authorization. *
+# ****************************************************************************/
+
+
+
+require "ncurses"
+
+
+# A class responsible for raindrop drawing
+class Raindrop
+ def initialize (window, color_pair = nil)
+ @window = window
+ @color_pair = color_pair
+ lines = []
+ columns = []
+ window.getmaxyx(lines,columns)
+ lines = (lines[0] <= 4) ? 1 : (lines[0] - 4)
+ columns = (columns[0] <= 4) ? 1 : (columns[0] - 4)
+ @current_phase = 0
+ @x = rand(columns)+2
+ @y = rand(lines)+2
+ end
+
+ # draw_next_phase draws the next phase of a raindrop. If this was the last
+ # phase, returns 0, otherwise returns the raindrop.
+ def draw_next_phase
+ if (@color_pair)
+ if Ncurses.respond_to?(:color_set)
+ @window.color_set(@color_pair, nil)
+ else
+ @window.attrset(Ncurses.COLOR_PAIR(@color_pair))
+ end
+ end
+ if (DRAWING_PROCS[@current_phase].call(@window,@y,@x))
+ @current_phase += 1
+ self
+ end
+ end
+
+ DRAWING_PROCS = [
+ Proc.new{|window,y,x|
+ window.mvaddstr(y,x, ".")
+ },
+ Proc.new{|window,y,x|
+ window.mvaddstr(y, x, "o")
+ },
+ Proc.new{|window,y,x|
+ window.mvaddstr(y, x, "O")
+ },
+ Proc.new{|window,y,x|
+ window.mvaddstr(y-1, x, "-")
+ window.mvaddstr(y, x-1, "|.|")
+ window.mvaddstr(y+1, x, "-")
+ },
+ Proc.new{|window,y,x|
+ window.mvaddstr(y-2, x, "-")
+ window.mvaddstr(y-1, x-1, "/ \\")
+ window.mvaddstr(y, x-2, "| O |")
+ window.mvaddstr(y+1, x-1, "\\ /")
+ window.mvaddstr(y+2, x, "-")
+ },
+ Proc.new{|window,y,x|
+ window.mvaddstr(y-2, x, " ")
+ window.mvaddstr(y-1, x-1, " ")
+ window.mvaddstr(y, x-2, " ")
+ window.mvaddstr(y+1, x-1, " ")
+ window.mvaddstr(y+2, x, " ")
+ nil # signal the last raindrop phase
+ }
+ ]
+ NUMBER_OF_PHASES = DRAWING_PROCS.size - 1
+end
+
+
+# This class creates raindrops and tells them to draw on the screen
+class Rain
+ AVERAGE_RAINDROP_SPACE = 475.1 # 4 simultaneous raindrops in a 80x24 Window
+
+ def Rain.sigwinch_handler(sig = nil)
+ ObjectSpace.each_object(Rain){|rain|
+ rain.window_size_changed = true
+ }
+ end
+
+ attr_writer :window_size_changed
+
+ def initialize(window)
+ @window = window
+ @window_size_changed = true
+ @raindrops = []
+ @has_colors = Ncurses.has_colors?
+ if (@has_colors)
+ @current_color = 1
+ end
+ end
+
+ def fall_for_a_moment
+ adjust_to_new_window_size if (@window_size_changed)
+
+ current_number_of_new_raindrops.times{
+ if (@has_colors)
+ @raindrops.push(Raindrop.new(@window, @current_color))
+ @current_color = 3 - @current_color # alternate between 1 and 2
+ else
+ @raindrops.push(Raindrop.new(@window))
+ end
+ }
+
+ @raindrops = @raindrops.collect{|raindrop|
+ raindrop.draw_next_phase
+ }.compact # erase raindrops that have expired from the list
+ end
+
+ def adjust_to_new_window_size
+ @window_size_changed = false
+ window_size = @window.getmaxx * @window.getmaxy
+ average_number_of_raindrops = window_size / AVERAGE_RAINDROP_SPACE
+ @average_number_of_new_raindrops =
+ average_number_of_raindrops / Raindrop::NUMBER_OF_PHASES
+ end
+
+ def current_number_of_new_raindrops
+ num_floor = @average_number_of_new_raindrops.floor
+ num_ceil = @average_number_of_new_raindrops.ceil
+ chance = @average_number_of_new_raindrops - num_floor
+ if (rand > chance)
+ num_floor
+ else
+ num_ceil
+ end
+ end
+
+ def fall(pause = 0.1)
+ begin
+ fall_for_a_moment
+ @window.refresh
+ sleep(pause)
+ end while (true)
+ end
+end
+
+Ncurses.initscr
+begin
+ if (Ncurses.has_colors?)
+ bg = Ncurses::COLOR_BLACK
+ Ncurses.start_color
+ if (Ncurses.respond_to?("use_default_colors"))
+ if (Ncurses.use_default_colors == Ncurses::OK)
+ bg = -1
+ end
+ end
+ Ncurses.init_pair(1, Ncurses::COLOR_BLUE, bg);
+ Ncurses.init_pair(2, Ncurses::COLOR_CYAN, bg);
+ end
+ Ncurses.nl()
+ Ncurses.noecho()
+ Ncurses.curs_set(0)
+ Ncurses.stdscr.nodelay(true)
+
+ rain = Rain.new(Ncurses.stdscr)
+
+ begin
+ case(Ncurses.getch())
+ when 'q'[0], 'Q'[0]
+ Ncurses.curs_set(1)
+ Ncurses.endwin()
+ exit
+ when 's'[0]
+ Ncurses.stdscr.nodelay(false)
+ when ' '[0]
+ Ncurses.stdscr.nodelay(true)
+ when Ncurses::KEY_RESIZE
+ Rain.sigwinch_handler
+ end
+ sleep(0.050)
+ rain.fall_for_a_moment
+ Ncurses.refresh
+ end while true
+ensure
+ Ncurses.curs_set(1)
+ Ncurses.endwin()
+end
67 examples/read_line.rb
@@ -0,0 +1,67 @@
+#!/usr/bin/env ruby
+# Emacs: This is -*- ruby -*- code!
+#
+# Unfinished read_line function
+#
+# Written 2003, 2004 by Tobias Peters
+# No warranties
+# Share and enjoy!
+
+require "ncurses"
+
+# read_line returns an array
+# [string, last_cursor_position_in_string, keycode_of_terminating_enter_key].
+# Complete the "when" clauses before including in your app!
+def read_line(y, x,
+ window = Ncurses.stdscr,
+ max_len = (window.getmaxx - x - 1),
+ string = "",
+ cursor_pos = 0)
+ loop do
+ window.mvaddstr(y,x,string)
+ window.move(y,x+cursor_pos)
+ ch = window.getch
+ case ch
+ when Ncurses::KEY_LEFT
+ cursor_pos = [0, cursor_pos-1].max
+ when Ncurses::KEY_RIGHT
+ # similar, implement yourself !
+ when Ncurses::KEY_ENTER, ?\n, ?\r
+ return string, cursor_pos, ch # Which return key has been used?
+ when Ncurses::KEY_BACKSPACE
+ string = string[0...([0, cursor_pos-1].max)] + string[cursor_pos..-1]
+ cursor_pos = [0, cursor_pos-1].max
+ window.mvaddstr(y, x+string.length, " ")
+ # when etc...
+ when " "[0]..255 # remaining printables
+ if (cursor_pos < max_len)
+ string[cursor_pos,0] = ch.chr
+ cursor_pos += 1
+ else
+ Ncurses.beep
+ end
+ else
+ Ncurses.beep
+ end
+ end
+end
+
+if (__FILE__ == $0) then begin
+ # demo mode
+ Ncurses.initscr
+ Ncurses.cbreak
+ Ncurses.noecho
+
+ # recognize KEY_ENTER, KEY_BACKSPACE etc
+ Ncurses.keypad(Ncurses.stdscr, true)
+
+ y = 10
+ x = 2
+ prompt = "Hallo > "
+ Ncurses.mvaddstr(y,x, prompt)
+ s = read_line(y, x + prompt.length)
+
+ensure
+ Ncurses.endwin
+end end
+p s
227 examples/tclock.rb
@@ -0,0 +1,227 @@
+#!/usr/bin/env ruby
+
+# $Id: tclock.rb,v 1.6 2002/02/28 13:50:10 t-peters Exp $
+
+# tclock - analog/digital clock for curses, translated to ruby
+# Copyright (C) 2002 Tobias Peters <t-peters@users.berlios.de>
+# This file was adapted from the C program tclock.c from the ncurses
+# distribution, which bears the following copyright statement:
+
+# tclock - analog/digital clock for curses.
+# If it gives you joy, then
+# (a) I'm glad
+# (b) you need to get out more :-)
+#
+# This program is copyright Howard Jones, September 1994
+# (ha.jones@ic.ac.uk). It may be freely distributed as
+# long as this copyright message remains intact, and any
+# modifications are clearly marked as such. [In fact, if
+# you modify it, I wouldn't mind the modifications back,
+# especially if they add any nice features. A good one
+# would be a precalc table for the 60 hand positions, so
+# that the floating point stuff can be ditched. As I said,
+# it was a 20 hackup minute job.]
+#
+# COMING SOON: tfishtank. Be the envy of your mac-owning
+# colleagues.
+
+###########################################################################
+# The translation of this program to ruby is a modification and is hereby #
+# clearly marked as such. #
+###########################################################################
+
+require "ncurses"
+PI = Math::PI
+
+def sign(_x)
+ (_x<0?-1:1)
+end
+
+ASPECT = 2.2
+
+def a2x(angle,radius)
+ (ASPECT * radius * Math::sin(angle)).round
+end
+def a2y(angle,radius)
+ (radius * Math::cos(angle)).round
+end
+
+# Plot a point
+def plot(x, y, c)
+ Ncurses.mvaddch(y, x, c[0])
+end
+
+# Draw a diagonal(arbitrary) line using Bresenham's alogrithm.
+def dline(pair, from_x, from_y, x2, y2, ch)
+ if (Ncurses.has_colors?)
+ Ncurses.attrset(Ncurses.COLOR_PAIR(pair))
+ end
+
+ dx = x2 - from_x;
+ dy = y2 - from_y;
+
+ ax = (dx * 2).abs
+ ay = (dy * 2).abs
+
+ sx = sign(dx);
+ sy = sign(dy);
+
+ x = from_x;
+ y = from_y;
+
+ if (ax > ay)
+ d = ay - (ax / 2);
+
+ while (1)
+ plot(x, y, ch);
+ if (x == x2)
+ return nil
+ end
+ if (d >= 0)
+ y += sy;
+ d -= ax;
+ end
+ x += sx;
+ d += ay;
+ end
+ else
+ d = ax - (ay / 2);
+
+ while (1)
+ plot(x, y, ch);
+ if (y == y2)
+ return nil;
+ end
+ if (d >= 0)
+ x += sx;
+ d -= ay;
+ end
+ y += sy;
+ d += ax;
+ end
+ end
+end
+
+begin
+ # int i, cx, cy;
+ # double mradius, hradius, mangle, hangle;
+ # double sangle, sradius, hours;
+ # int hdx, hdy;
+ # int mdx, mdy;
+ # int sdx, sdy;
+ # int ch;
+
+
+ lastbeep = -1;
+ my_bg = Ncurses::COLOR_BLACK;
+
+ Ncurses::initscr();
+ Ncurses::noecho();
+ Ncurses::cbreak();
+ Ncurses::nodelay(Ncurses::stdscr, TRUE);
+ Ncurses::curs_set(0);
+
+ if (Ncurses::has_colors?())
+ Ncurses::start_color();
+
+ Ncurses::init_pair(1, Ncurses::COLOR_RED, my_bg);
+ Ncurses::init_pair(2, Ncurses::COLOR_MAGENTA, my_bg);
+ Ncurses::init_pair(3, Ncurses::COLOR_GREEN, my_bg);
+ end
+ Ncurses::keypad(Ncurses::stdscr, TRUE);
+
+ while (:restart)
+ cx = (Ncurses.COLS - 1) / 2; #/* 39 */
+ cy = Ncurses.LINES / 2; #/* 12 */
+ ch = (cx > cy) ? cy : cx; #/* usually cy */
+ mradius = ((3 * cy) / 4).to_f; #/* 9 */
+ hradius = (cy / 2).to_f; #/* 6 */
+ sradius = ((2 * cy) / 3).to_f; #/* 8 */
+
+ for i in (0...12)
+ sangle = (i + 1) * (2.0 * PI) / 12.0;
+ sradius = ((5 * cy) / 6).to_f; #/* 10 */
+ sdx = a2x(sangle, sradius);
+ sdy = a2y(sangle, sradius);
+ szChar = sprintf("%d", i + 1);
+
+ Ncurses::mvaddstr(cy - sdy, cx + sdx, szChar);
+ end
+
+ Ncurses::mvaddstr(0, 0,
+ "ASCII Clock by Howard Jones (ha.jones@ic.ac.uk),1994");
+
+ sradius -=2
+ sradius = 1 if sradius < 1
+ window_size_changed = false
+ while (window_size_changed == false)
+ sleep(0.100);
+
+ hours = Time.now.hour + Time.now.min / 60.0;
+ if (hours > 12.0)
+ hours -= 12.0;
+ end
+
+ mangle = Time.now.min * (2 * PI) / 60.0;
+ mdx = a2x(mangle, mradius);
+ mdy = a2y(mangle, mradius);
+
+ hangle = ((hours) * (2.0 * PI) / 12.0);
+ hdx = a2x(hangle, hradius);
+ hdy = a2y(hangle, hradius);
+
+ sangle = ((Time.now.sec) * (2.0 * PI) / 60.0);
+ sdx = a2x(sangle, sradius);
+ sdy = a2y(sangle, sradius);
+
+ dline(3, cx, cy, cx + mdx, cy - mdy, '#');
+
+ Ncurses::attrset(Ncurses::A_REVERSE);
+ dline(2, cx, cy, cx + hdx, cy - hdy, '.');
+ Ncurses::attroff(Ncurses::A_REVERSE);
+
+ if (Ncurses::has_colors?())
+ Ncurses::attrset(Ncurses::COLOR_PAIR(1));
+ end
+ plot(cx + sdx, cy - sdy, 'O');
+
+ if (Ncurses::has_colors?())
+ Ncurses::attrset(Ncurses::COLOR_PAIR(0));
+ end
+ Ncurses::mvaddstr(Ncurses.LINES - 2, 0, Time.now.to_s);
+ Ncurses::refresh();
+ if ((Time.now.sec % 5) == 0 &&
+ Time.now.sec != lastbeep)
+ lastbeep = Time.now.sec;
+ Ncurses::beep();
+ end
+
+ if ((ch = Ncurses::getch()) != Ncurses::ERR)
+ if (ch == Ncurses::KEY_RESIZE)
+ Ncurses::erase();
+ window_size_changed = true;
+ else
+ break;
+ end
+ end
+
+ plot(cx + sdx, cy - sdy, ' ');
+ dline(0, cx, cy, cx + hdx, cy - hdy, ' ');
+ dline(0, cx, cy, cx + mdx, cy - mdy, ' ');
+
+ end
+
+ if ! window_size_changed
+ $stderr.puts "! window_size_changed"
+ break
+ end
+ end
+ensure
+ Ncurses::curs_set(1);
+ Ncurses::endwin();
+end
+
+
+
+
+
27 examples/test_scanw.rb
@@ -0,0 +1,27 @@
+#!/usr/bin/env ruby
+
+# $Id: test_scanw.rb,v 1.1 2003/03/22 22:55:00 t-peters Exp $
+#
+# Test of the scanw function. Should really not be used in any serious curses
+# program. To use it, install scanf for ruby.
+
+# Copyright (C) 2003 Tobias Peters <t-peters@users.berlios.de>
+#
+# No warranties. Share and enjoy.
+
+require "ncurses"
+begin
+ Ncurses.initscr
+ Ncurses.mvaddstr(4, 19, "Give me a number: ")
+ Ncurses.refresh
+ num = []
+ Ncurses.scanw("%d", num)
+
+ Ncurses.mvprintw(6, 19, "You gave: %d", num[0])
+ Ncurses.refresh
+ sleep 1
+ensure
+ Ncurses.endwin
+end
+
+puts("You gave: #{num[0]}")
131 extconf.rb
@@ -0,0 +1,131 @@
+#!/usr/bin/env ruby
+
+# ncurses-ruby is a ruby module for accessing the FSF's ncurses library
+# (C) 2002, 2004 Tobias Peters <t-peters@users.berlios.de>
+# (C) 2005 Tobias Herzke
+#
+# This module is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This module 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this module; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# $Id: extconf.rb,v 1.11 2005/02/26 22:51:45 t-peters Exp $
+
+require "mkmf"
+
+$CFLAGS += " -g"
+$CXXFLAGS = $CFLAGS
+
+have_header("unistd.h")
+if have_header("ncurses.h")
+ curses_header = "ncurses.h"
+elsif have_header("ncurses/curses.h")
+ curses_header = "ncurses/curses.h"
+elsif have_header("curses.h")
+ curses_header = "curses.h"
+else
+ raise "ncurses header file not found"
+end
+
+if have_library("ncurses", "wmove")
+ curses_lib = "ncurses"
+elsif have_library("pdcurses", "wmove")
+ curses_lib = "pdcurses"
+else
+ raise "ncurses library not found"
+end
+
+have_func("newscr")
+have_func("TABSIZE")
+have_func("ESCDELAY")
+have_func("keybound")
+have_func("curses_version")
+have_func("tigetstr")
+have_func("getwin")
+have_func("putwin")
+have_func("ungetmouse")
+have_func("mousemask")
+have_func("wenclose")
+have_func("mouseinterval")
+have_func("wmouse_trafo")
+have_func("mcprint")
+have_func("has_key")
+
+have_func("delscreen")
+have_func("define_key")
+have_func("keyok")
+have_func("resizeterm")
+have_func("use_default_colors")
+have_func("use_extended_names")
+have_func("wresize")
+have_func("attr_on")
+have_func("attr_off")
+have_func("attr_set")
+have_func("chgat")
+have_func("color_set")
+have_func("filter")
+have_func("intrflush")
+have_func("mvchgat")
+have_func("mvhline")
+have_func("mvvline")
+have_func("mvwchgat")
+have_func("mvwhline")
+have_func("mvwvline")
+have_func("noqiflush")
+have_func("putp")
+have_func("qiflush")
+have_func("scr_dump")
+have_func("scr_init")
+have_func("scr_restore")
+have_func("scr_set")
+have_func("slk_attr_off")
+have_func("slk_attr_on")
+have_func("slk_attr")
+have_func("slk_attr_set")
+have_func("slk_color")
+have_func("tigetflag")
+have_func("tigetnum")
+have_func("use_env")
+have_func("vidattr")
+have_func("vid_attr")
+have_func("wattr_on")
+have_func("wattr_off")
+have_func("wattr_set")
+have_func("wchgat")
+have_func("wcolor_set")
+have_func("getattrs")
+
+puts "checking which debugging functions to wrap..."
+have_func("_tracef")
+have_func("_tracedump")
+have_func("_nc_tracebits")
+have_func("_traceattr")
+have_func("_traceattr2")
+have_func("_tracechar")
+have_func("_tracechtype")
+have_func("_tracechtype2")
+have_func("_tracemouse")
+
+puts "checking for other functions that appeared after ncurses version 5.0..."
+have_func("assume_default_colors")
+have_func("attr_get")
+
+puts "checking for the panel library..."
+if have_header("panel.h")
+ have_library("panel", "panel_hidden")
+end
+puts "checking for the form library..."
+if have_header("form.h")
+ have_library("form", "new_form")
+end
+
+create_makefile('ncurses_bin')
1,449 form_wrap.c
@@ -0,0 +1,1449 @@
+/*
+ * This is a curses forms wrapper as part of ncurses-ruby
+ * Contributed by Simon Kaczor <skaczor@cox.net>
+ * Prognosoft Inc. <http://www.prognosoft.biz>
+ * Copyright 2004
+ *
+ * Changes:
+ * (C) 2004 Tobias Peters
+ * (C) 2005 Tobias Herzke
+ *
+ * This module is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This module 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this module; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+
+#ifdef HAVE_FORM_H
+
+#include "form_wrap.h"
+#include "ncurses_wrap.h"
+
+VALUE mForm;
+VALUE cFIELD;
+VALUE cFIELDTYPE;
+VALUE cFORM;
+
+void init_err_codes()
+{
+ /* The routine succeeded. */
+ FORM_DEF_CONST(E_OK);
+ /* The field is already connected to a form. */
+ FORM_DEF_CONST(E_CONNECTED);
+ /* System error occurred (see errno). */
+ FORM_DEF_CONST(E_SYSTEM_ERROR);
+ /* Routine detected an incorrect or out-of-range argument. */
+ FORM_DEF_CONST(E_BAD_ARGUMENT);
+ /* The form is already posted. */
+ FORM_DEF_CONST(E_POSTED);
+ /* Routine was called from an initialization or termination function. */
+ FORM_DEF_CONST(E_BAD_STATE);
+ /* Form is too large for its window. */
+ FORM_DEF_CONST(E_NO_ROOM);
+ /* The form has not been posted. */
+ FORM_DEF_CONST(E_NOT_POSTED);
+ /* The form driver code saw an unknown request code. */
+ FORM_DEF_CONST(E_UNKNOWN_COMMAND);
+ /* Contents of a field are not valid. */
+ FORM_DEF_CONST(E_INVALID_FIELD);
+ /* No fields are connected to the form. */
+ FORM_DEF_CONST(E_NOT_CONNECTED);
+ /* The form driver could not process the request.} */
+ FORM_DEF_CONST(E_REQUEST_DENIED);
+}
+
+/*
+ * Form driver request characters listed in form_driver(3x) man page
+ */
+void init_req_constants() {
+ /* Move to the next page */
+ FORM_DEF_CONST(REQ_NEXT_PAGE);
+ /* Move to the previous page. */
+ FORM_DEF_CONST(REQ_PREV_PAGE);
+ /* Move to the first page. */
+ FORM_DEF_CONST(REQ_FIRST_PAGE);
+ /* Move to the last field. */
+ FORM_DEF_CONST(REQ_LAST_PAGE);
+ /* Move to the next field. */
+ FORM_DEF_CONST(REQ_NEXT_FIELD);
+ /* Move to the previous field. */
+ FORM_DEF_CONST(REQ_PREV_FIELD);
+ /* Move to the first field. */
+ FORM_DEF_CONST(REQ_FIRST_FIELD);
+ /* Move to the last field. */
+ FORM_DEF_CONST(REQ_LAST_FIELD);
+ /* Move to the sorted next field. */
+ FORM_DEF_CONST(REQ_SNEXT_FIELD);
+ /* Move to the sorted previous field. */
+ FORM_DEF_CONST(REQ_SPREV_FIELD);
+ /* Move to the sorted first field. */
+ FORM_DEF_CONST(REQ_SFIRST_FIELD);
+ /* Move to the sorted last field. */
+ FORM_DEF_CONST(REQ_SLAST_FIELD);
+ /* Move left to a field. */
+ FORM_DEF_CONST(REQ_LEFT_FIELD);
+ /* Move right to a field. */
+ FORM_DEF_CONST(REQ_RIGHT_FIELD);
+ /* Move up to a field. */
+ FORM_DEF_CONST(REQ_UP_FIELD);
+ /* Move down to a field. */
+ FORM_DEF_CONST(REQ_DOWN_FIELD);
+ /* Move to the next char. */
+ FORM_DEF_CONST(REQ_NEXT_CHAR);
+ /* Move to the previous char. */
+ FORM_DEF_CONST(REQ_PREV_CHAR);
+ /* Move to the next line. */
+ FORM_DEF_CONST(REQ_NEXT_LINE);
+ /* Move to the previous line. */
+ FORM_DEF_CONST(REQ_PREV_LINE);
+ /* Move to the next word. */
+ FORM_DEF_CONST(REQ_NEXT_WORD);
+ /* Move to the previous word. */
+ FORM_DEF_CONST(REQ_PREV_WORD);
+ /* Move to the beginning of the field. */
+ FORM_DEF_CONST(REQ_BEG_FIELD);
+ /* Move to the end of the field. */
+ FORM_DEF_CONST(REQ_END_FIELD);
+ /* Move to the beginning of the line. */
+ FORM_DEF_CONST(REQ_BEG_LINE);
+ /* Move to the end of the line. */
+ FORM_DEF_CONST(REQ_END_LINE);
+ /* Move left in the field. */
+ FORM_DEF_CONST(REQ_LEFT_CHAR);
+ /* Move right in the field. */
+ FORM_DEF_CONST(REQ_RIGHT_CHAR);
+ /* Move up in the field. */
+ FORM_DEF_CONST(REQ_UP_CHAR);
+ /* Move down in the field. */
+ FORM_DEF_CONST(REQ_DOWN_CHAR);
+ /* Insert or overlay a new line. */
+ FORM_DEF_CONST(REQ_NEW_LINE);
+ /* Insert a blank at the cursor. */
+ FORM_DEF_CONST(REQ_INS_CHAR);
+ /* Insert a blank line at the cursor. */
+ FORM_DEF_CONST(REQ_INS_LINE);
+ /* Delete character at the cursor. */
+ FORM_DEF_CONST(REQ_DEL_CHAR);
+ /* Delete character before the cursor. */
+ FORM_DEF_CONST(REQ_DEL_PREV);
+ /* Delete line at the cursor. */
+ FORM_DEF_CONST(REQ_DEL_LINE);
+ /* Delete blank-delimited word at the cursor. */
+ FORM_DEF_CONST(REQ_DEL_WORD);
+ /* Clear to end of line from cursor. */
+ FORM_DEF_CONST(REQ_CLR_EOL);
+ /* Clear to end of field from cursor. */
+ FORM_DEF_CONST(REQ_CLR_EOF);
+ /* Clear the entire field. */
+ FORM_DEF_CONST(REQ_CLR_FIELD);
+ /* Enter overlay mode. */
+ FORM_DEF_CONST(REQ_OVL_MODE);
+ /* Enter insert mode. */
+ FORM_DEF_CONST(REQ_INS_MODE);
+ /* Scroll the field forward a line. */
+ FORM_DEF_CONST(REQ_SCR_FLINE);
+ /* Scroll the field backward a line. */
+ FORM_DEF_CONST(REQ_SCR_BLINE);
+ /* Scroll the field forward a page. */
+ FORM_DEF_CONST(REQ_SCR_FPAGE);
+ /* Scroll the field backward a page. */
+ FORM_DEF_CONST(REQ_SCR_BPAGE);
+ /* Scroll the field forward half a page. */
+ FORM_DEF_CONST(REQ_SCR_FHPAGE);
+ /* Scroll the field backward half a page. */
+ FORM_DEF_CONST(REQ_SCR_BHPAGE);
+ /* Scroll the field forward a character. */
+ FORM_DEF_CONST(REQ_SCR_FCHAR);
+ /* Scroll the field backward a character. */
+ FORM_DEF_CONST(REQ_SCR_BCHAR);
+ /* Horizontal scroll the field forward a line. */
+ FORM_DEF_CONST(REQ_SCR_HFLINE);
+ /* Horizontal scroll the field backward a line. */
+ FORM_DEF_CONST(REQ_SCR_HBLINE);
+ /* Horizontal scroll the field forward half a line. */
+ FORM_DEF_CONST(REQ_SCR_HFHALF);
+ /* Horizontal scroll the field backward half a line. */
+ FORM_DEF_CONST(REQ_SCR_HBHALF);
+ /* Validate field. */
+ FORM_DEF_CONST(REQ_VALIDATION);
+ /* Display next field choice. */
+ FORM_DEF_CONST(REQ_NEXT_CHOICE);
+ /* Display previous field choice. */
+ FORM_DEF_CONST(REQ_PREV_CHOICE);
+}
+
+/*
+ * field justification constants
+ */
+void init_just_constants() {
+ FORM_DEF_CONST(NO_JUSTIFICATION);
+ FORM_DEF_CONST(JUSTIFY_RIGHT);
+ FORM_DEF_CONST(JUSTIFY_LEFT);
+ FORM_DEF_CONST(JUSTIFY_CENTER);
+}
+
+/*
+ * field options constants
+ */
+void init_opts_constants() {
+ FORM_DEF_CONST(O_VISIBLE);
+ FORM_DEF_CONST(O_ACTIVE);
+ FORM_DEF_CONST(O_PUBLIC);
+ FORM_DEF_CONST(O_EDIT);
+ FORM_DEF_CONST(O_WRAP);
+ FORM_DEF_CONST(O_BLANK);
+ FORM_DEF_CONST(O_AUTOSKIP);
+ FORM_DEF_CONST(O_NULLOK);
+ FORM_DEF_CONST(O_STATIC);
+ FORM_DEF_CONST(O_PASSOK);
+}
+
+void init_form_opts_constants() {
+ FORM_DEF_CONST(O_NL_OVERLOAD);
+ FORM_DEF_CONST(O_BS_OVERLOAD);
+}
+
+/*
+ * _PAGE wrapper
+ */
+/* static VALUE wrap_page(_PAGE* page) */
+/* { */
+/* if (page == 0) return Qnil; */
+/* { */
+/* VALUE pages_hash = rb_iv_get(mForm, "@pages_hash"); */
+/* VALUE page_adress = INT2NUM((long)(page)); */
+/* VALUE rb_page = rb_hash_aref(pages_hash, page_adress); */
+/* if (rb_page == Qnil) { */
+/* rb_page = Data_Wrap_Struct(cPAGE, 0, 0, page); */
+/* rb_iv_set(rb_page, "@destroyed", Qfalse); */
+/* rb_hash_aset(pages_hash, page_adress, rb_page); */
+/* } */
+/* return rb_page; */
+/* } */
+/* } */
+/* static _PAGE* get_page(VALUE rb_page) */
+/* { */
+/* _PAGE* page; */
+/* if (rb_page == Qnil) return 0; */
+/* if (rb_iv_get(rb_page, "@destroyed") == Qtrue) { */
+/* rb_raise(rb_eRuntimeError, "Attempt to access a destroyed page"); */
+/* return 0; */
+/* } */
+/* Data_Get_Struct(rb_page, _PAGE, page); */
+/* return page; */
+/* } */
+
+/*
+ * FIELD wrapper
+ */
+static VALUE wrap_field(FIELD* field)
+{
+ if (field == 0) return Qnil;
+ {
+ VALUE fields_hash = rb_iv_get(mForm, "@fields_hash");
+ VALUE field_adress = INT2NUM((long)(field));
+ VALUE rb_field = rb_hash_aref(fields_hash, field_adress);
+ if (rb_field == Qnil) {
+ rb_field = Data_Wrap_Struct(cFIELD, 0, 0, field);
+ rb_iv_set(rb_field, "@destroyed", Qfalse);
+ rb_hash_aset(fields_hash, field_adress, rb_field);
+ }
+ return rb_field;
+ }
+}
+static FIELD* get_field(VALUE rb_field)
+{
+ FIELD* field;
+ if (rb_field == Qnil) return 0;
+ if (rb_iv_get(rb_field, "@destroyed") == Qtrue) {
+ rb_raise(rb_eRuntimeError, "Attempt to access a destroyed field");
+ return 0;
+ }
+ Data_Get_Struct(rb_field, FIELD, field);
+ return field;
+}
+
+/*
+ * FIELDTYPE wrapper
+ */
+static VALUE wrap_fieldtype(FIELDTYPE* fieldtype)
+{
+ if (fieldtype == NULL) return Qnil;
+ {
+ VALUE fieldtypes_hash = rb_iv_get(mForm, "@fieldtypes_hash");
+ VALUE fieldtype_adress = INT2NUM((long)(fieldtype));
+ VALUE rb_fieldtype = rb_hash_aref(fieldtypes_hash, fieldtype_adress);
+ if (rb_fieldtype == Qnil) {
+ rb_fieldtype = Data_Wrap_Struct(cFIELDTYPE, 0, 0, fieldtype);
+ rb_iv_set(rb_fieldtype, "@destroyed", Qfalse);
+ rb_hash_aset(fieldtypes_hash, fieldtype_adress, rb_fieldtype);
+ }
+ return rb_fieldtype;
+ }
+}
+static FIELDTYPE* get_fieldtype(VALUE rb_fieldtype)
+{
+ FIELDTYPE* fieldtype;
+ if (rb_fieldtype == Qnil) return 0;
+ if (rb_iv_get(rb_fieldtype, "@destroyed") == Qtrue) {
+ rb_raise(rb_eRuntimeError, "Attempt to access a destroyed fieldtype");
+ return 0;
+ }
+ Data_Get_Struct(rb_fieldtype, FIELDTYPE, fieldtype);
+ return fieldtype;
+}
+
+/*
+ * FORM wrapper
+ */
+static VALUE wrap_form(FORM* form)
+{
+ if (form == 0) return Qnil;
+ {
+ VALUE forms_hash = rb_iv_get(mForm, "@forms_hash");
+ VALUE form_adress = INT2NUM((long)(form));
+ VALUE rb_form = rb_hash_aref(forms_hash, form_adress);
+ if (rb_form == Qnil) {
+ rb_form = Data_Wrap_Struct(cFORM, 0, 0, form);
+ rb_iv_set(rb_form, "@destroyed", Qfalse);
+ rb_hash_aset(forms_hash, form_adress, rb_form);
+ }
+ return rb_form;
+ }
+}
+static FORM* get_form(VALUE rb_form)
+{
+ FORM* form;
+ if (rb_form == Qnil) return 0;
+ if (rb_iv_get(rb_form, "@destroyed") == Qtrue) {
+ rb_raise(rb_eRuntimeError, "Attempt to access a destroyed form");
+ return 0;
+ }
+ Data_Get_Struct(rb_form, FORM, form);
+ return form;
+}
+
+/*
+ * Proc objects are registered using hashes (one for each type of hook)
+ * The key in the hash is the address of the ncurses "object" and the value is
+ * the Proc object.
+ */
+#define FIELD_INIT_HOOK 0
+#define FIELD_TERM_HOOK 1
+#define FORM_INIT_HOOK 2
+#define FORM_TERM_HOOK 3
+#define FIELDTYPE_FIELD_CHECK_HOOK 4
+#define FIELDTYPE_CHAR_CHECK_HOOK 5
+#define FIELDTYPE_NEXT_CHOICE_HOOK 6
+#define FIELDTYPE_PREV_CHOICE_HOOK 7
+#define FIELDTYPE_ARGS 8
+#define PROC_HASHES_COUNT 9
+static VALUE get_proc_hash(int hook) {
+ VALUE arr = rb_iv_get(mForm, "@proc_hashes");
+ VALUE hash = rb_ary_entry(arr, (long)hook);
+ if (hash == Qnil) {
+ rb_raise(rb_eRuntimeError, "Invalid proc hash.");
+ }
+ return hash;
+}
+
+/*
+ * Returns an existing Ruby Proc for a given owning "object" and hook type.
+ * Qnil will be returned if no Proc was associated with the owner
+ */
+static VALUE get_proc(void* owner, int hook) {
+ if (owner == 0) return Qnil;
+ {
+ VALUE owner_adress = INT2NUM((long)(owner));
+ VALUE proc_hash = get_proc_hash(hook);
+ VALUE proc = rb_hash_aref(proc_hash, owner_adress);
+ return proc;
+ }
+}
+/*
+ * Registers the Proc object with a given owner "object" and hook type.
+ * If proc is Qnil, the hook is unregistered instead.
+ */
+static void reg_proc(void* owner, int hook, VALUE proc) {
+ if (owner == NULL) return;
+ {
+ VALUE proc_hash = get_proc_hash(hook);
+ VALUE owner_address = INT2NUM((long)(owner));
+ if (proc == Qnil) {
+ rb_hash_delete(proc_hash, owner_address);
+ }
+ else {
+ rb_hash_aset(proc_hash, owner_address, proc);
+ }
+ }
+}
+
+/*
+ * Form creation/destruction functions
+ */
+static VALUE rbncurs_m_new_form(VALUE dummy, VALUE rb_field_array)
+{
+ long n = RARRAY(rb_field_array)->len;
+ /* Will ncurses free this array? If not, must do it after calling free_form(). */
+ FIELD** fields = ALLOC_N(FIELD*, (n+1));
+ long i;
+ for (i=0; i<n; i++){
+ fields[i] = get_field(rb_ary_entry(rb_field_array, i));
+ }
+ fields[n] = NULL;
+ return wrap_form(new_form(fields));
+}
+
+static VALUE rbncurs_c_free_form(VALUE rb_form) {
+ VALUE forms_hash = rb_iv_get(mForm, "@forms_hash");
+ FORM* form = get_form(rb_form);
+ VALUE form_adress = INT2NUM((long)(form));
+ rb_funcall(forms_hash, rb_intern("delete"), 1, form_adress);
+ rb_iv_set(rb_form, "@destroyed", Qtrue);