diff --git a/COPYING b/COPYING new file mode 100644 index 000000000..43433c494 --- /dev/null +++ b/COPYING @@ -0,0 +1,482 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 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. + + [This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + 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 Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, 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 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 a program 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. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, 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 companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + 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, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +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. + + 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. + + 6. As an exception to the Sections above, you may also compile 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) 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. + + c) 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. + + d) 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 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. + + 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. + + 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 to +this License. + + 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 Library 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. + + 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 + + Appendix: 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. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/FL/Enumerations.H b/FL/Enumerations.H new file mode 100644 index 000000000..e8237ff74 --- /dev/null +++ b/FL/Enumerations.H @@ -0,0 +1,293 @@ +#ifndef Fl_Enumerations_H +#define Fl_Enumerations_H + +const double FL_VERSION = 0.99; + +typedef unsigned char uchar; +typedef unsigned long ulong; +typedef unsigned int u32; // you must fix if not 32 bits on your machine! + +enum Fl_Event { // events + FL_NO_EVENT = 0, + FL_PUSH = 1, + FL_RELEASE = 2, + FL_ENTER = 3, + FL_LEAVE = 4, + FL_DRAG = 5, + FL_FOCUS = 6, + FL_UNFOCUS = 7, + FL_KEYBOARD = 8, + FL_CLOSE = 9, + FL_MOVE = 10, + FL_SHORTCUT = 11, + FL_DEACTIVATE = 13, + FL_ACTIVATE = 14, + FL_HIDE = 15, + FL_SHOW = 16, + FL_PASTE = 17, + FL_SELECTIONCLEAR = 18 +}; + +enum Fl_When { // Fl_Widget::when(): + FL_WHEN_NEVER = 0, + FL_WHEN_CHANGED = 1, + FL_WHEN_RELEASE = 4, + FL_WHEN_RELEASE_ALWAYS= 6, + FL_WHEN_ENTER_KEY = 8, + FL_WHEN_ENTER_KEY_ALWAYS=10, + FL_WHEN_NOT_CHANGED = 2 // modifier bit to disable changed() test +}; + +// Fl::event_key() and Fl::get_key(n) (use ascii letters for all other keys): +#define FL_Button 0xfee8 // use Fl_Button+n for mouse button n +#define FL_BackSpace 0xff08 +#define FL_Tab 0xff09 +#define FL_Enter 0xff0d +#define FL_Pause 0xff13 +#define FL_Scroll_Lock 0xff14 +#define FL_Escape 0xff1b +#define FL_Home 0xff50 +#define FL_Left 0xff51 +#define FL_Up 0xff52 +#define FL_Right 0xff53 +#define FL_Down 0xff54 +#define FL_Page_Up 0xff55 +#define FL_Page_Down 0xff56 +#define FL_End 0xff57 +#define FL_Print 0xff61 +#define FL_Insert 0xff63 +#define FL_Menu 0xff67 // the "menu/apps" key on XFree86 +#define FL_Num_Lock 0xff7f +#define FL_KP 0xff80 // use FL_KP+'x' for 'x' on numeric keypad +#define FL_KP_Enter 0xff8d // same as Fl_KP+'\r' +#define FL_KP_Last 0xffbd // use to range-check keypad +#define FL_F 0xffbd // use FL_F+n for function key n +#define FL_F_Last 0xffe0 // use to range-check function keys +#define FL_Shift_L 0xffe1 +#define FL_Shift_R 0xffe2 +#define FL_Control_L 0xffe3 +#define FL_Control_R 0xffe4 +#define FL_Caps_Lock 0xffe5 +#define FL_Meta_L 0xffe7 // the left MSWindows key on XFree86 +#define FL_Meta_R 0xffe8 // the right MSWindows key on XFree86 +#define FL_Alt_L 0xffe9 +#define FL_Alt_R 0xffea +#define FL_Delete 0xffff + +// Fl::event_state(): +#define FL_SHIFT 0x00010000 +#define FL_CAPS_LOCK 0x00020000 +#define FL_CTRL 0x00040000 +#define FL_ALT 0x00080000 +#define FL_NUM_LOCK 0x00100000 // most X servers do this? +#define FL_META 0x00400000 // correct for XFree86 +#define FL_SCROLL_LOCK 0x00800000 // correct for XFree86 +#define FL_BUTTON1 0x01000000 +#define FL_BUTTON2 0x02000000 +#define FL_BUTTON3 0x04000000 + +enum Fl_Boxtype { // boxtypes (if you change these you must fix fl_boxtype.C): + FL_NO_BOX = 0, FL_FLAT_BOX, + + FL_UP_BOX, FL_DOWN_BOX, + FL_UP_FRAME, FL_DOWN_FRAME, + FL_THIN_UP_BOX, FL_THIN_DOWN_BOX, + FL_THIN_UP_FRAME, FL_THIN_DOWN_FRAME, + FL_ENGRAVED_BOX, FL_EMBOSSED_BOX, + FL_ENGRAVED_FRAME, FL_EMBOSSED_FRAME, + FL_BORDER_BOX, _FL_SHADOW_BOX, + FL_BORDER_FRAME, _FL_SHADOW_FRAME, + _FL_ROUNDED_BOX, _FL_RSHADOW_BOX, + _FL_ROUNDED_FRAME, _FL_RFLAT_BOX, + _FL_ROUND_UP_BOX, _FL_ROUND_DOWN_BOX, + _FL_DIAMOND_UP_BOX, _FL_DIAMOND_DOWN_BOX, + _FL_OVAL_BOX, _FL_OSHADOW_BOX, + _FL_OVAL_FRAME, _FL_OFLAT_BOX +}; +extern Fl_Boxtype define_FL_ROUND_UP_BOX(); +#define FL_ROUND_UP_BOX define_FL_ROUND_UP_BOX() +#define FL_ROUND_DOWN_BOX (Fl_Boxtype)(define_FL_ROUND_UP_BOX()+1) +extern Fl_Boxtype define_FL_SHADOW_BOX(); +#define FL_SHADOW_BOX define_FL_SHADOW_BOX() +#define FL_SHADOW_FRAME (Fl_Boxtype)(define_FL_SHADOW_BOX()+2) +extern Fl_Boxtype define_FL_ROUNDED_BOX(); +#define FL_ROUNDED_BOX define_FL_ROUNDED_BOX() +#define FL_ROUNDED_FRAME (Fl_Boxtype)(define_FL_ROUNDED_BOX()+2) +extern Fl_Boxtype define_FL_RFLAT_BOX(); +#define FL_RFLAT_BOX define_FL_RFLAT_BOX() +extern Fl_Boxtype define_FL_RSHADOW_BOX(); +#define FL_RSHADOW_BOX define_FL_RSHADOW_BOX() +extern Fl_Boxtype define_FL_DIAMOND_BOX(); +#define FL_DIAMOND_UP_BOX define_FL_DIAMOND_BOX() +#define FL_DIAMOND_DOWN_BOX (Fl_Boxtype)(define_FL_DIAMOND_BOX()+1) +extern Fl_Boxtype define_FL_OVAL_BOX(); +#define FL_OVAL_BOX define_FL_OVAL_BOX() +#define FL_OSHADOW_BOX (Fl_Boxtype)(define_FL_OVAL_BOX()+1) +#define FL_OVAL_FRAME (Fl_Boxtype)(define_FL_OVAL_BOX()+2) +#define FL_OFLAT_BOX (Fl_Boxtype)(define_FL_OVAL_BOX()+3) + +// conversions of box types to other boxtypes: +inline Fl_Boxtype down(Fl_Boxtype b) {return (Fl_Boxtype)(b|1);} +inline Fl_Boxtype frame(Fl_Boxtype b) {return (Fl_Boxtype)(b|2);} + +// back-compatability box types: +#define FL_FRAME FL_ENGRAVED_FRAME +#define FL_FRAME_BOX FL_ENGRAVED_BOX +#define FL_CIRCLE_BOX FL_ROUND_DOWN_BOX +#define FL_DIAMOND_BOX FL_DIAMOND_DOWN_BOX + +enum Fl_Labeltype { // labeltypes: + FL_NORMAL_LABEL = 0, + FL_NO_LABEL, + _FL_SYMBOL_LABEL, + _FL_SHADOW_LABEL, + _FL_ENGRAVED_LABEL, + _FL_EMBOSSED_LABEL, + _FL_BITMAP_LABEL, + _FL_PIXMAP_LABEL, + _FL_IMAGE_LABEL, + _FL_MULTI_LABEL, + FL_FREE_LABELTYPE +}; +extern Fl_Labeltype define_FL_SYMBOL_LABEL(); +#define FL_SYMBOL_LABEL define_FL_SYMBOL_LABEL() +extern Fl_Labeltype define_FL_SHADOW_LABEL(); +#define FL_SHADOW_LABEL define_FL_SHADOW_LABEL() +extern Fl_Labeltype define_FL_ENGRAVED_LABEL(); +#define FL_ENGRAVED_LABEL define_FL_ENGRAVED_LABEL() +extern Fl_Labeltype define_FL_EMBOSSED_LABEL(); +#define FL_EMBOSSED_LABEL define_FL_EMBOSSED_LABEL() + +enum Fl_Align { // align() values + FL_ALIGN_CENTER = 0, + FL_ALIGN_TOP = 1, + FL_ALIGN_BOTTOM = 2, + FL_ALIGN_LEFT = 4, + FL_ALIGN_RIGHT = 8, + FL_ALIGN_INSIDE = 16, + FL_ALIGN_CLIP = 64, + FL_ALIGN_WRAP = 128, + FL_ALIGN_TOP_LEFT = FL_ALIGN_TOP | FL_ALIGN_LEFT, + FL_ALIGN_TOP_RIGHT = FL_ALIGN_TOP | FL_ALIGN_RIGHT, + FL_ALIGN_BOTTOM_LEFT = FL_ALIGN_BOTTOM | FL_ALIGN_LEFT, + FL_ALIGN_BOTTOM_RIGHT = FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT, + FL_ALIGN_LEFT_TOP = FL_ALIGN_TOP_LEFT, + FL_ALIGN_RIGHT_TOP = FL_ALIGN_TOP_RIGHT, + FL_ALIGN_LEFT_BOTTOM = FL_ALIGN_BOTTOM_LEFT, + FL_ALIGN_RIGHT_BOTTOM = FL_ALIGN_BOTTOM_RIGHT, + FL_ALIGN_NOWRAP = 0 // for back compatability +}; + +enum Fl_Font { // standard fonts + FL_HELVETICA = 0, + FL_HELVETICA_BOLD, + FL_HELVETICA_ITALIC, + FL_HELVETICA_BOLD_ITALIC, + FL_COURIER, + FL_COURIER_BOLD, + FL_COURIER_ITALIC, + FL_COURIER_BOLD_ITALIC, + FL_TIMES, + FL_TIMES_BOLD, + FL_TIMES_ITALIC, + FL_TIMES_BOLD_ITALIC, + FL_SYMBOL, + FL_SCREEN, + FL_SCREEN_BOLD, + FL_ZAPF_DINGBATS, + + FL_FREE_FONT = 16, // first one to allocate + FL_BOLD = 1, // add this to helvetica, courier, or times + FL_ITALIC = 2 // add this to helvetica, courier, or times +}; + +#define FL_NORMAL_SIZE 14 // default size of all labels & text + +enum Fl_Color { // standard colors + FL_BLACK = 0, + FL_RED = 1, + FL_GREEN = 2, + FL_YELLOW = 3, + FL_BLUE = 4, + FL_MAGENTA = 5, + FL_CYAN = 6, + FL_WHITE = 7, + FL_INACTIVE_COLOR = 8, + FL_SELECTION_COLOR = 15, + + FL_FREE_COLOR = 16, + FL_NUM_FREE_COLOR = 16, + + FL_GRAY_RAMP = 32, + + // boxtypes limit themselves to these colors so whole ramp is not allocated: + FL_GRAY0 = 32, // 'A' + FL_DARK3 = 39, // 'H' + FL_DARK2 = 45, // 'N' + FL_DARK1 = 47, // 'P' + FL_GRAY = 49, // 'R' default color + FL_LIGHT1 = 50, // 'S' + FL_LIGHT2 = 52, // 'U' + FL_LIGHT3 = 54, // 'W' + + FL_COLOR_CUBE = 56 +}; + +inline Fl_Color inactive(Fl_Color c) {return (Fl_Color)(c|8);} +Fl_Color contrast(Fl_Color fg, Fl_Color bg); +#define FL_NUM_GRAY 24 +inline Fl_Color fl_gray_ramp(int i) {return (Fl_Color)(i+FL_GRAY_RAMP);} +#define FL_NUM_RED 5 +#define FL_NUM_GREEN 8 +#define FL_NUM_BLUE 5 +inline Fl_Color fl_color_cube(int r, int g, int b) { + return (Fl_Color)((b*FL_NUM_RED + r) * FL_NUM_GREEN + g + FL_COLOR_CUBE);} + +enum Fl_Cursor { // standard cursors + FL_CURSOR_DEFAULT = 0, + FL_CURSOR_ARROW = 35, + FL_CURSOR_CROSS = 66, + FL_CURSOR_WAIT = 76, + FL_CURSOR_INSERT = 77, + FL_CURSOR_HAND = 31, + FL_CURSOR_HELP = 47, + FL_CURSOR_MOVE = 27, + // fltk provides bitmaps for these: + FL_CURSOR_NS = 78, + FL_CURSOR_WE = 79, + FL_CURSOR_NWSE = 80, + FL_CURSOR_NESW = 81, + FL_CURSOR_NONE = 255, + // for back compatability (non MSWindows ones): + FL_CURSOR_N = 70, + FL_CURSOR_NE = 69, + FL_CURSOR_E = 49, + FL_CURSOR_SE = 8, + FL_CURSOR_S = 9, + FL_CURSOR_SW = 7, + FL_CURSOR_W = 36, + FL_CURSOR_NW = 68 + //FL_CURSOR_NS = 22, + //FL_CURSOR_WE = 55, +}; + +enum { // values for "when" passed to Fl::add_fd() + FL_READ = 1, + FL_WRITE = 4, + FL_EXCEPT = 8 +}; + +enum Fl_Mode { // visual types and Fl_Gl_Window::mode() (values match Glut) + FL_RGB = 0, + FL_INDEX = 1, + FL_SINGLE = 0, + FL_DOUBLE = 2, + FL_ACCUM = 4, + FL_ALPHA = 8, + FL_DEPTH = 16, + FL_STENCIL = 32, + FL_RGB8 = 64, + FL_MULTISAMPLE= 128 +}; + +#endif diff --git a/FL/Fl.H b/FL/Fl.H new file mode 100644 index 000000000..b0cc41fd4 --- /dev/null +++ b/FL/Fl.H @@ -0,0 +1,195 @@ +// Fl.H + +// fltk (Fast Light Tool Kit) version 0.99 +// Copyright (C) 1998 Bill Spitzak + +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library 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 +// Library General Public License for more details. + +// You should have received a copy of the GNU Library 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. + +// Written by Bill Spitzak spitzak@d2.com + +#ifndef Fl_H +#define Fl_H + +#include "Enumerations.H" +#ifndef Fl_Object +#define Fl_Object Fl_Widget +#endif + +class Fl_Widget; +class Fl_Window; +struct Fl_Label; +typedef void (Fl_Label_Draw_F)(const Fl_Label*, int,int,int,int, Fl_Align); +typedef void (Fl_Label_Measure_F)(const Fl_Label*, int&, int&); +typedef void (Fl_Box_Draw_F)(int,int,int,int, Fl_Color); + +class Fl { + Fl() {}; // no constructor! + +public: // should be private! + + static int e_x,e_y,e_x_root,e_y_root; + static int e_state; + static int e_clicks; + static int e_is_click; + static int e_keysym; + static char* e_text; + static int e_length; + static Fl_Widget* belowmouse_; + static Fl_Widget* pushed_; + static Fl_Widget* focus_; + static int damage_; + static Fl_Widget* selection_owner_; + static Fl_Window* modal_; + static Fl_Window* grab_; + + static void damage(int x) {damage_ = x;} + + static void (*idle)(); + +public: + + // argument parsers: + static int arg(int, char**, int&); + static int args(int, char**, int&, int (*)(int,char**,int&) = 0); + static const char* const help; + static void args(int, char**); + + // things called by initialization: + static void display(const char*); + static int visual(int); + static int gl_visual(int, int *alist=0); + static void own_colormap(); + static void get_system_colors(); + static void foreground(uchar, uchar, uchar); + static void background(uchar, uchar, uchar); + static void background2(uchar, uchar, uchar); + + // execution: + static int wait(); + static double wait(double time); + static int check(); + static int ready(); + static int run(); + static Fl_Widget* readqueue(); + static void add_timeout(double t,void (*cb)(void*),void* = 0); + static void remove_timeout(void (*cb)(void*), void* = 0); + static void add_fd(int fd, int when, void (*cb)(int, void*), void* = 0); + static void add_fd(int fd, void (*cb)(int, void*), void* = 0); + static void remove_fd(int); + static void add_idle(void (*cb)(void*), void* = 0); + static void remove_idle(void (*cb)(void*), void* = 0); + static int damage() {return damage_;} + static void redraw(); + static void flush(); + static void (*warning)(const char*, ...); + static void (*error)(const char*, ...); + static void (*fatal)(const char*, ...); + static Fl_Window* first_window(); + static Fl_Window* next_window(const Fl_Window*); + static Fl_Window* modal() {return modal_;} + static Fl_Window* grab() {return grab_;} + static void grab(Fl_Window&); + static void release(); + + // event information: + static int event_x() {return e_x;} + static int event_y() {return e_y;} + static int event_x_root() {return e_x_root;} + static int event_y_root() {return e_y_root;} + static void get_mouse(int &,int &); + static int event_clicks() {return e_clicks;} + static void event_clicks(int i) {e_clicks = i;} + static int event_is_click() {return e_is_click;} + static void event_is_click(int i) {e_is_click = i;} // only 0 works! + static int event_button() {return e_keysym-FL_Button;} + static int event_state() {return e_state;} + static int event_state(int i) {return e_state&i;} + static int event_key() {return e_keysym;} + static int event_key(int); + static int get_key(int); + static const char* event_text() {return e_text;} + static int event_length() {return e_length;} + static int event_inside(int,int,int,int); + static int event_inside(const Fl_Widget*); + static int test_shortcut(int); + + // event destinations: + static int handle(int, Fl_Window*); + static Fl_Widget* belowmouse() {return belowmouse_;} + static void belowmouse(Fl_Widget*); + static Fl_Widget* pushed() {return pushed_;} + static void pushed(Fl_Widget*); + static Fl_Widget* focus() {return focus_;} + static void focus(Fl_Widget*); + static void add_handler(int (*h)(int)); + + // cut/paste: + static Fl_Widget* selection_owner() {return selection_owner_;} + static void selection_owner(Fl_Widget*); + static void selection(Fl_Widget &owner, const char* stuff, int len); + static void paste(Fl_Widget &receiver); + + // screen size: + static int x() {return 0;} + static int y() {return 0;} + static int w(); + static int h(); + + // color map: + static void set_color(Fl_Color, uchar, uchar, uchar); + static void set_color(Fl_Color, unsigned); + static unsigned get_color(Fl_Color); + static void get_color(Fl_Color, uchar&, uchar&, uchar&); + static void free_color(Fl_Color, int overlay = 0); + + // fonts: + static const char* get_font(Fl_Font); + static const char* get_font_name(Fl_Font, int* attributes = 0); + static int get_font_sizes(Fl_Font, int*& sizep); + static void set_font(Fl_Font, const char*); + static void set_font(Fl_Font, Fl_Font); + static Fl_Font set_fonts(const char* = 0); + + // labeltypes: + static void set_labeltype(Fl_Labeltype,Fl_Label_Draw_F*,Fl_Label_Measure_F*); + static void set_labeltype(Fl_Labeltype, Fl_Labeltype from); + static void enable_symbols(); + + // boxtypes: + static void set_boxtype(Fl_Boxtype, Fl_Box_Draw_F*,uchar,uchar,uchar,uchar); + static void set_boxtype(Fl_Boxtype, Fl_Boxtype from); + static int box_dx(Fl_Boxtype); + static int box_dy(Fl_Boxtype); + static int box_dw(Fl_Boxtype); + static int box_dh(Fl_Boxtype); + + // back compatability: + static void set_abort(void (*f)(const char*,...)) {fatal = f;} + static void (*atclose)(Fl_Window*,void*); + static void default_atclose(Fl_Window*,void*); + static void set_atclose(void (*f)(Fl_Window*,void*)) {atclose = f;} + static int event_shift() {return e_state&FL_SHIFT;} + static int event_ctrl() {return e_state&FL_CTRL;} + static int event_alt() {return e_state&FL_ALT;} + static int event_buttons() {return e_state&0x7f000000;} + static int event_button1() {return e_state&FL_BUTTON1;} + static int event_button2() {return e_state&FL_BUTTON2;} + static int event_button3() {return e_state&FL_BUTTON3;} + static void set_idle(void (*cb)()) {idle = cb;} + +}; + +#endif diff --git a/FL/Fl_Adjuster.H b/FL/Fl_Adjuster.H new file mode 100644 index 000000000..df4a2cdd1 --- /dev/null +++ b/FL/Fl_Adjuster.H @@ -0,0 +1,26 @@ +// Fl_Adjuster.H + +// 3-button "slider", made for Nuke + +#ifndef Fl_Adjuster_H +#define Fl_Adjuster_H + +#ifndef Fl_Valuator_H +#include "Fl_Valuator.H" +#endif + +class Fl_Adjuster : public Fl_Valuator { + int drag; + int ix; + int soft_; +protected: + void draw(); + int handle(int); + void value_damage(); +public: + Fl_Adjuster(int x,int y,int w,int h,const char *l=0); + void soft(int x) {soft_ = x;} + int soft() const {return soft_;} +}; + +#endif diff --git a/FL/Fl_Bitmap.H b/FL/Fl_Bitmap.H new file mode 100644 index 000000000..2707cf1ed --- /dev/null +++ b/FL/Fl_Bitmap.H @@ -0,0 +1,24 @@ +/* Fl_Bitmap.H */ + +#ifndef Fl_Bitmap_H +#define Fl_Bitmap_H + +class Fl_Widget; +struct Fl_Menu_Item; + +struct Fl_Bitmap { + const uchar *array; + int w, h; + ulong id; // for internal use + Fl_Bitmap(const uchar *bits, int W, int H) : + array(bits), w(W), h(H), id(0) {} + Fl_Bitmap(const char *bits, int W, int H) : + array((const uchar *)bits), w(W), h(H), id(0) {} + ~Fl_Bitmap(); + void label(Fl_Widget*); + void label(Fl_Menu_Item*); + void draw(int X, int Y, int W, int H, int cx=0, int cy=0); + void draw(int X, int Y) {draw(X, Y, w, h, 0, 0);} +}; + +#endif diff --git a/FL/Fl_Box.H b/FL/Fl_Box.H new file mode 100644 index 000000000..a1936a094 --- /dev/null +++ b/FL/Fl_Box.H @@ -0,0 +1,19 @@ +/* Fl_Box.H */ + +#ifndef Fl_Box_H +#define Fl_Box_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +class Fl_Box : public Fl_Widget { + void draw(); +public: + Fl_Box(int x, int y, int w, int h, const char *l=0) + : Fl_Widget(x,y,w,h,l) {} + Fl_Box(Fl_Boxtype b, int x, int y, int w, int h, const char *l) + : Fl_Widget(x,y,w,h,l) {box(b);} +}; + +#endif diff --git a/FL/Fl_Browser.H b/FL/Fl_Browser.H new file mode 100644 index 000000000..aaf2975d5 --- /dev/null +++ b/FL/Fl_Browser.H @@ -0,0 +1,86 @@ +/* Fl_Browser.H + + Forms-compatable browser. Probably useful for other + lists of textual data. Notice that the line numbers + start from 1, and 0 means "no line". + +*/ + +#ifndef Fl_Browser_H +#define Fl_Browser_H + +#include "Fl_Browser_.H" + +struct FL_BLINE; + +class Fl_Browser : public Fl_Browser_ { + + // required routines for Fl_Browser_ subclass: + void* item_first() const ; + void* item_next(void*) const ; + void* item_prev(void*) const ; + int item_selected(void*) const ; + void item_select(void*, int); + int item_height(void*) const ; + int item_width(void*) const ; + void item_draw(void*, int, int, int, int) const ; + int full_height() const ; + int incr_height() const ; + + FL_BLINE *first; // the array of lines + FL_BLINE *last; + FL_BLINE *cache; + int cacheline; // line number of cache + int lines; // Number of lines + int full_height_; + const int* column_widths_; + char format_char_; // alternative to @-sign + char column_char_; // alternative to tab + FL_BLINE* find_line(int) const ; + FL_BLINE* _remove(int) ; + void insert(int, FL_BLINE*); + int lineno(void*) const ; + +public: + + void remove(int); + void add(const char*, void* = 0); + void insert(int, const char*, void* = 0); + void move(int to, int from); + int load(const char* filename); + void clear(); + + int size() const {return lines;} + int topline() const ; + void topline(int); + + int select(int, int=1); + int selected(int) const ; + void show(int n); + void hide(int n); + int visible(int n) const ; + + int value() const ; + void value(int v) {select(v);} + const char* text(int) const ; + void text(int, const char*); + void* data(int) const ; + void data(int, void* v); + + Fl_Browser(int, int, int, int, const char* = 0); + + char format_char() const {return format_char_;} + void format_char(char c) {format_char_ = c;} + char column_char() const {return column_char_;} + void column_char(char c) {column_char_ = c;} + const int* column_widths() const {return column_widths_;} + void column_widths(const int* l) { column_widths_=l; } + + int displayed(int n) const {return Fl_Browser_::displayed(find_line(n));} + + // for back compatability only: + void replace(int a, const char* b) {text(a, b);} + void display(int, int=1); +}; + +#endif diff --git a/FL/Fl_Browser_.H b/FL/Fl_Browser_.H new file mode 100644 index 000000000..f3ff3b521 --- /dev/null +++ b/FL/Fl_Browser_.H @@ -0,0 +1,123 @@ +// Fl_Browser_.H + +// This is the base class for browsers. To be useful it must +// be subclassed and several virtual functions defined. The +// Forms-compatable browser and the file chooser's browser are +// subclassed off of this. + +// Yes, I know this should be a template... + +#ifndef Fl_Browser__H +#define Fl_Browser__H + +#ifndef Fl_Group_H +#include "Fl_Group.H" +#endif +#include "Fl_Scrollbar.H" + +#define FL_NORMAL_BROWSER 0 +#define FL_SELECT_BROWSER 1 +#define FL_HOLD_BROWSER 2 +#define FL_MULTI_BROWSER 3 + +class Fl_Browser_ : public Fl_Group { + int position_; // where user wants it scrolled to + int real_position_; // the current vertical scrolling position + int hposition_; // where user wants it panned to + int real_hposition_; // the current horizontal scrolling position + int offset_; // how far down top_ item the real_position is + int max_width; // widest object seen so far + uchar textfont_, textsize_, textcolor_; + uchar has_scrollbar_; // which scrollbars are enabled + void* top_; // which item scrolling position is in + void* selection_; // which is selected (except for FL_MULTI_BROWSER) + void *redraw1,*redraw2; // minimal update pointers + void* max_width_item; // which item has max_width_ + + static int scrollbar_width_; + + void update_top(); + +protected: + + // All of the following must be supplied by the subclass: + virtual void *item_first() const = 0; + virtual void *item_next(void *) const = 0; + virtual void *item_prev(void *) const = 0; + virtual int item_height(void *) const = 0; + virtual int item_width(void *) const = 0; + virtual int item_quick_height(void *) const ; + virtual void item_draw(void *,int,int,int,int) const = 0; + // you don't have to provide these but it may help speed it up: + virtual int full_width() const ; // current width of all items + virtual int full_height() const ; // current height of all items + virtual int incr_height() const ; // average height of an item + // These only need to be done by subclass if you want a multi-browser: + virtual void item_select(void *,int=1); + virtual int item_selected(void *) const ; + + // things the subclass may want to call: + void *top() const {return top_;} + void *selection() const {return selection_;} + void new_list(); // completely clobber all data, as though list replaced + void deleting(void *a); // get rid of any pointers to a + void replacing(void *a,void *b); // change a pointers to b + void inserting(void *a,void *b); // insert a before b + int displayed(void *) const ; // true if this line is visible + void redraw_line(void *); // minimal update, no change in size + void redraw_lines() {damage(4);} // redraw all of them + void bbox(int&,int&,int&,int&) const; + int leftedge() const; // x position after scrollbar & border + void *find_item(int my); // item under mouse + void draw(int,int,int,int); + int handle(int,int,int,int,int); + + void draw(); + int handle(int); + Fl_Browser_(int,int,int,int,const char * = 0); + +public: + + Fl_Scrollbar scrollbar; // Vertical scrollbar + Fl_Scrollbar hscrollbar; // Horizontal scrollbar + + void resize(int,int,int,int); + + int select(void *,int=1,int docallbacks=0); + int select_only(void *,int docallbacks=0); + int deselect(int docallbacks=0); + int position() const {return position_;} + int hposition() const {return hposition_;} + void position(int); // scroll to here + void hposition(int); // pan to here + void display(void*); // scroll so this item is shown + + uchar has_scrollbar() const {return has_scrollbar_;} + void has_scrollbar(uchar i) {has_scrollbar_ = i;} + enum { // values for has_scrollbar() + HORIZONTAL = 1, + VERTICAL = 2, + BOTH = 3, + ALWAYS_ON = 4, + HORIZONTAL_ALWAYS = 5, + VERTICAL_ALWAYS = 6, + BOTH_ALWAYS = 7 + }; + + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar s) {textfont_ = s;} + uchar textsize() const {return textsize_;} + void textsize(uchar s) {textsize_ = s;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(uchar n) {textcolor_ = n;} + + static void scrollbar_width(int b) {scrollbar_width_ = b;} + static int scrollbar_width() {return scrollbar_width_;} + + // for back compatability: + void scrollbar_right() {scrollbar.align(FL_ALIGN_RIGHT);} + void scrollbar_left() {scrollbar.align(FL_ALIGN_LEFT);} + +}; + +#endif diff --git a/FL/Fl_Button.H b/FL/Fl_Button.H new file mode 100644 index 000000000..49f4b98cb --- /dev/null +++ b/FL/Fl_Button.H @@ -0,0 +1,48 @@ +// Fl_Button.H + +#ifndef Fl_Button_H +#define Fl_Button_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +// values for type() +#define FL_TOGGLE_BUTTON 1 +#define FL_RADIO_BUTTON (FL_RESERVED_TYPE+2) +#define FL_HIDDEN_BUTTON 3 // for Forms compatability + +extern int fl_old_shortcut(const char*); + +class Fl_Button : public Fl_Widget { + + int shortcut_; + char value_; + char oldval; + uchar down_box_; + +protected: + + virtual void draw(); + +public: + + virtual int handle(int); + Fl_Button(int,int,int,int,const char * = 0); + int value(int); + char value() const {return value_;} + int set() {return value(1);} + int clear() {return value(0);} + void setonly(); // this should only be called on FL_RADIO_BUTTONs + int shortcut() const {return shortcut_;} + void shortcut(int s) {shortcut_ = s;} + Fl_Boxtype down_box() const {return (Fl_Boxtype)down_box_;} + void down_box(Fl_Boxtype b) {down_box_ = b;} + + // back compatability: + void shortcut(const char *s) {shortcut(fl_old_shortcut(s));} + Fl_Color down_color() const {return selection_color();} + void down_color(uchar c) {selection_color(c);} +}; + +#endif diff --git a/FL/Fl_Chart.H b/FL/Fl_Chart.H new file mode 100644 index 000000000..08a58f32e --- /dev/null +++ b/FL/Fl_Chart.H @@ -0,0 +1,65 @@ +/* Fl_Chart.H + + Emulation of the Forms Chart widget. + I did not try to improve this much, as I doubt it is used. + +*/ + +#ifndef Fl_Chart_H +#define Fl_Chart_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +// values for type() +#define FL_BAR_CHART 0 +#define FL_HORBAR_CHART 1 +#define FL_LINE_CHART 2 +#define FL_FILL_CHART 3 +#define FL_SPIKE_CHART 4 +#define FL_PIE_CHART 5 +#define FL_SPECIALPIE_CHART 6 + +#define FL_FILLED_CHART FL_FILL_CHART // compatibility + +#define FL_CHART_MAX 128 +#define FL_CHART_LABEL_MAX 18 + +struct FL_CHART_ENTRY { + float val; + uchar col; + char str[FL_CHART_LABEL_MAX+1]; +}; + +class Fl_Chart : public Fl_Widget { + int numb; + int maxnumb; + FL_CHART_ENTRY entries[FL_CHART_MAX+1]; + double min,max; + uchar autosize_; + uchar textfont_,textsize_,textcolor_; +protected: + void draw(); +public: + Fl_Chart(int,int,int,int,const char * = 0); + void clear(); + void add(double, const char * =0, uchar=0); + void insert(int, double, const char * =0, uchar=0); + void replace(int, double, const char * =0, uchar=0); + void bounds(double *a,double *b) const {*a = min; *b = max;} + void bounds(double a,double b); + int size() const {return numb;} + int maxsize() const {return maxnumb;} + void maxsize(int); + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar s) {textfont_ = s;} + uchar textsize() const {return textsize_;} + void textsize(uchar s) {textsize_ = s;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(uchar n) {textcolor_ = n;} + uchar autosize() const {return autosize_;} + void autosize(uchar n) {autosize_ = n;} +}; + +#endif diff --git a/FL/Fl_Check_Button.H b/FL/Fl_Check_Button.H new file mode 100644 index 000000000..bc935a45d --- /dev/null +++ b/FL/Fl_Check_Button.H @@ -0,0 +1,15 @@ +// Fl_Check_Button.H + +// Fl_Light_Button with a diamond down_box() and a red color. + +#ifndef Fl_Check_Button_H +#define Fl_Check_Button_H + +#include "Fl_Light_Button.H" + +class Fl_Check_Button : public Fl_Light_Button { +public: + Fl_Check_Button(int x,int y,int w,int h,const char *l = 0); +}; + +#endif diff --git a/FL/Fl_Choice.H b/FL/Fl_Choice.H new file mode 100644 index 000000000..8d5d3462f --- /dev/null +++ b/FL/Fl_Choice.H @@ -0,0 +1,20 @@ +// Fl_Choice.H + +// Popup menu with last-picked item displayed in button + +#ifndef Fl_Choice_H +#define Fl_Choice_H + +#include "Fl_Menu_.H" + +class Fl_Choice : public Fl_Menu_ { +protected: + void draw(); +public: + int handle(int); + Fl_Choice(int,int,int,int,const char * = 0); + int value(int i); + int value() const {return Fl_Menu_::value();} +}; + +#endif diff --git a/FL/Fl_Clock.H b/FL/Fl_Clock.H new file mode 100644 index 000000000..b442e5474 --- /dev/null +++ b/FL/Fl_Clock.H @@ -0,0 +1,38 @@ +// Fl_Clock.H + +#ifndef Fl_Clock_H +#define Fl_Clock_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +// values for type: +#define FL_SQUARE_CLOCK 0 +#define FL_ROUND_CLOCK 1 +#define FL_ANALOG_CLOCK FL_SQUARE_CLOCK +#define FL_DIGITAL_CLOCK FL_SQUARE_CLOCK // nyi + +class Fl_Clock : public Fl_Widget { + int hour_, minute_, second_; + ulong value_; + void drawhands(Fl_Color,Fl_Color); // part of draw +protected: + void draw(int, int, int, int); + void draw(); + void _Fl_Clock(); + int handle(int); +public: + Fl_Clock(int x,int y,int w,int h, const char *l = 0); + Fl_Clock(uchar t,int x,int y,int w,int h, const char *l); + ~Fl_Clock(); + void value(ulong v); // set to this Unix time + void value(int,int,int); // set hour, minute, second + ulong value() const {return value_;} + int hour() const {return hour_;} + int minute() const {return minute_;} + int second() const {return second_;} +}; + +#endif + diff --git a/FL/Fl_Color_Chooser.H b/FL/Fl_Color_Chooser.H new file mode 100644 index 000000000..e8f01cd56 --- /dev/null +++ b/FL/Fl_Color_Chooser.H @@ -0,0 +1,71 @@ +// Fl_Color_Chooser.H + +// The color chooser object and the color chooser popup. The popup +// is just a window containing a single color chooser and some boxes +// to indicate the current and cancelled color. + +#ifndef Fl_Color_Chooser_H +#define Fl_Color_Chooser_H + +#include +#include +#include +#include +#include + +class Flcc_HueBox : public Fl_Widget { + int handle(int); + void draw(); + int px, py; +public: + Flcc_HueBox(int X, int Y, int W, int H) : Fl_Widget(X,Y,W,H) { + px = py = 0;} +}; + +class Flcc_ValueBox : public Fl_Widget { + int handle(int); + void draw(); + int py; +public: + Flcc_ValueBox(int X, int Y, int W, int H) : Fl_Widget(X,Y,W,H) { + py = 0;} +}; + +class Flcc_Value_Input : public Fl_Value_Input { +public: + int format(char*); + Flcc_Value_Input(int X, int Y, int W, int H) : Fl_Value_Input(X,Y,W,H) {} +}; + +class Fl_Color_Chooser : public Fl_Group { + Flcc_HueBox huebox; + Flcc_ValueBox valuebox; + Fl_Choice choice; + Flcc_Value_Input rvalue; + Flcc_Value_Input gvalue; + Flcc_Value_Input bvalue; + Fl_Box resize_box; + double hue_, saturation_, value_; + double r_, g_, b_; + void set_valuators(); + static void rgb_cb(Fl_Widget*, void*); + static void mode_cb(Fl_Widget*, void*); +public: + int mode() {return choice.value();} + double hue() const {return hue_;} + double saturation() const {return saturation_;} + double value() const {return value_;} + double r() const {return r_;} + double g() const {return g_;} + double b() const {return b_;} + int hsv(double,double,double); + int rgb(double,double,double); + static void hsv2rgb(double, double, double,double&,double&,double&); + static void rgb2hsv(double, double, double,double&,double&,double&); + Fl_Color_Chooser(int,int,int,int,const char* = 0); +}; + +int fl_color_chooser(const char* name, double& r, double& g, double& b); +int fl_color_chooser(const char* name, uchar& r, uchar& g, uchar& b); + +#endif diff --git a/FL/Fl_Counter.H b/FL/Fl_Counter.H new file mode 100644 index 000000000..33c0002d2 --- /dev/null +++ b/FL/Fl_Counter.H @@ -0,0 +1,47 @@ +// Fl_Counter.H + +// A numerical value with up/down step buttons. From Forms. + +#ifndef Fl_Counter_H +#define Fl_Counter_H + +#ifndef Fl_Valuator_H +#include "Fl_Valuator.H" +#endif + +// values for type(): +#define FL_NORMAL_COUNTER 0 +#define FL_SIMPLE_COUNTER 1 + +class Fl_Counter : public Fl_Valuator { + + uchar textfont_, textsize_, textcolor_; + double lstep_; + uchar mouseobj; + static void repeat_callback(void *); + int calc_mouseobj(); + void increment_cb(); + +protected: + + void draw(); + +public: + + int handle(int); + Fl_Counter(int,int,int,int,const char * = 0); + ~Fl_Counter(); + void lstep(double a) {lstep_ = a;} + void step(double a,double b) {Fl_Valuator::step(a); lstep_ = b;} + void step(double a) {Fl_Valuator::step(a);} + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar s) {textfont_ = s;} + uchar textsize() const {return textsize_;} + void textsize(uchar s) {textsize_ = s;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(uchar s) {textcolor_ = s;} + +}; + +#endif + diff --git a/FL/Fl_Dial.H b/FL/Fl_Dial.H new file mode 100644 index 000000000..a6b74c7b1 --- /dev/null +++ b/FL/Fl_Dial.H @@ -0,0 +1,43 @@ +// Fl_Dial.H + +// A circular dial control, like xv uses. From Forms. + +#ifndef Fl_Dial_H +#define Fl_Dial_H + +#ifndef Fl_Valuator_H +#include "Fl_Valuator.H" +#endif + +// values for type(): +#define FL_NORMAL_DIAL 0 +#define FL_LINE_DIAL 1 +#define FL_FILL_DIAL 2 + +#define FL_DIAL_CW 0 +#define FL_DIAL_CCW 1 + +class Fl_Dial : public Fl_Valuator { + + short a1,a2; + uchar direction_; + +protected: + + // these allow subclasses to put the dial in a smaller area: + void draw(int, int, int, int); + int handle(int, int, int, int, int); + void draw(); + +public: + + int handle(int); + Fl_Dial(int x,int y,int w,int h, const char *l = 0); + void angles(short a, short b) {a1=a; a2=b;} + void direction(uchar d) {direction_ = d;} + uchar direction() const {return direction_;} + +}; + +#endif + diff --git a/FL/Fl_Double_Window.H b/FL/Fl_Double_Window.H new file mode 100644 index 000000000..ba7a42d90 --- /dev/null +++ b/FL/Fl_Double_Window.H @@ -0,0 +1,23 @@ +// Fl_Double_Window.H + +#ifndef Fl_Double_Window_H +#define Fl_Double_Window_H + +#include "Fl_Window.H" + +class Fl_Double_Window : public Fl_Window { +protected: + void _flush(int); // used by Fl_Overlay_Window +public: + void show(); + void show(int a, char **b) {Fl_Window::show(a,b);} + void flush(); + void resize(int,int,int,int); + void hide(); + ~Fl_Double_Window(); + Fl_Double_Window(int W, int H, const char *l = 0) : Fl_Window(W,H,l) {} + Fl_Double_Window(int X, int Y, int W, int H, const char *l = 0) + : Fl_Window(X,Y,W,H,l) {} +}; + +#endif diff --git a/FL/Fl_Fill_Dial.H b/FL/Fl_Fill_Dial.H new file mode 100644 index 000000000..a0e699a72 --- /dev/null +++ b/FL/Fl_Fill_Dial.H @@ -0,0 +1,12 @@ +#ifndef Fl_Fill_Dial_H +#define Fl_Fill_Dial_H + +#include "Fl_Dial.H" + +class Fl_Fill_Dial : public Fl_Dial { +public: + Fl_Fill_Dial(int x,int y,int w,int h, const char *l = 0) + : Fl_Dial(x,y,w,h,l) {type(FL_FILL_DIAL);} +}; + +#endif diff --git a/FL/Fl_Fill_Slider.H b/FL/Fl_Fill_Slider.H new file mode 100644 index 000000000..7fa946db0 --- /dev/null +++ b/FL/Fl_Fill_Slider.H @@ -0,0 +1,12 @@ +#ifndef Fl_Fill_Slider_H +#define Fl_Fill_Slider_H + +#include "Fl_Slider.H" + +class Fl_Fill_Slider : public Fl_Slider { +public: + Fl_Fill_Slider(int x,int y,int w,int h,const char *l=0) + : Fl_Slider(x,y,w,h,l) {type(FL_VERT_FILL_SLIDER);} +}; + +#endif diff --git a/FL/Fl_Float_Input.H b/FL/Fl_Float_Input.H new file mode 100644 index 000000000..fc70bbebc --- /dev/null +++ b/FL/Fl_Float_Input.H @@ -0,0 +1,12 @@ +#ifndef Fl_Float_Input_H +#define Fl_Float_Input_H + +#include "Fl_Input.H" + +class Fl_Float_Input : public Fl_Input { +public: + Fl_Float_Input(int x,int y,int w,int h,const char *l = 0) + : Fl_Input(x,y,w,h,l) {type(FL_FLOAT_INPUT);} +}; + +#endif diff --git a/FL/Fl_FormsBitmap.H b/FL/Fl_FormsBitmap.H new file mode 100644 index 000000000..2790f66f9 --- /dev/null +++ b/FL/Fl_FormsBitmap.H @@ -0,0 +1,23 @@ +/* Fl_FormsBitmap.H + + Forms compatability widget + +*/ + +#ifndef Fl_FormsBitmap_H +#define Fl_FormsBitmap_H + +#include "Fl_Bitmap.H" + +class Fl_FormsBitmap : public Fl_Widget { + Fl_Bitmap *b; +protected: + void draw(); +public: + Fl_FormsBitmap(Fl_Boxtype, int, int, int, int, const char * = 0); + void set(int W, int H, const uchar *bits); + void bitmap(Fl_Bitmap *B) {b = B;} + Fl_Bitmap *bitmap() const {return b;} +}; + +#endif diff --git a/FL/Fl_FormsPixmap.H b/FL/Fl_FormsPixmap.H new file mode 100644 index 000000000..f5515848c --- /dev/null +++ b/FL/Fl_FormsPixmap.H @@ -0,0 +1,23 @@ +/* Fl_FormsPixmap.H + + Forms compatability widget + +*/ + +#ifndef Fl_FormsPixmap_H +#define Fl_FormsPixmap_H + +#include "Fl_Pixmap.H" + +class Fl_FormsPixmap : public Fl_Widget { + Fl_Pixmap *b; +protected: + void draw(); +public: + Fl_FormsPixmap(Fl_Boxtype, int, int, int, int, const char * = 0); + void set(/*const*/char * const * bits); + void Pixmap(Fl_Pixmap *B) {b = B;} + Fl_Pixmap *Pixmap() const {return b;} +}; + +#endif diff --git a/FL/Fl_Free.H b/FL/Fl_Free.H new file mode 100644 index 000000000..edba73fb8 --- /dev/null +++ b/FL/Fl_Free.H @@ -0,0 +1,40 @@ +// Fl_Free.H + +// Emulation of the Forms "free" widget. This emulation allows the +// free demo to run, but it is not clear if it is sufficient to make +// porting programs any easier. + +#ifndef Fl_Free_H +#define Fl_Free_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +#define FL_NORMAL_FREE 1 +#define FL_SLEEPING_FREE 2 +#define FL_INPUT_FREE 3 +#define FL_CONTINUOUS_FREE 4 +#define FL_ALL_FREE 5 + +typedef int (*FL_HANDLEPTR)(Fl_Widget *, int , float, float, char); + +class Fl_Free : public Fl_Widget { + FL_HANDLEPTR hfunc; + static void step(void *); + void draw(); + int handle(int); +public: + Fl_Free(uchar t,int x,int y,int w,int h,const char *l,FL_HANDLEPTR hdl); + ~Fl_Free(); +}; + +// old event names for compatability: +#define FL_MOUSE FL_DRAG +#define FL_DRAW 0 +#define FL_STEP 9 +#define FL_FREEMEM 12 +#define FL_FREEZE FL_UNMAP +#define FL_THAW FL_MAP + +#endif diff --git a/FL/Fl_Gl_Window.H b/FL/Fl_Gl_Window.H new file mode 100644 index 000000000..1cc083c53 --- /dev/null +++ b/FL/Fl_Gl_Window.H @@ -0,0 +1,60 @@ +#ifndef Fl_Gl_Window_H +#define Fl_Gl_Window_H + +#include "Fl_Window.H" + +class Fl_Gl_Choice; // structure to hold result of glXChooseVisual + +class Fl_Gl_Window : public Fl_Window { + + int mode_; + const int *alist; + Fl_Gl_Choice *g; + void * context; // actually a GLXContext + char valid_; + char damage1_; // damage() of back buffer + virtual void draw_overlay(); + void init(); + + void *overlay; + void make_overlay(); + friend class _Fl_Gl_Overlay; + + static int can_do(int, const int *); + int mode(int, const int *); + +public: + + void show(); + void show(int a, char **b) {Fl_Window::show(a,b);} + void flush(); + void hide(); + void resize(int,int,int,int); + + char valid() const {return valid_;} + void valid(char i) {valid_ = i;} + void invalidate(); + + static int can_do(int i) {return can_do(i,0);} + static int can_do(const int *i) {return can_do(0, i);} + int can_do() {return can_do(mode_,alist);} + Fl_Mode mode() const {return (Fl_Mode)mode_;} + int mode(int a) {return mode(a,0);} + int mode(const int *a) {return mode(0, a);} + + int can_do_overlay(); + void redraw_overlay(); + void hide_overlay(); + + void make_current(); + void make_overlay_current(); + void swap_buffers(); + void ortho(); + + ~Fl_Gl_Window(); + Fl_Gl_Window(int W, int H, const char *l=0) : Fl_Window(W,H,l) {init();} + Fl_Gl_Window(int X, int Y, int W, int H, const char *l=0) + : Fl_Window(X,Y,W,H,l) {init();} +}; + +#endif diff --git a/FL/Fl_Group.H b/FL/Fl_Group.H new file mode 100644 index 000000000..c64af5312 --- /dev/null +++ b/FL/Fl_Group.H @@ -0,0 +1,73 @@ +// Fl_Group.H + +#ifndef Fl_Group_H +#define Fl_Group_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +class Fl_Group : public Fl_Widget { + + Fl_Widget** array_; + Fl_Widget* savedfocus_; + Fl_Widget* resizable_; + int children_; + short *sizes_; // remembered initial sizes of children + + int navigation(int = 0); + static Fl_Group *current_; + +protected: + + void draw(); + int handle(int); + void draw_child(Fl_Widget&) const; + void update_child(Fl_Widget&) const; + void draw_outside_label(const Fl_Widget&) const ; + short* sizes(); + +public: + + void begin() {current_ = this;} + void end() {current_ = (Fl_Group*)parent();} + static Fl_Group *current() {return current_;} + static void current(Fl_Group *g) {current_ = g;} + + int children() const {return children_;} + Fl_Widget* child(int n) const {return array()[n];} + int find(const Fl_Widget*) const; + int find(const Fl_Widget& o) const {return find(&o);} + Fl_Widget* const* array() const; + + void resize(int,int,int,int); + Fl_Group(int,int,int,int, const char * = 0); + virtual ~Fl_Group(); + void add(Fl_Widget&); + void add(Fl_Widget* o) {add(*o);} + void insert(Fl_Widget&, int i); + void insert(Fl_Widget& o, Fl_Widget* before) {insert(o,find(before));} + void remove(Fl_Widget&); + void remove(Fl_Widget* o) {remove(*o);} + void clear(); + + void resizable(Fl_Widget& o) {resizable_ = &o;} + void resizable(Fl_Widget* o) {resizable_ = o;} + Fl_Widget* resizable() const {return resizable_;} + void add_resizable(Fl_Widget& o) {resizable_ = &o; add(o);} + void init_sizes(); + + // back compatability function: + void focus(Fl_Widget* o) {o->take_focus();} + Fl_Widget* & _ddfdesign_kludge() {return resizable_;} + void forms_end(); +}; + +// dummy class used to end child groups in constructors for complex +// subclasses of Fl_Group: +class Fl_End { +public: + Fl_End() {Fl_Group::current()->end();} +}; + +#endif diff --git a/FL/Fl_Hold_Browser.H b/FL/Fl_Hold_Browser.H new file mode 100644 index 000000000..19faf82f0 --- /dev/null +++ b/FL/Fl_Hold_Browser.H @@ -0,0 +1,12 @@ +#ifndef Fl_Hold_Browser_H +#define Fl_Hold_Browser_H + +#include "Fl_Browser.H" + +class Fl_Hold_Browser : public Fl_Browser { +public: + Fl_Hold_Browser(int x,int y,int w,int h,const char *l=0) + : Fl_Browser(x,y,w,h,l) {type(FL_HOLD_BROWSER);} +}; + +#endif diff --git a/FL/Fl_Hor_Fill_Slider.H b/FL/Fl_Hor_Fill_Slider.H new file mode 100644 index 000000000..f049b6f75 --- /dev/null +++ b/FL/Fl_Hor_Fill_Slider.H @@ -0,0 +1,12 @@ +#ifndef Fl_Hor_Fill_Slider_H +#define Fl_Hor_Fill_Slider_H + +#include "Fl_Slider.H" + +class Fl_Hor_Fill_Slider : public Fl_Slider { +public: + Fl_Hor_Fill_Slider(int x,int y,int w,int h,const char *l=0) + : Fl_Slider(x,y,w,h,l) {type(FL_HOR_FILL_SLIDER);} +}; + +#endif diff --git a/FL/Fl_Hor_Nice_Slider.H b/FL/Fl_Hor_Nice_Slider.H new file mode 100644 index 000000000..5fd141a9e --- /dev/null +++ b/FL/Fl_Hor_Nice_Slider.H @@ -0,0 +1,12 @@ +#ifndef Fl_Hor_Nice_Slider_H +#define Fl_Hor_Nice_Slider_H + +#include "Fl_Slider.H" + +class Fl_Hor_Nice_Slider : public Fl_Slider { +public: + Fl_Hor_Nice_Slider(int x,int y,int w,int h,const char *l=0) + : Fl_Slider(x,y,w,h,l) {type(FL_HOR_NICE_SLIDER); box(FL_FLAT_BOX);} +}; + +#endif diff --git a/FL/Fl_Hor_Slider.H b/FL/Fl_Hor_Slider.H new file mode 100644 index 000000000..0e9e54fa0 --- /dev/null +++ b/FL/Fl_Hor_Slider.H @@ -0,0 +1,12 @@ +#ifndef Fl_Hor_Slider_H +#define Fl_Hor_Slider_H + +#include "Fl_Slider.H" + +class Fl_Hor_Slider : public Fl_Slider { +public: + Fl_Hor_Slider(int x,int y,int w,int h,const char *l=0) + : Fl_Slider(x,y,w,h,l) {type(FL_HOR_SLIDER);} +}; + +#endif diff --git a/FL/Fl_Hor_Value_Slider.H b/FL/Fl_Hor_Value_Slider.H new file mode 100644 index 000000000..e0fc43db3 --- /dev/null +++ b/FL/Fl_Hor_Value_Slider.H @@ -0,0 +1,12 @@ +#ifndef Fl_Hor_Value_Slider_H +#define Fl_Hor_Value_Slider_H + +#include "Fl_Value_Slider.H" + +class Fl_Hor_Value_Slider : public Fl_Value_Slider { +public: + Fl_Hor_Value_Slider(int x,int y,int w,int h,const char *l=0) + : Fl_Value_Slider(x,y,w,h,l) {type(FL_HOR_SLIDER);} +}; + +#endif diff --git a/FL/Fl_Image.H b/FL/Fl_Image.H new file mode 100644 index 000000000..7e03a70aa --- /dev/null +++ b/FL/Fl_Image.H @@ -0,0 +1,22 @@ +/* Fl_Image.H */ + +#ifndef Fl_Image_H +#define Fl_Image_H + +class Fl_Widget; +struct Fl_Menu_Item; + +struct Fl_Image { + const uchar *array; + int w, h, d, ld; + ulong id; // for internal use + Fl_Image(const uchar *bits, int W, int H, int D=3, int LD=0) : + array(bits), w(W), h(H), d(D), ld(LD), id(0) {} + ~Fl_Image(); + void label(Fl_Widget*); + void label(Fl_Menu_Item*); + void draw(int X, int Y, int W, int H, int cx=0, int cy=0); + void draw(int X, int Y) {draw(X, Y, w, h, 0, 0);} +}; + +#endif diff --git a/FL/Fl_Input.H b/FL/Fl_Input.H new file mode 100644 index 000000000..172a30447 --- /dev/null +++ b/FL/Fl_Input.H @@ -0,0 +1,22 @@ +// Fl_Input.H + +// This is the "user interface", it decodes user actions into what to +// do to the text. See also Fl_Input_.H for text manipulation functions. + +#ifndef Fl_Input_H +#define Fl_Input_H + +#include "Fl_Input_.H" + +class Fl_Input : public Fl_Input_ { + int handle_key(); + int shift_position(int p); + int shift_up_down_position(int p); + void handle_mouse(int keepmark=0); +public: + void draw(); + int handle(int); + Fl_Input(int,int,int,int,const char * = 0); +}; + +#endif diff --git a/FL/Fl_Input_.H b/FL/Fl_Input_.H new file mode 100644 index 000000000..696ffe829 --- /dev/null +++ b/FL/Fl_Input_.H @@ -0,0 +1,107 @@ +// Fl_Input_.H + +#ifndef Fl_Input__H +#define Fl_Input__H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +#define FL_NORMAL_INPUT 0 +#define FL_FLOAT_INPUT 1 +#define FL_INT_INPUT 2 +#define FL_HIDDEN_INPUT 3 +#define FL_MULTILINE_INPUT 4 +#define FL_SECRET_INPUT 5 + +class Fl_Input_ : public Fl_Widget { + + const char* value_; + char* buffer; + + int size_; + int bufsize; + int position_; + int mark_; + int xscroll_, yscroll_; + int mu_p; + int maximum_size_; + + uchar textfont_; + uchar textsize_; + uchar textcolor_; + uchar cursor_color_; + uchar erase_cursor_only; + + const char* expand(const char*, char*) const; + double expandpos(const char*, const char*, const char*, int*) const; + void minimal_update(int, int); + void minimal_update(int p); + void put_in_buffer(int newsize); + + static Fl_Boxtype default_box_; + static Fl_Font default_font_; + static int default_size_; + void setfont() const; + +protected: + + int wordboundary(int i) const; + int lineboundary(int i) const; + void drawtext(int, int, int, int); + int up_down_position(int, int keepmark=0); + void handle_mouse(int, int, int, int, int keepmark=0); + int handletext(int e, int, int, int, int); + void maybe_do_callback(); + int xscroll() const {return xscroll_;} + int yscroll() const {return yscroll_;} + +public: + + void resize(int, int, int, int); + + Fl_Input_(int, int, int, int, const char* = 0); + ~Fl_Input_(); + + int value(const char*); + int value(const char*, int); + int static_value(const char*); + int static_value(const char*, int); + const char* value() const {return value_;} + char index(int i) const {return value_[i];} + int size() const {return size_;} + int maximum_size() const {return maximum_size_;} + void maximum_size(int m) {maximum_size_ = m;} + + int position() const {return position_;} + int mark() const {return mark_;} + int position(int p, int m); + int position(int p) {return position(p, p);} + int mark(int m) {return position(position(), m);} + int replace(int, int, const char*, int=0); + int cut() {return replace(position(), mark(), 0);} + int cut(int n) {return replace(position(), position()+n, 0);} + int cut(int a, int b) {return replace(a, b, 0);} + int insert(const char* t, int l=0){return replace(position_, mark_, t, l);} + int copy(); + int undo(); + int copy_cuts(); + + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar s) {textfont_ = s;} + uchar textsize() const {return textsize_;} + void textsize(uchar s) {textsize_ = s;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(uchar n) {textcolor_ = n;} + Fl_Color cursor_color() const {return (Fl_Color)cursor_color_;} + void cursor_color(uchar n) {cursor_color_ = n;} + + static void default_box(Fl_Boxtype b) {default_box_ = b;} + static Fl_Boxtype default_box() {return default_box_;} + static void default_font(Fl_Font b) {default_font_ = b;} + static Fl_Font default_font() {return default_font_;} + static void default_size(int b) {default_size_ = b;} + static int default_size() {return default_size_;} +}; + +#endif diff --git a/FL/Fl_Int_Input.H b/FL/Fl_Int_Input.H new file mode 100644 index 000000000..97648e5fa --- /dev/null +++ b/FL/Fl_Int_Input.H @@ -0,0 +1,12 @@ +#ifndef Fl_Int_Input_H +#define Fl_Int_Input_H + +#include "Fl_Input.H" + +class Fl_Int_Input : public Fl_Input { +public: + Fl_Int_Input(int x,int y,int w,int h,const char *l = 0) + : Fl_Input(x,y,w,h,l) {type(FL_INT_INPUT);} +}; + +#endif diff --git a/FL/Fl_Light_Button.H b/FL/Fl_Light_Button.H new file mode 100644 index 000000000..cd55ded00 --- /dev/null +++ b/FL/Fl_Light_Button.H @@ -0,0 +1,23 @@ +// Fl_Light_Button.H + +// Subclass of Fl_Button where the "box" indicates whether it is +// pushed or not, and the "down box" is drawn small and square on +// the left to indicate the current state. + +// The default down_box of zero draws a rectangle designed to look +// just like Flame's buttons. + +#ifndef Fl_Light_Button_H +#define Fl_Light_Button_H + +#include "Fl_Button.H" + +class Fl_Light_Button : public Fl_Button { +protected: + virtual void draw(); +public: + virtual int handle(int); + Fl_Light_Button(int x,int y,int w,int h,const char *l = 0); +}; + +#endif diff --git a/FL/Fl_Line_Dial.H b/FL/Fl_Line_Dial.H new file mode 100644 index 000000000..c4eb48dd4 --- /dev/null +++ b/FL/Fl_Line_Dial.H @@ -0,0 +1,12 @@ +#ifndef Fl_Line_Dial_H +#define Fl_Line_Dial_H + +#include "Fl_Dial.H" + +class Fl_Line_Dial : public Fl_Dial { +public: + Fl_Line_Dial(int x,int y,int w,int h, const char *l = 0) + : Fl_Dial(x,y,w,h,l) {type(FL_LINE_DIAL);} +}; + +#endif diff --git a/FL/Fl_Menu.H b/FL/Fl_Menu.H new file mode 100644 index 000000000..6aad15936 --- /dev/null +++ b/FL/Fl_Menu.H @@ -0,0 +1,2 @@ +// this include file is for back compatability only +#include "Fl_Menu_Item.H" diff --git a/FL/Fl_Menu_.H b/FL/Fl_Menu_.H new file mode 100644 index 000000000..658ad74a7 --- /dev/null +++ b/FL/Fl_Menu_.H @@ -0,0 +1,82 @@ +// Fl_Menu_.H + +// This is a base class for all items that have a menu: +// Fl_Menu_Bar, Fl_Menu_Button, Fl_Choice +// This provides storage for a menu item, functions to add/modify/delete +// items, and a call for when the user picks a menu item. +// Implementation in Fl_Menu.C + +#ifndef Fl_Menu__H +#define Fl_Menu__H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif +#include "Fl_Menu_Item.H" + +class Fl_Menu_ : public Fl_Widget { + + Fl_Menu_Item *menu_; + const Fl_Menu_Item *value_; + static Fl_Font default_font_; + static int default_size_; + +protected: + + const Fl_Menu_Item* picked(const Fl_Menu_Item*); + uchar down_box_; + uchar textfont_; + uchar textsize_; + uchar textcolor_; + uchar alloc; + +public: + + Fl_Menu_(int,int,int,int,const char * =0); + ~Fl_Menu_(); + + const Fl_Menu_Item* test_shortcut() {return picked(menu()->test_shortcut());} + void global(); + + const Fl_Menu_Item *menu() const {return menu_;} + void menu(const Fl_Menu_Item *m); + int add(const char*, int shortcut, Fl_Callback*, void* = 0, int = 0); + int add(const char* a, const char* b, Fl_Callback* c, + void* d = 0, int e = 0) {return add(a,fl_old_shortcut(b),c,d,e);} + int size() const ; + void clear(); + int add(const char *); + void replace(int,const char *); + void remove(int); + void shortcut(int i, int s) {menu_[i].shortcut(s);} + void mode(int i,int x) {menu_[i].flags = x;} + int mode(int i) const {return menu_[i].flags;} + + const Fl_Menu_Item *mvalue() const {return value_;} + int value() const {return value_-menu_;} + int value(const Fl_Menu_Item*); + int value(int i) {return value(menu_+i);} + const char *text() const {return value_ ? value_->text : 0;} + const char *text(int i) const {return menu_[i].text;} + + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar c) {textfont_=c;} + uchar textsize() const {return textsize_;} + void textsize(uchar c) {textsize_=c;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(uchar c) {textcolor_=c;} + + static void default_font(Fl_Font b) {default_font_ = b;} + static Fl_Font default_font() {return default_font_;} + static void default_size(int b) {default_size_ = b;} + static int default_size() {return default_size_;} + + Fl_Boxtype down_box() const {return (Fl_Boxtype)down_box_;} + void down_box(Fl_Boxtype b) {down_box_ = b;} + + // back compatability: + Fl_Color down_color() const {return selection_color();} + void down_color(uchar c) {selection_color(c);} +}; + +#endif diff --git a/FL/Fl_Menu_Bar.H b/FL/Fl_Menu_Bar.H new file mode 100644 index 000000000..0985b7dbe --- /dev/null +++ b/FL/Fl_Menu_Bar.H @@ -0,0 +1,27 @@ +// Fl_Menu_Bar.H + +// The implementation is in Fl_Menu.C + +#ifndef Fl_Menu_Bar_H +#define Fl_Menu_Bar_H + +#include "Fl_Menu_.H" + +class Fl_Menu_Bar : public Fl_Menu_ { +protected: + int handle(int); + void draw(); +public: + Fl_Menu_Bar(int x,int y,int w,int h,const char *l=0) + : Fl_Menu_(x,y,w,h,l) {} +}; + +#endif + + + + + + + + diff --git a/FL/Fl_Menu_Button.H b/FL/Fl_Menu_Button.H new file mode 100644 index 000000000..81d7d1af0 --- /dev/null +++ b/FL/Fl_Menu_Button.H @@ -0,0 +1,19 @@ +// Fl_Menu_Button.C + +#ifndef Fl_Menu_Button_H +#define Fl_Menu_Button_H + +#include "Fl_Menu_.H" + +class Fl_Menu_Button : public Fl_Menu_ { +protected: + void draw(); +public: + // values for type: + enum {POPUP1 = 1, POPUP2, POPUP12, POPUP3, POPUP13, POPUP23, POPUP123}; + int handle(int); + const Fl_Menu_Item* popup(); + Fl_Menu_Button(int,int,int,int,const char * =0); +}; + +#endif diff --git a/FL/Fl_Menu_Item.H b/FL/Fl_Menu_Item.H new file mode 100644 index 000000000..99085a8b6 --- /dev/null +++ b/FL/Fl_Menu_Item.H @@ -0,0 +1,134 @@ +// Fl_Menu_Item.H + +// The Fl_Menu_ widget has a pointer to an array of these structures. +// These are designed so that the array can be built efficiently using +// a C initialization constant. + +#ifndef Fl_Menu_Item_H +#define Fl_Menu_Item_H + +#ifndef Fl_Widget_H +// used to get the Fl_Callback typedefs: +#include "Fl_Widget.H" +#endif + +enum { // values for flags: + FL_MENU_INACTIVE = 1, + FL_MENU_TOGGLE= 2, + FL_MENU_VALUE = 4, + FL_MENU_RADIO = 8, + FL_MENU_INVISIBLE = 0x10, + FL_SUBMENU_POINTER = 0x20, + FL_SUBMENU = 0x40, + FL_MENU_DIVIDER = 0x80, + FL_MENU_HORIZONTAL = 0x100 +}; + +extern int fl_old_shortcut(const char*); + +class Fl_Menu_; + +struct Fl_Menu_Item { + const char *text; // label() + int shortcut_; + Fl_Callback *callback_; + void *user_data_; + int flags; + uchar labeltype_; + uchar labelfont_; + uchar labelsize_; + uchar labelcolor_; + + // advance N items, skipping submenus: + const Fl_Menu_Item *next(int=1) const; + Fl_Menu_Item *next(int i=1) { + return (Fl_Menu_Item*)(((const Fl_Menu_Item*)this)->next(i));} + + // methods on menu items: + const char* label() const {return text;} + void label(const char* a) {text=a;} + void label(Fl_Labeltype a,const char* b) {labeltype_ = a; text = b;} + Fl_Labeltype labeltype() const {return (Fl_Labeltype)labeltype_;} + void labeltype(Fl_Labeltype a) {labeltype_ = a;} + Fl_Color labelcolor() const {return (Fl_Color)labelcolor_;} + void labelcolor(uchar a) {labelcolor_ = a;} + Fl_Font labelfont() const {return (Fl_Font)labelfont_;} + void labelfont(uchar a) {labelfont_ = a;} + uchar labelsize() const {return labelsize_;} + void labelsize(uchar a) {labelsize_ = a;} + Fl_Callback* callback() const {return callback_;} + void callback(Fl_Callback* c, void* p) {callback_=c; user_data_=p;} + void callback(Fl_Callback* c) {callback_=c;} + void callback(Fl_Callback0*c) {callback_=(Fl_Callback*)c;} + void callback(Fl_Callback1*c, long p=0) {callback_=(Fl_Callback*)c; user_data_=(void*)p;} + void* user_data() const {return user_data_;} + void user_data(void* v) {user_data_ = v;} + long argument() const {return (long)user_data_;} + void argument(long v) {user_data_ = (void*)v;} + int shortcut() const {return shortcut_;} + void shortcut(int s) {shortcut_ = s;} + int submenu() const {return flags&(FL_SUBMENU|FL_SUBMENU_POINTER);} + int checkbox() const {return flags&FL_MENU_TOGGLE;} + int radio() const {return flags&FL_MENU_RADIO;} + int value() const {return flags&FL_MENU_VALUE;} + void set() {flags |= FL_MENU_VALUE;} + void clear() {flags &= ~FL_MENU_VALUE;} + void setonly(); + int visible() const {return !(flags&FL_MENU_INVISIBLE);} + void show() {flags &= ~FL_MENU_INVISIBLE;} + void hide() {flags |= FL_MENU_INVISIBLE;} + int active() const {return !(flags&FL_MENU_INACTIVE);} + void activate() {flags &= ~FL_MENU_INACTIVE;} + void deactivate() {flags |= FL_MENU_INACTIVE;} + int activevisible() const {return !(flags&0x11);} + + // used by menubar: + int measure(int* h, const Fl_Menu_*) const; + void draw(int x, int y, int w, int h, const Fl_Menu_*, int t=0) const; + + // popup menus without using an Fl_Menu_ widget: + const Fl_Menu_Item* popup( + int X, int Y, + const char *title = 0, + const Fl_Menu_Item* picked=0, + const Fl_Menu_* = 0) const; + const Fl_Menu_Item* pulldown( + int X, int Y, int W, int H, + const Fl_Menu_Item* picked = 0, + const Fl_Menu_* = 0, + const Fl_Menu_Item* title = 0, + int menubar=0) const; + const Fl_Menu_Item* test_shortcut() const; + const Fl_Menu_Item* find_shortcut(int *ip=0) const; + + void do_callback(Fl_Widget* o) const {callback_(o, user_data_);} + void do_callback(Fl_Widget* o,void* arg) const {callback_(o, arg);} + void do_callback(Fl_Widget* o,long arg) const {callback_(o, (void*)arg);} + + // back-compatability, do not use: + int checked() const {return flags&FL_MENU_VALUE;} + void check() {flags |= FL_MENU_VALUE;} + void uncheck() {flags &= ~FL_MENU_VALUE;} + int add(const char*, int shortcut, Fl_Callback*, void* =0, int = 0); + int add(const char*a, const char* b, Fl_Callback* c, + void* d = 0, int e = 0) { + return add(a,fl_old_shortcut(b),c,d,e);} + int size() const ; +}; + +typedef Fl_Menu_Item Fl_Menu; // back compatability + +enum { // back-compatability enum: + FL_PUP_NONE = 0, + FL_PUP_GREY = FL_MENU_INACTIVE, + FL_PUP_GRAY = FL_MENU_INACTIVE, + FL_MENU_BOX = FL_MENU_TOGGLE, + FL_PUP_BOX = FL_MENU_TOGGLE, + FL_MENU_CHECK = FL_MENU_VALUE, + FL_PUP_CHECK = FL_MENU_VALUE, + FL_PUP_RADIO = FL_MENU_RADIO, + FL_PUP_INVISIBLE = FL_MENU_INVISIBLE, + FL_PUP_SUBMENU = FL_SUBMENU_POINTER +}; + +#endif diff --git a/FL/Fl_Menu_Window.H b/FL/Fl_Menu_Window.H new file mode 100644 index 000000000..081827e2b --- /dev/null +++ b/FL/Fl_Menu_Window.H @@ -0,0 +1,29 @@ +// Fl_Menu_Window.H + +// This is the window type used by Fl_Menu to make the pop-ups. It +// draws in the overlay planes, if possible, and does other fun things +// such as turning on override_redirect. + +#ifndef Fl_Menu_Window_H +#define Fl_Menu_Window_H + +#include "Fl_Single_Window.H" + +class Fl_Menu_Window : public Fl_Single_Window { + enum {NO_OVERLAY = 128}; +public: + void show(); + void erase(); + void flush(); + void hide(); + int overlay() {return !(flags()&NO_OVERLAY);} + void set_overlay() {clear_flag(NO_OVERLAY);} + void clear_overlay() {set_flag(NO_OVERLAY);} + ~Fl_Menu_Window(); + Fl_Menu_Window(int W, int H, const char *l = 0) + : Fl_Single_Window(W,H,l) {} + Fl_Menu_Window(int X, int Y, int W, int H, const char *l = 0) + : Fl_Single_Window(X,Y,W,H,l) {} +}; + +#endif diff --git a/FL/Fl_Multi_Browser.H b/FL/Fl_Multi_Browser.H new file mode 100644 index 000000000..69a986759 --- /dev/null +++ b/FL/Fl_Multi_Browser.H @@ -0,0 +1,12 @@ +#ifndef Fl_Multi_Browser_H +#define Fl_Multi_Browser_H + +#include "Fl_Browser.H" + +class Fl_Multi_Browser : public Fl_Browser { +public: + Fl_Multi_Browser(int x,int y,int w,int h,const char *l=0) + : Fl_Browser(x,y,w,h,l) {type(FL_MULTI_BROWSER);} +}; + +#endif diff --git a/FL/Fl_Multi_Label.H b/FL/Fl_Multi_Label.H new file mode 100644 index 000000000..7a30a7497 --- /dev/null +++ b/FL/Fl_Multi_Label.H @@ -0,0 +1,18 @@ +// Fl_Multi_Label.H + +#ifndef Fl_Multi_Label_H +#define Fl_Multi_Label_H + +class Fl_Widget; +struct Fl_Menu_Item; + +struct Fl_Multi_Label { + const char* labela; + const char* labelb; + uchar typea; + uchar typeb; + void label(Fl_Widget*); + void label(Fl_Menu_Item*); +}; + +#endif diff --git a/FL/Fl_Multiline_Input.H b/FL/Fl_Multiline_Input.H new file mode 100644 index 000000000..83bc2bd35 --- /dev/null +++ b/FL/Fl_Multiline_Input.H @@ -0,0 +1,12 @@ +#ifndef Fl_Multiline_Input_H +#define Fl_Multiline_Input_H + +#include "Fl_Input.H" + +class Fl_Multiline_Input : public Fl_Input { +public: + Fl_Multiline_Input(int x,int y,int w,int h,const char *l = 0) + : Fl_Input(x,y,w,h,l) {type(FL_MULTILINE_INPUT);} +}; + +#endif diff --git a/FL/Fl_Multiline_Output.H b/FL/Fl_Multiline_Output.H new file mode 100644 index 000000000..0bf99e5d0 --- /dev/null +++ b/FL/Fl_Multiline_Output.H @@ -0,0 +1,12 @@ +#ifndef Fl_Multiline_Output_H +#define Fl_Multiline_Output_H + +#include "Fl_Output.H" + +class Fl_Multiline_Output : public Fl_Output { +public: + Fl_Multiline_Output(int x,int y,int w,int h,const char *l = 0) + : Fl_Output(x,y,w,h,l) {type(FL_MULTILINE_INPUT);} +}; + +#endif diff --git a/FL/Fl_Nice_Slider.H b/FL/Fl_Nice_Slider.H new file mode 100644 index 000000000..1bb49b47c --- /dev/null +++ b/FL/Fl_Nice_Slider.H @@ -0,0 +1,12 @@ +#ifndef Fl_Nice_Slider_H +#define Fl_Nice_Slider_H + +#include "Fl_Slider.H" + +class Fl_Nice_Slider : public Fl_Slider { +public: + Fl_Nice_Slider(int x,int y,int w,int h,const char *l=0) + : Fl_Slider(x,y,w,h,l) {type(FL_VERT_NICE_SLIDER); box(FL_FLAT_BOX);} +}; + +#endif diff --git a/FL/Fl_Object.H b/FL/Fl_Object.H new file mode 100644 index 000000000..18c1fc110 --- /dev/null +++ b/FL/Fl_Object.H @@ -0,0 +1,5 @@ +// This file is provided for back compatability only. Please use Fl_Widget +#ifndef Fl_Object +#define Fl_Object Fl_Widget +#endif +#include "Fl_Widget.H" diff --git a/FL/Fl_Output.H b/FL/Fl_Output.H new file mode 100644 index 000000000..784e3202a --- /dev/null +++ b/FL/Fl_Output.H @@ -0,0 +1,18 @@ +// Fl_Output.H +// a non-editable subclass of Fl_Input_ + +#ifndef Fl_Output_H +#define Fl_Output_H + +#include "Fl_Input_.H" + +class Fl_Output : public Fl_Input_ { +protected: + void draw(); +public: + int handle(int); + Fl_Output(int x, int y, int w, int h, const char *l = 0) + : Fl_Input_(x, y, w, h, l) {} +}; + +#endif diff --git a/FL/Fl_Overlay_Window.H b/FL/Fl_Overlay_Window.H new file mode 100644 index 000000000..76bf5bcf3 --- /dev/null +++ b/FL/Fl_Overlay_Window.H @@ -0,0 +1,31 @@ +// Fl_Overlay_Window.H + +// A window using double-buffering and able to draw an overlay +// on top of that. Uses the hardware to draw the overlay if +// possible, otherwise it just draws in the front buffer. + +#ifndef Fl_Overlay_Window_H +#define Fl_Overlay_Window_H + +#include "Fl_Double_Window.H" + +class Fl_Overlay_Window : public Fl_Double_Window { + friend class _Fl_Overlay; + virtual void draw_overlay() = 0; + Fl_Window *overlay_; +public: + void show(); + void flush(); + void hide(); + void resize(int,int,int,int); + ~Fl_Overlay_Window(); + int can_do_overlay(); + void redraw_overlay(); + Fl_Overlay_Window(int W, int H, const char *l=0) + : Fl_Double_Window(W,H,l) {overlay_ = 0;} + Fl_Overlay_Window(int X, int Y, int W, int H, const char *l=0) + : Fl_Double_Window(X,Y,W,H,l) {overlay_ = 0;} + void show(int a, char **b) {Fl_Double_Window::show(a,b);} +}; + +#endif diff --git a/FL/Fl_Pack.H b/FL/Fl_Pack.H new file mode 100644 index 000000000..5cc59439f --- /dev/null +++ b/FL/Fl_Pack.H @@ -0,0 +1,22 @@ +// Fl_Pack.H + +#ifndef Fl_Pack_H +#define Fl_Pack_H + +#include + +class Fl_Pack : public Fl_Group { + int spacing_; +public: + enum { // values for type(int) + VERTICAL = 0, + HORIZONTAL = 1 + }; + void draw(); + Fl_Pack(int x,int y,int w ,int h,const char *l = 0); + int spacing() const {return spacing_;} + void spacing(int i) {spacing_ = i;} + uchar horizontal() const {return type();} +}; + +#endif diff --git a/FL/Fl_Pixmap.H b/FL/Fl_Pixmap.H new file mode 100644 index 000000000..128761521 --- /dev/null +++ b/FL/Fl_Pixmap.H @@ -0,0 +1,22 @@ +/* Fl_Pixmap.H */ + +#ifndef Fl_Pixmap_H +#define Fl_Pixmap_H + +class Fl_Widget; +struct Fl_Menu_Item; + +struct Fl_Pixmap { + /*const*/ char * const * data; + int w, h; // set by first draw... + ulong id; // for internal use (the pixmap) + ulong mask; // for internal use (mask bitmap) + Fl_Pixmap(/*const*/char * const * d) : data(d), w(-1), h(0), id(0),mask(0) {} + ~Fl_Pixmap(); + void label(Fl_Widget*); + void label(Fl_Menu_Item*); + void draw(int X, int Y, int W, int H, int cx=0, int cy=0); + void draw(int X, int Y) {draw(X, Y, w, h, 0, 0);} +}; + +#endif diff --git a/FL/Fl_Positioner.H b/FL/Fl_Positioner.H new file mode 100644 index 000000000..6b8d4f346 --- /dev/null +++ b/FL/Fl_Positioner.H @@ -0,0 +1,51 @@ +// Fl_Positioner.H + +// The positioner widget from Forms, gives 2D input + +#ifndef Fl_Positioner_H +#define Fl_Positioner_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +class Fl_Positioner : public Fl_Widget { + + double xmin, ymin; + double xmax, ymax; + double xvalue_, yvalue_; + double xstep_, ystep_; + +protected: + + // these allow subclasses to put the dial in a smaller area: + void draw(int, int, int, int); + int handle(int, int, int, int, int); + void draw(); + +public: + + int handle(int); + Fl_Positioner(int x,int y,int w,int h, const char *l=0); + double xvalue() const {return xvalue_;} + double yvalue() const {return yvalue_;} + int xvalue(double); + int yvalue(double); + int value(double,double); + void xbounds(double, double); + double xminimum() const {return xmin;} + void xminimum(double a) {xbounds(a,xmax);} + double xmaximum() const {return xmax;} + void xmaximum(double a) {xbounds(xmin,a);} + void ybounds(double, double); + double yminimum() const {return ymin;} + void yminimum(double a) {ybounds(a,ymax);} + double ymaximum() const {return ymax;} + void ymaximum(double a) {ybounds(ymin,a);} + void xstep(double a) {xstep_ = a;} + void ystep(double a) {ystep_ = a;} + +}; + +#endif + diff --git a/FL/Fl_Radio_Button.H b/FL/Fl_Radio_Button.H new file mode 100644 index 000000000..494ea03d2 --- /dev/null +++ b/FL/Fl_Radio_Button.H @@ -0,0 +1,12 @@ +#ifndef Fl_Radio_Button_H +#define Fl_Radio_Button_H + +#include "Fl_Button.H" + +class Fl_Radio_Button : public Fl_Button { +public: + Fl_Radio_Button(int x,int y,int w,int h,const char *l=0) + : Fl_Button(x,y,w,h,l) {type(FL_RADIO_BUTTON);} +}; + +#endif diff --git a/FL/Fl_Radio_Light_Button.H b/FL/Fl_Radio_Light_Button.H new file mode 100644 index 000000000..54bb16c93 --- /dev/null +++ b/FL/Fl_Radio_Light_Button.H @@ -0,0 +1,12 @@ +#ifndef Fl_Radio_Light_Button_H +#define Fl_Radio_Light_Button_H + +#include "Fl_Light_Button.H" + +class Fl_Radio_Light_Button : public Fl_Light_Button { +public: + Fl_Radio_Light_Button(int x,int y,int w,int h,const char *l=0) + : Fl_Light_Button(x,y,w,h,l) {type(FL_RADIO_BUTTON);} +}; + +#endif diff --git a/FL/Fl_Radio_Round_Button.H b/FL/Fl_Radio_Round_Button.H new file mode 100644 index 000000000..119a9a5ff --- /dev/null +++ b/FL/Fl_Radio_Round_Button.H @@ -0,0 +1,12 @@ +#ifndef Fl_Radio_Round_Button_H +#define Fl_Radio_Round_Button_H + +#include "Fl_Round_Button.H" + +class Fl_Radio_Round_Button : public Fl_Round_Button { +public: + Fl_Radio_Round_Button(int x,int y,int w,int h,const char *l=0) + : Fl_Round_Button(x,y,w,h,l) {type(FL_RADIO_BUTTON);} +}; + +#endif diff --git a/FL/Fl_Repeat_Button.H b/FL/Fl_Repeat_Button.H new file mode 100644 index 000000000..849902a4b --- /dev/null +++ b/FL/Fl_Repeat_Button.H @@ -0,0 +1,18 @@ +// Fl_Repeat_Button.H + +// When held down, this generates callbacks repeatedly. +// Forms called this a "touch" button. + +#ifndef Fl_Repeat_Button_H +#define Fl_Repeat_Button_H +#include "Fl_Button.H" + +class Fl_Repeat_Button : public Fl_Button { + static void repeat_callback(void *); +public: + int handle(int); + Fl_Repeat_Button(int x,int y,int w,int h,const char *l=0) + : Fl_Button(x,y,w,h,l) {} +}; + +#endif diff --git a/FL/Fl_Return_Button.H b/FL/Fl_Return_Button.H new file mode 100644 index 000000000..793e578f3 --- /dev/null +++ b/FL/Fl_Return_Button.H @@ -0,0 +1,19 @@ +// Fl_Return_Button.H + +// Just like a normal button except it has a built-in shortcut for +// the Enter key and it draws a user-friendly arrow on the button. + +#ifndef Fl_Return_Button_H +#define Fl_Return_Button_H +#include "Fl_Button.H" + +class Fl_Return_Button : public Fl_Button { +protected: + void draw(); +public: + int handle(int); + Fl_Return_Button(int x,int y,int w,int h,const char *l=0) + : Fl_Button(x,y,w,h,l) {} +}; + +#endif diff --git a/FL/Fl_Roller.H b/FL/Fl_Roller.H new file mode 100644 index 000000000..ef0da9361 --- /dev/null +++ b/FL/Fl_Roller.H @@ -0,0 +1,19 @@ +// Fl_Roller.H + +// Rapid-App style knob + +#ifndef Fl_Roller_H +#define Fl_Roller_H + +#ifndef Fl_Valuator_H +#include "Fl_Valuator.H" +#endif + +class Fl_Roller : public Fl_Valuator { + void draw(); +public: + int handle(int); + Fl_Roller(int X,int Y,int W,int H,const char* L=0); +}; + +#endif diff --git a/FL/Fl_Round_Button.H b/FL/Fl_Round_Button.H new file mode 100644 index 000000000..9b7bb22d8 --- /dev/null +++ b/FL/Fl_Round_Button.H @@ -0,0 +1,15 @@ +// Fl_Round_Button.H + +// A Fl_Light_Button with a round down_box() and a red color. + +#ifndef Fl_Round_Button_H +#define Fl_Round_Button_H + +#include "Fl_Light_Button.H" + +class Fl_Round_Button : public Fl_Light_Button { +public: + Fl_Round_Button(int x,int y,int w,int h,const char *l = 0); +}; + +#endif diff --git a/FL/Fl_Round_Clock.H b/FL/Fl_Round_Clock.H new file mode 100644 index 000000000..9ad9b0042 --- /dev/null +++ b/FL/Fl_Round_Clock.H @@ -0,0 +1,12 @@ +#ifndef Fl_Round_Clock_H +#define Fl_Round_Clock_H + +#include "Fl_Clock.H" + +class Fl_Round_Clock : public Fl_Clock { +public: + Fl_Round_Clock(int x,int y,int w,int h, const char *l = 0) + : Fl_Clock(x,y,w,h,l) {type(FL_ROUND_CLOCK); box(FL_NO_BOX);} +}; + +#endif diff --git a/FL/Fl_Scroll.H b/FL/Fl_Scroll.H new file mode 100644 index 000000000..ce8c83c02 --- /dev/null +++ b/FL/Fl_Scroll.H @@ -0,0 +1,50 @@ +// Fl_Scroll.H +// A scrolling area of child widgets. + +#ifndef Fl_Scroll_H +#define Fl_Scroll_H + +#include "Fl_Group.H" +#include "Fl_Scrollbar.H" + +class Fl_Scroll : public Fl_Group { + + int xposition_, yposition_; + int width_, height_; + int oldx, oldy; + static void hscrollbar_cb(Fl_Widget*, void*); + static void scrollbar_cb(Fl_Widget*, void*); + void fix_scrollbar_order(); + static void draw_clip(void*,int,int,int,int); + void bbox(int&,int&,int&,int&); + +protected: + + void draw(); + +public: + + Fl_Scrollbar scrollbar; + Fl_Scrollbar hscrollbar; + + void resize(int,int,int,int); + int handle(int); + + Fl_Scroll(int X,int Y,int W,int H,const char*l=0); + + enum { // values for type() + HORIZONTAL = 1, + VERTICAL = 2, + BOTH = 3, + ALWAYS_ON = 4, + HORIZONTAL_ALWAYS = 5, + VERTICAL_ALWAYS = 6, + BOTH_ALWAYS = 7 + }; + + int xposition() const {return xposition_;} + int yposition() const {return yposition_;} + void position(int, int); +}; + +#endif diff --git a/FL/Fl_Scrollbar.H b/FL/Fl_Scrollbar.H new file mode 100644 index 000000000..cac210f46 --- /dev/null +++ b/FL/Fl_Scrollbar.H @@ -0,0 +1,30 @@ +// Fl_Scrollbar.H + +#ifndef Fl_Scrollbar_H +#define Fl_Scrollbar_H + +#include "Fl_Slider.H" + +class Fl_Scrollbar : public Fl_Slider { + + int linesize_; + int pushed_; + void draw(); + int handle(int); + static void timeout_cb(void*); + void increment_cb(); + +public: + + Fl_Scrollbar(int x,int y,int w,int h, const char *l = 0); + + int value() {return int(Fl_Slider::value());} + int value(int position, int size, int top, int total) { + return scrollvalue(position, size, top, total); + } + int linesize() const {return linesize_;} + void linesize(int i) {linesize_ = i;} + +}; + +#endif diff --git a/FL/Fl_Secret_Input.H b/FL/Fl_Secret_Input.H new file mode 100644 index 000000000..2a4fac8a3 --- /dev/null +++ b/FL/Fl_Secret_Input.H @@ -0,0 +1,12 @@ +#ifndef Fl_Secret_Input_H +#define Fl_Secret_Input_H + +#include "Fl_Input.H" + +class Fl_Secret_Input : public Fl_Input { +public: + Fl_Secret_Input(int x,int y,int w,int h,const char *l = 0) + : Fl_Input(x,y,w,h,l) {type(FL_SECRET_INPUT);} +}; + +#endif diff --git a/FL/Fl_Select_Browser.H b/FL/Fl_Select_Browser.H new file mode 100644 index 000000000..205b31f38 --- /dev/null +++ b/FL/Fl_Select_Browser.H @@ -0,0 +1,12 @@ +#ifndef Fl_Select_Browser_H +#define Fl_Select_Browser_H + +#include "Fl_Browser.H" + +class Fl_Select_Browser : public Fl_Browser { +public: + Fl_Select_Browser(int x,int y,int w,int h,const char *l=0) + : Fl_Browser(x,y,w,h,l) {type(FL_SELECT_BROWSER);} +}; + +#endif diff --git a/FL/Fl_Simple_Counter.H b/FL/Fl_Simple_Counter.H new file mode 100644 index 000000000..bbb316e81 --- /dev/null +++ b/FL/Fl_Simple_Counter.H @@ -0,0 +1,12 @@ +#ifndef Fl_Simple_Counter_H +#define Fl_Simple_Counter_H + +#include "Fl_Counter.H" + +class Fl_Simple_Counter : public Fl_Counter { +public: + Fl_Simple_Counter(int x,int y,int w,int h, const char *l = 0) + : Fl_Counter(x,y,w,h,l) {type(FL_SIMPLE_COUNTER);} +}; + +#endif diff --git a/FL/Fl_Single_Window.H b/FL/Fl_Single_Window.H new file mode 100644 index 000000000..79b0349c2 --- /dev/null +++ b/FL/Fl_Single_Window.H @@ -0,0 +1,20 @@ +// Fl_Single_Window.H + +#ifndef Fl_Single_Window_H +#define Fl_Single_Window_H + +#include "Fl_Window.H" + +class Fl_Single_Window : public Fl_Window { +public: + void show(); + void show(int a, char **b) {Fl_Window::show(a,b);} + void flush(); + Fl_Single_Window(int W, int H, const char *l=0) + : Fl_Window(W,H,l) {} + Fl_Single_Window(int X, int Y, int W, int H, const char *l=0) + : Fl_Window(X,Y,W,H,l) {} + int make_current(); +}; + +#endif diff --git a/FL/Fl_Slider.H b/FL/Fl_Slider.H new file mode 100644 index 000000000..148f761be --- /dev/null +++ b/FL/Fl_Slider.H @@ -0,0 +1,46 @@ +// Fl_Slider.H + +#ifndef Fl_Slider_H +#define Fl_Slider_H + +#ifndef Fl_Valuator_H +#include "Fl_Valuator.H" +#endif + +// values for type(), lowest bit indicate horizontal: +#define FL_VERT_SLIDER 0 +#define FL_HOR_SLIDER 1 +#define FL_VERT_FILL_SLIDER 2 +#define FL_HOR_FILL_SLIDER 3 +#define FL_VERT_NICE_SLIDER 4 +#define FL_HOR_NICE_SLIDER 5 + +class Fl_Slider : public Fl_Valuator { + + float slider_size_; + uchar slider_; + void _Fl_Slider(); + void draw_bg(int, int, int, int); + +protected: + + // these allow subclasses to put the slider in a smaller area: + void draw(int, int, int, int); + int handle(int, int, int, int, int); + +public: + + void draw(); + int handle(int); + Fl_Slider(int x,int y,int w,int h, const char *l = 0); + Fl_Slider(uchar t,int x,int y,int w,int h, const char *l); + + int scrollvalue(int windowtop,int windowsize,int first,int totalsize); + void bounds(double a, double b); + float slider_size() const {return slider_size_;} + void slider_size(double v); + Fl_Boxtype slider() const {return (Fl_Boxtype)slider_;} + void slider(Fl_Boxtype c) {slider_ = c;} +}; + +#endif diff --git a/FL/Fl_Tabs.H b/FL/Fl_Tabs.H new file mode 100644 index 000000000..2af820908 --- /dev/null +++ b/FL/Fl_Tabs.H @@ -0,0 +1,31 @@ +// Fl_Tabs.C + +// This is the "file card tabs" interface to allow you to put lots and lots +// of buttons and switches in a panel, as popularized by many toolkits. + +// Each child widget is a card, and it's label() is printed on the card tab. +// Clicking the tab makes that card visible. + +#ifndef Fl_Tabs_H +#define Fl_Tabs_H + +#include "Fl_Group.H" + +class Fl_Tabs : public Fl_Group { + Fl_Widget *value_; + Fl_Widget *push_; + void draw(); + int tab_positions(int*, int*); + int tab_height(); + void draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int sel=0); +public: + int handle(int); + Fl_Widget *value(); + int value(Fl_Widget *); + Fl_Widget *push() const {return push_;} + int push(Fl_Widget *); + Fl_Tabs(int,int,int,int,const char * = 0); + Fl_Widget *which(int event_x, int event_y); +}; + +#endif diff --git a/FL/Fl_Tile.H b/FL/Fl_Tile.H new file mode 100644 index 000000000..118fd2cc4 --- /dev/null +++ b/FL/Fl_Tile.H @@ -0,0 +1,18 @@ +// Fl_Tile.H - Group of 2,3 or 4 "tiles" that can be resized by +// dragging the borders between them. May be improved in the future +// to handle more tiles in arbitrary layout. + +#ifndef Fl_Tile_H +#define Fl_Tile_H + +#include "Fl_Group.H" + +class Fl_Tile : public Fl_Group { + int handle(int); +public: + Fl_Tile(int X,int Y,int W,int H,const char*l=0) : Fl_Group(X,Y,W,H,l) {} + void resize(int, int, int, int); + void position(int, int, int, int); +}; + +#endif diff --git a/FL/Fl_Timer.H b/FL/Fl_Timer.H new file mode 100644 index 000000000..7ed9e018b --- /dev/null +++ b/FL/Fl_Timer.H @@ -0,0 +1,38 @@ +// Fl_Timer.H + +// Emulate the forms Timer widget + +#ifndef Fl_Timer_H +#define Fl_Timer_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +// values for type(): +#define FL_NORMAL_TIMER 0 +#define FL_VALUE_TIMER 1 +#define FL_HIDDEN_TIMER 2 + +class Fl_Timer : public Fl_Widget { + static void stepcb(void *); + void step(); + char on, direction_; + double delay, total; + long lastsec,lastusec; +protected: + void draw(); +public: + int handle(int); + Fl_Timer(uchar t,int x,int y,int w,int h, const char *l); + ~Fl_Timer(); + void value(double); + double value() const {return delay>0.0?delay:0.0;} + char direction() const {return direction_;} + void direction(char d) {direction_ = d;} + char suspended() const {return !on;} + void suspended(char d); +}; + +#endif + diff --git a/FL/Fl_Toggle_Button.H b/FL/Fl_Toggle_Button.H new file mode 100644 index 000000000..12da9a577 --- /dev/null +++ b/FL/Fl_Toggle_Button.H @@ -0,0 +1,12 @@ +#ifndef Fl_Toggle_Button_H +#define Fl_Toggle_Button_H + +#include "Fl_Button.H" + +class Fl_Toggle_Button : public Fl_Button { +public: + Fl_Toggle_Button(int x,int y,int w,int h,const char *l=0) + : Fl_Button(x,y,w,h,l) {type(FL_TOGGLE_BUTTON);} +}; + +#endif diff --git a/FL/Fl_Toggle_Light_Button.H b/FL/Fl_Toggle_Light_Button.H new file mode 100644 index 000000000..5ac3c1b16 --- /dev/null +++ b/FL/Fl_Toggle_Light_Button.H @@ -0,0 +1,6 @@ +// provided for back-compatability only + +#ifndef Fl_Toggle_Light_Button +#include "Fl_Light_Button.H" +#define Fl_Toggle_Light_Button Fl_Light_Button +#endif diff --git a/FL/Fl_Toggle_Round_Button.H b/FL/Fl_Toggle_Round_Button.H new file mode 100644 index 000000000..18f74f7b8 --- /dev/null +++ b/FL/Fl_Toggle_Round_Button.H @@ -0,0 +1,6 @@ +// provided for back-compatability only + +#ifndef Fl_Toggle_Round_Button +#include "Fl_Round_Button.H" +#define Fl_Toggle_Round_Button Fl_Round_Button +#endif diff --git a/FL/Fl_Valuator.H b/FL/Fl_Valuator.H new file mode 100644 index 000000000..4444bdd8d --- /dev/null +++ b/FL/Fl_Valuator.H @@ -0,0 +1,59 @@ +// Fl_Valuator.H + +// Base class for sliders and all other one-value "knobs" + +#ifndef Fl_Valuator_H +#define Fl_Valuator_H + +#ifndef Fl_Widget_H +#include "Fl_Widget.H" +#endif + +// shared type() values for classes that work in both directions: +#define FL_VERTICAL 0 +#define FL_HORIZONTAL 1 + +class Fl_Valuator : public Fl_Widget { + + double value_; + double previous_value_; + double min, max; // truncates to this range *after* rounding + double A; int B; // rounds to multiples of A/B, or no rounding if A is zero + +protected: + + int horizontal() const {return type()&1;} + Fl_Valuator(int X, int Y, int W, int H, const char* L); + + double previous_value() const {return previous_value_;} + void handle_push() {previous_value_ = value_;} + double softclamp(double); + void handle_drag(double newvalue); + void handle_release(); // use drag() value + virtual void value_damage(); // cause damage() due to value() changing + +public: + + void bounds(double a, double b) {min=a; max=b;} + double minimum() const {return min;} + void minimum(double a) {min = a;} + double maximum() const {return max;} + void maximum(double a) {max = a;} + void range(double a, double b) {min = a; max = b;} + void step(int a) {A = a; B = 1;} + void step(double a, int b) {A = a; B = b;} + void step(double s); + double step() const {return A/B;} + void precision(int); + + double value() const {return value_;} + int value(double); + + virtual int format(char*); + double round(double); // round to nearest multiple of step + double clamp(double); // keep in range + double increment(double, int); // add n*step to value +}; + +#endif + diff --git a/FL/Fl_Value_Input.H b/FL/Fl_Value_Input.H new file mode 100644 index 000000000..ddb557b05 --- /dev/null +++ b/FL/Fl_Value_Input.H @@ -0,0 +1,50 @@ +// Fl_Value_Input.H + +// Edit text or drag to adjust floating point value. +// as suggested by Pierre Jasmin + +// Current behavior: +// Dragging left mouse moves by step() +// Middle mouse is 5*step() +// Right mouse is 20*step() +// clicking any mouse button puts insertion cursor there +// You can also navigate there with tab + +// Bugs (?): +// No way to select region of text +// Hard to paste in new values + +#ifndef Fl_Value_Input_H +#define Fl_Value_Input_H + +#include "Fl_Valuator.H" +#include "Fl_Input.H" + +class Fl_Value_Input : public Fl_Valuator { +public: + Fl_Input input; +private: + char soft_; + static void input_cb(Fl_Widget*,void*); + virtual void value_damage(); // cause damage() due to value() changing +public: + int handle(int); + void draw(); + void resize(int,int,int,int); + Fl_Value_Input(int x,int y,int w,int h,const char *l=0); + + void soft(char x) {soft_ = x;} + char soft() const {return soft_;} + + Fl_Font textfont() const {return input.textfont();} + void textfont(uchar s) {input.textfont(s);} + uchar textsize() const {return input.textsize();} + void textsize(uchar s) {input.textsize(s);} + Fl_Color textcolor() const {return input.textcolor();} + void textcolor(uchar n) {input.textcolor(n);} + Fl_Color cursor_color() const {return input.cursor_color();} + void cursor_color(uchar n) {input.cursor_color(n);} + +}; + +#endif diff --git a/FL/Fl_Value_Output.H b/FL/Fl_Value_Output.H new file mode 100644 index 000000000..0d1e10a7a --- /dev/null +++ b/FL/Fl_Value_Output.H @@ -0,0 +1,32 @@ +// Fl_Value_Output.H + +// Fltk widget for drag-adjusting a floating point value. +// This is much lighter than Fl_Value_Input because it has no text editor +// If you deactivate() it, it can be used to display a floating-point value + +#ifndef Fl_Value_Output_H +#define Fl_Value_Output_H + +#ifndef Fl_Valuator_H +#include "Fl_Valuator.H" +#endif + +class Fl_Value_Output : public Fl_Valuator { + uchar textfont_, textsize_, textcolor_, soft_; +public: + int handle(int); + void draw(); + Fl_Value_Output(int x,int y,int w,int h,const char *l=0); + + void soft(uchar x) {soft_ = x;} + uchar soft() const {return soft_;} + + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar s) {textfont_ = s;} + uchar textsize() const {return textsize_;} + void textsize(uchar s) {textsize_ = s;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(uchar s) {textcolor_ = s;} +}; + +#endif diff --git a/FL/Fl_Value_Slider.H b/FL/Fl_Value_Slider.H new file mode 100644 index 000000000..defc8ccde --- /dev/null +++ b/FL/Fl_Value_Slider.H @@ -0,0 +1,26 @@ +/* Fl_Value_Slider.H + + A slider with a box displaying the current value + +*/ + +#ifndef Fl_Value_Slider_H +#define Fl_Value_Slider_H + +#include "Fl_Slider.H" + +class Fl_Value_Slider : public Fl_Slider { + uchar textfont_, textsize_, textcolor_; +public: + void draw(); + int handle(int); + Fl_Value_Slider(int x,int y,int w,int h, const char *l = 0); + Fl_Font textfont() const {return (Fl_Font)textfont_;} + void textfont(uchar s) {textfont_ = s;} + uchar textsize() const {return textsize_;} + void textsize(uchar s) {textsize_ = s;} + Fl_Color textcolor() const {return (Fl_Color)textcolor_;} + void textcolor(uchar s) {textcolor_ = s;} +}; + +#endif diff --git a/FL/Fl_Widget.H b/FL/Fl_Widget.H new file mode 100644 index 000000000..d49fced1b --- /dev/null +++ b/FL/Fl_Widget.H @@ -0,0 +1,178 @@ +// Fl_Widget.H + +// fltk (Fast Light Tool Kit) version 0.99 +// Copyright (C) 1998 Bill Spitzak + +#ifndef Fl_Widget_H +#define Fl_Widget_H + +#include "Enumerations.H" + +class Fl_Widget; +class Fl_Window; + +typedef void (Fl_Callback )(Fl_Widget*, void*); +typedef void (Fl_Callback0)(Fl_Widget*); +typedef void (Fl_Callback1)(Fl_Widget*, long); + +struct Fl_Label { + const char* value; + uchar type; + uchar font; + uchar size; + uchar color; + void draw(int,int,int,int, Fl_Align) const ; + void measure(int&, int&) const ; +}; + +class Fl_Widget { + friend class Fl_Group; + + Fl_Widget* parent_; + Fl_Callback* callback_; + void* user_data_; + short x_,y_,w_,h_; + Fl_Label label_; + uchar type_; + uchar flags_; + uchar damage_; + uchar box_; + uchar color_; + uchar color2_; + uchar align_; + uchar when_; + + // "de-implement" the copy constructors: + Fl_Widget & operator=(const Fl_Widget &); + Fl_Widget(const Fl_Widget &); + +protected: + + Fl_Widget(int,int,int,int,const char* =0); + + void x(int v) {x_ = v;} + void y(int v) {y_ = v;} + void w(int v) {w_ = v;} + void h(int v) {h_ = v;} + + uchar flags() const {return flags_;} + void set_flag(int c) {flags_ |= c;} + void clear_flag(int c) {flags_ &= ~c;} + enum {INACTIVE=1, INVISIBLE=2, OUTPUT=4, SHORTCUT_LABEL=64, CHANGED=128}; + + void draw_box() const; + void draw_box(Fl_Boxtype, Fl_Color) const; + void draw_box(Fl_Boxtype, int,int,int,int, Fl_Color) const; + void draw_label() const; + void draw_label(int, int, int, int) const; + + static Fl_Font default_font_; + static int default_size_; + +public: + + virtual ~Fl_Widget(); + + virtual void draw() = 0; + virtual int handle(int); + Fl_Widget* parent() const {return parent_;} + void parent(Fl_Widget* w) {parent_ = w;} // for hacks only + + uchar type() const {return type_;} + void type(uchar t) {type_ = t;} + + int x() const {return x_;} + int y() const {return y_;} + int w() const {return w_;} + int h() const {return h_;} + virtual void resize(int,int,int,int); + int damage_resize(int,int,int,int); + void position(int X,int Y) {resize(X,Y,w_,h_);} + void size(int W,int H) {resize(x_,y_,W,H);} + + Fl_Align align() const {return (Fl_Align)align_;} + void align(uchar a) {align_ = a;} + Fl_Boxtype box() const {return (Fl_Boxtype)box_;} + void box(Fl_Boxtype a) {box_ = a;} + Fl_Color color() const {return (Fl_Color)color_;} + void color(uchar a) {color_ = a;} + Fl_Color selection_color() const {return (Fl_Color)color2_;} + void selection_color(uchar a) {color2_ = a;} + void color(uchar a, uchar b) {color_=a; color2_=b;} + const char* label() const {return label_.value;} + void label(const char* a) {label_.value=a;} + void label(Fl_Labeltype a,const char* b) {label_.type = a; label_.value = b;} + Fl_Labeltype labeltype() const {return (Fl_Labeltype)label_.type;} + void labeltype(Fl_Labeltype a) {label_.type = a;} + Fl_Color labelcolor() const {return (Fl_Color)label_.color;} + void labelcolor(uchar a) {label_.color=a;} + Fl_Font labelfont() const {return (Fl_Font)label_.font;} + void labelfont(uchar a) {label_.font=a;} + uchar labelsize() const {return label_.size;} + void labelsize(uchar a) {label_.size=a;} + Fl_Callback* callback() const {return callback_;} + void callback(Fl_Callback* c, void* p) {callback_=c; user_data_=p;} + void callback(Fl_Callback* c) {callback_=c;} + void callback(Fl_Callback0*c) {callback_=(Fl_Callback*)c;} + void callback(Fl_Callback1*c, long p=0) {callback_=(Fl_Callback*)c; user_data_=(void*)p;} + void* user_data() const {return user_data_;} + void user_data(void* v) {user_data_ = v;} + long argument() const {return (long)user_data_;} + void argument(long v) {user_data_ = (void*)v;} + Fl_When when() const {return (Fl_When)when_;} + void when(uchar i) {when_ = i;} + + static void default_font(Fl_Font b) {default_font_ = b;} + static Fl_Font default_font() {return default_font_;} + static void default_size(int b) {default_size_ = b;} + static int default_size() {return default_size_;} + + int visible() const {return !(flags_&INVISIBLE);} + int visible_r() const; + void show(); + void hide(); + void set_visible() {flags_ &= ~INVISIBLE;} + void clear_visible() {flags_ |= INVISIBLE;} + int active() const {return !(flags_&INACTIVE);} + int active_r() const; + void activate(); + void deactivate(); + int output() const {return (flags_&OUTPUT);} + void set_output() {flags_ |= OUTPUT;} + void clear_output() {flags_ &= ~OUTPUT;} + int takesevents() const {return !(flags_&(INACTIVE|INVISIBLE|OUTPUT));} + int changed() const {return flags_&CHANGED;} + void set_changed() {flags_ |= CHANGED;} + void clear_changed() {flags_ &= ~CHANGED;} + int take_focus(); + + static void default_callback(Fl_Widget*, void*); + void do_callback() {callback_(this,user_data_);} + void do_callback(Fl_Widget* o,void* arg=0) {callback_(o,arg);} + void do_callback(Fl_Widget* o,long arg) {callback_(o,(void*)arg);} + int test_shortcut(); + static int test_shortcut(const char*); + int contains(const Fl_Widget*) const ; + int inside(const Fl_Widget* o) const {return o ? o->contains(this) : 0;} + + void redraw(); + uchar damage() const {return damage_;} + void clear_damage(uchar c = 0) {damage_ = c;} + void damage(uchar c); + void damage(uchar c,int,int,int,int); + void draw_label(int, int, int, int, Fl_Align) const; + void measure_label(int& x, int& y) {label_.measure(x,y);} + + Fl_Window* window() const ; + + // back compatability only: + Fl_Color color2() const {return (Fl_Color)color2_;} + void color2(uchar a) {color2_ = a;} +}; + +// reserved type numbers (necessary for my cheapo RTTI) start here. +// grep the header files for "RESERVED_TYPE" to find the next available +// number. +#define FL_RESERVED_TYPE 100 + +#endif diff --git a/FL/Fl_Window.H b/FL/Fl_Window.H new file mode 100644 index 000000000..b365f67cf --- /dev/null +++ b/FL/Fl_Window.H @@ -0,0 +1,90 @@ +// Fl_Window.H + +// fltk (Fast Light Tool Kit) version 0.99 +// Copyright (C) 1998 Bill Spitzak + +#ifndef Fl_Window_H +#define Fl_Window_H + +#include "Fl_Group.H" + +#define FL_WINDOW 0xF0 // all subclasses have type() >= this + +class Fl_Window : public Fl_Group { + + friend class Fl_X; Fl_X *i; // points at the system-specific stuff + + const char* iconlabel_; + const char* xclass_; + // size_range stuff: + short minw, minh, maxw, maxh; + uchar dw, dh, aspect, size_range_set; + void size_range_(); + // values for flags(): + enum { + FL_MODAL = 64, + FL_NOBORDER = 8, + FL_FORCE_POSITION = 16, + FL_NON_MODAL = 32 + }; + static Fl_Window *current_; + void _Fl_Window(); // constructor innards + +protected: + + virtual void draw(); + virtual void flush(); + +public: + + Fl_Window(int,int,int,int, const char* = 0); + Fl_Window(int,int, const char* = 0); + virtual ~Fl_Window(); + + virtual int handle(int); + + virtual void resize(int,int,int,int); + void border(int b); + void clear_border() {set_flag(FL_NOBORDER);} + int border() const {return !(flags() & FL_NOBORDER);} + void set_modal() {set_flag(FL_MODAL);} + uchar modal() const {return flags() & FL_MODAL;} + void set_non_modal() {set_flag(FL_NON_MODAL);} + uchar non_modal() const {return flags() & (FL_NON_MODAL|FL_MODAL);} + + void hotspot(int x, int y, int offscreen = 0); + void hotspot(const Fl_Widget*, int offscreen = 0); + void hotspot(const Fl_Widget& p, int offscreen = 0) {hotspot(&p,offscreen);} + void free_position() {clear_flag(FL_FORCE_POSITION);} + void size_range(int a, int b, int c=0, int d=0, int e=0, int f=0, int g=0) { + minw=a; minh=b; maxw=c; maxh=d; dw=e; dh=f; aspect=g; size_range_();} + + const char* label() const {return Fl_Widget::label();} + const char* iconlabel() const {return iconlabel_;} + void label(const char*); + void iconlabel(const char*); + void label(const char* label, const char* iconlabel); + const char* xclass() const {return xclass_;} + void xclass(const char* c) {xclass_ = c;} + + int shown() {return i != 0;} + virtual void show(); + virtual void hide(); + void show(int, char**); + void fullscreen(); + void fullscreen_off(int,int,int,int); + void iconize(); + + int x_root() const ; + int y_root() const ; + + static Fl_Window *current() {return current_;} + void make_current(); + + // for back-compatability only: + void cursor(Fl_Cursor, Fl_Color=FL_BLACK, Fl_Color=FL_WHITE); + static void default_callback(Fl_Window*, void* v); + +}; + +#endif diff --git a/FL/dirent.h b/FL/dirent.h new file mode 100644 index 000000000..2ddc15dae --- /dev/null +++ b/FL/dirent.h @@ -0,0 +1,4 @@ +// this file is for back-compatability only +#include "fl_scandir.H" + + diff --git a/FL/filename.H b/FL/filename.H new file mode 100644 index 000000000..2952108e7 --- /dev/null +++ b/FL/filename.H @@ -0,0 +1,41 @@ +// filename.H + +// fltk filename utilities. These are used by the file chooser but may +// be useful to other programs. + +#ifndef FL_PATH_MAX + +#define FL_PATH_MAX 256 // all buffers are this length + +const char *filename_name(const char *); // return pointer to name +const char *filename_ext(const char *); // return pointer to .ext +char *filename_setext(char *,const char *ext); // clobber .ext +int filename_expand(char *, const char *from); // do $x and ~x +int filename_absolute(char *, const char *from); // prepend getcwd() +int filename_match(const char *, const char *pattern); // glob match +int filename_isdir(const char*); + +// Portable "scandir" function. Ugly but apparently necessary... + +#ifdef WIN32 + +struct dirent {char d_name[1];}; + +#else + +#include +#include +// warning: on some systems (very few nowadays?) may not exist. +// The correct information is in one of these files: +//#include +//#include +//#include +// plus you must do the following #define: +//#define dirent direct +// It would be best to create a file that does this... + +#endif + +int filename_list(const char *d, dirent ***list); + +#endif diff --git a/FL/fl_ask.H b/FL/fl_ask.H new file mode 100644 index 000000000..8671e0140 --- /dev/null +++ b/FL/fl_ask.H @@ -0,0 +1,51 @@ +// fl_ask.H + +// Pop-up window utilities +// This header file is usable without including any other fltk headers + +#ifndef fl_ask_H +#define fl_ask_H + +class Fl_Widget; + +void fl_message(const char *); +void fl_alert(const char *); +int fl_ask(const char *); +int fl_choice(const char *q,const char *b0,const char *b1,const char *b2); +const char *fl_input(const char *label, const char *deflt, unsigned char type); +const char *fl_input(const char *label, const char *deflt = 0); +inline const char *fl_password(const char *label, const char *deflt = 0) { + return fl_input(label, deflt, 5); +} +Fl_Widget *fl_message_icon(); +extern unsigned char fl_message_font_; +extern unsigned char fl_message_size_; +inline void fl_message_font(unsigned char f,unsigned char s) { + fl_message_font_ = f; fl_message_size_ = s;} + +// pointers you can use to change fltk to a foreign language: +extern const char* fl_no; +extern const char* fl_yes; +extern const char* fl_ok; +extern const char* fl_cancel; + +// back compatability and XForms compatability functions: + +inline int fl_show_question(const char *c) {return fl_ask(c);} +void fl_show_message(const char *,const char *,const char *); +void fl_show_alert(const char *,const char *,const char *); +int fl_show_question(const char *,const char *,const char *); +inline const char *fl_show_input(const char *l,const char*d=0) {return fl_input(l,d);} +/*const*/ char *fl_show_simple_input(const char *label, const char *deflt = 0); + +// all are implemented using this: +int fl_show_choice( + const char *m1, + const char *m2, + const char *m3, + int numb, + const char *b0, + const char *b1, + const char *b2); + +#endif diff --git a/FL/fl_draw.H b/FL/fl_draw.H new file mode 100644 index 000000000..49b7c51c4 --- /dev/null +++ b/FL/fl_draw.H @@ -0,0 +1,135 @@ +// fl_draw.H +// Portable drawing functions + +#ifndef fl_draw_H +#define fl_draw_H + +#include "Enumerations.H" // for the color names + +// Colors: +void fl_color(Fl_Color); // select indexed color +inline void fl_color(int c) {fl_color((Fl_Color)c);} // for back compatability +void fl_color(uchar, uchar, uchar); // select actual color +extern Fl_Color fl_color_; inline Fl_Color fl_color() {return fl_color_;} + +// clip: +void fl_clip(int x, int y, int w, int h); +#define fl_push_clip fl_clip +void fl_push_no_clip(); +void fl_pop_clip(); +int fl_not_clipped(int x, int y, int w, int h); +int fl_clip_box(int, int, int, int, int& x, int& y, int& w, int& h); + +// points: +void fl_point(int x, int y); + +// rectangles tweaked to exactly fill the pixel rectangle: +void fl_rect(int x, int y, int w, int h); +void fl_rectf(int x, int y, int w, int h); + +// line segments: +void fl_line(int,int, int,int); +void fl_line(int,int, int,int, int,int); + +// closed line segments: +void fl_loop(int,int, int,int, int,int); +void fl_loop(int,int, int,int, int,int, int,int); + +// filled polygons +void fl_polygon(int,int, int,int, int,int); +void fl_polygon(int,int, int,int, int,int, int,int); + +// draw rectilinear lines, horizontal segment first: +void fl_xyline(int x, int y, int x1); +void fl_xyline(int x, int y, int x1, int y2); +void fl_xyline(int x, int y, int x1, int y2, int x3); + +// draw rectilinear lines, vertical segment first: +void fl_yxline(int x, int y, int y1); +void fl_yxline(int x, int y, int y1, int x2); +void fl_yxline(int x, int y, int y1, int x2, int y3); + +// circular lines and pie slices (code in fl_arci.C): +void fl_arc(int x, int y, int w, int h, double a1, double a2); +void fl_pie(int x, int y, int w, int h, double a1, double a2); +void fl_chord(int x, int y, int w, int h, double a1, double a2); // nyi + +// scalable drawing code (code in fl_vertex.C and fl_arc.C): +void fl_push_matrix(); +void fl_pop_matrix(); +void fl_scale(double x, double y); +void fl_scale(double x); +void fl_translate(double x, double y); +void fl_rotate(double d); +void fl_mult_matrix(double a, double b, double c, double d, double x,double y); +void fl_begin_points(); +void fl_begin_line(); +void fl_begin_loop(); +void fl_begin_polygon(); +void fl_vertex(double x, double y); +void fl_curve(double, double, double, double, double, double, double, double); +void fl_arc(double x, double y, double r, double start, double a); +void fl_circle(double x, double y, double r); +void fl_end_points(); +void fl_end_line(); +void fl_end_loop(); +void fl_end_polygon(); +void fl_begin_complex_polygon(); +void fl_gap(); +void fl_end_complex_polygon(); +// get and use transformed positions: +double fl_transform_x(double x, double y); +double fl_transform_y(double x, double y); +double fl_transform_dx(double x, double y); +double fl_transform_dy(double x, double y); +void fl_transformed_vertex(double x, double y); + +// current font: +void fl_font(int face, int size); +void fl_font(int face, int size, Fl_Font default_font, int default_size); +extern int fl_font_; inline int fl_font() {return fl_font_;} +extern int fl_size_; inline int fl_size() {return fl_size_;} + +// information you can get about the current font: +int fl_height(); // using "size" should work ok +int fl_descent(); +double fl_width(const char*); +double fl_width(const char*, int n); +double fl_width(uchar); + +// draw using current font: +void fl_draw(const char*, int x, int y); +void fl_draw(const char*, int n, int x, int y); +void fl_draw(const char*, int x, int y, int w, int h, Fl_Align); +void fl_measure(const char*, int& x, int& y); + +// boxtypes: +void fl_frame(const char* s, int x, int y, int w, int h); +void fl_frame2(const char* s, int x, int y, int w, int h); +void fl_draw_box(Fl_Boxtype, int x, int y, int w, int h, Fl_Color); + +// images: +void fl_draw_image(const uchar*, int,int,int,int, int delta=3, int ldelta=0); +void fl_draw_image_mono(const uchar*, int,int,int,int, int delta=1, int ld=0); +typedef void (*Fl_Draw_Image_Cb)(void*,int,int,int,uchar*); +void fl_draw_image(Fl_Draw_Image_Cb, void*, int,int,int,int, int delta=3); +void fl_draw_image_mono(Fl_Draw_Image_Cb, void*, int,int,int,int, int delta=1); +void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b); + +// pixmaps: +int fl_draw_pixmap(/*const*/ char* const* data, int x,int y,Fl_Color=FL_GRAY); +int fl_measure_pixmap(/*const*/ char* const* data, int &w, int &h); + +// other: +extern void fl_scroll(int X, int Y, int W, int H, int dx, int dy, + void (*draw_area)(void*, int,int,int,int), void* data); +const char* fl_shortcut_label(int); +void fl_overlay_rect(int,int,int,int); +void fl_overlay_clear(); +void fl_cursor(Fl_Cursor, Fl_Color=FL_BLACK, Fl_Color=FL_WHITE); + +// XForms symbols: +int fl_draw_symbol(const char* label,int x,int y,int w,int h, Fl_Color); +int fl_add_symbol(const char* name, void (*drawit)(Fl_Color), int scalable); + +#endif diff --git a/FL/fl_file_chooser.H b/FL/fl_file_chooser.H new file mode 100644 index 000000000..82fef8bbc --- /dev/null +++ b/FL/fl_file_chooser.H @@ -0,0 +1,9 @@ +// fl_file_chooser.H + +#ifndef fl_file_chooser_H +#define fl_file_chooser_H + +char *fl_file_chooser(const char *message,const char *pat,const char *fname); +void fl_file_chooser_callback(void (*cb)(const char *)); + +#endif diff --git a/FL/fl_message.H b/FL/fl_message.H new file mode 100644 index 000000000..c03141c07 --- /dev/null +++ b/FL/fl_message.H @@ -0,0 +1,2 @@ +// fl_message.H +#include "fl_ask.H" diff --git a/FL/fl_show_colormap.H b/FL/fl_show_colormap.H new file mode 100644 index 000000000..eb6b0f361 --- /dev/null +++ b/FL/fl_show_colormap.H @@ -0,0 +1,10 @@ +// fl_show_colormap.H + +// Color picker copied from Forms + +#ifndef fl_show_colormap_H +#define fl_show_colormap_H + +Fl_Color fl_show_colormap(Fl_Color oldcol); + +#endif diff --git a/FL/fl_show_input.H b/FL/fl_show_input.H new file mode 100644 index 000000000..9635836ad --- /dev/null +++ b/FL/fl_show_input.H @@ -0,0 +1,2 @@ +// fl_show_input.H +#include "fl_ask.H" diff --git a/FL/forms.H b/FL/forms.H new file mode 100644 index 000000000..87ca5afc0 --- /dev/null +++ b/FL/forms.H @@ -0,0 +1,810 @@ +// forms.h + +// Include file for emulating the original Mark Overmars +// Forms library. Based on version 0.86, 3/22/97 +// Warning: emulation is in no way 100%!! + +#ifndef __FORMS_H__ +#define __FORMS_H__ + +#include "Fl.H" +#include "Fl_Group.H" +#include "Fl_Window.H" +#include "fl_draw.H" + +typedef Fl_Widget FL_OBJECT; +typedef Fl_Window FL_FORM; + +//////////////////////////////////////////////////////////////// +// Random constants & symbols defined by forms.h file: + +#ifndef NULL +#define NULL 0 +#endif +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +#define FL_ON 1 +#define FL_OK 1 +#define FL_VALID 1 +#define FL_PREEMPT 1 +#define FL_AUTO 2 +#define FL_WHEN_NEEDED FL_AUTO +#define FL_OFF 0 +#define FL_NONE 0 +#define FL_CANCEL 0 +#define FL_INVALID 0 +#define FL_IGNORE -1 +#define FL_CLOSE -2 + +#define FL_LCOL FL_BLACK +#define FL_COL1 FL_GRAY +#define FL_MCOL FL_LIGHT1 +#define FL_LEFT_BCOL FL_LIGHT3 // 53 is better match +#define FL_TOP_BCOL FL_LIGHT2 // 51 +#define FL_BOTTOM_BCOL FL_DARK2 // 40 +#define FL_RIGHT_BCOL FL_DARK3 // 36 +#define FL_INACTIVE FL_INACTIVE_COLOR +#define FL_INACTIVE_COL FL_INACTIVE_COLOR +#define FL_FREE_COL1 FL_FREE_COLOR +#define FL_FREE_COL2 ((Fl_Color)(FL_FREE_COLOR+1)) +#define FL_FREE_COL3 ((Fl_Color)(FL_FREE_COLOR+2)) +#define FL_FREE_COL4 ((Fl_Color)(FL_FREE_COLOR+3)) +#define FL_FREE_COL5 ((Fl_Color)(FL_FREE_COLOR+4)) +#define FL_FREE_COL6 ((Fl_Color)(FL_FREE_COLOR+5)) +#define FL_FREE_COL7 ((Fl_Color)(FL_FREE_COLOR+6)) +#define FL_FREE_COL8 ((Fl_Color)(FL_FREE_COLOR+7)) +#define FL_FREE_COL9 ((Fl_Color)(FL_FREE_COLOR+8)) +#define FL_FREE_COL10 ((Fl_Color)(FL_FREE_COLOR+9)) +#define FL_FREE_COL11 ((Fl_Color)(FL_FREE_COLOR+10)) +#define FL_FREE_COL12 ((Fl_Color)(FL_FREE_COLOR+11)) +#define FL_FREE_COL13 ((Fl_Color)(FL_FREE_COLOR+12)) +#define FL_FREE_COL14 ((Fl_Color)(FL_FREE_COLOR+13)) +#define FL_FREE_COL15 ((Fl_Color)(FL_FREE_COLOR+14)) +#define FL_FREE_COL16 ((Fl_Color)(FL_FREE_COLOR+15)) +#define FL_TOMATO ((Fl_Color)(131)) +#define FL_INDIANRED ((Fl_Color)(164)) +#define FL_SLATEBLUE ((Fl_Color)(195)) +#define FL_DARKGOLD ((Fl_Color)(84)) +#define FL_PALEGREEN ((Fl_Color)(157)) +#define FL_ORCHID ((Fl_Color)(203)) +#define FL_DARKCYAN ((Fl_Color)(189)) +#define FL_DARKTOMATO ((Fl_Color)(113)) +#define FL_WHEAT ((Fl_Color)(174)) + +#define FL_ALIGN_BESIDE FL_ALIGN_INSIDE + +#define FL_PUP_TOGGLE 2 // FL_MENU_TOGGLE +#define FL_PUP_INACTIVE 1 // FL_MENU_INACTIVE +#define FL_NO_FRAME FL_NO_BOX +#define FL_ROUNDED3D_UPBOX FL_ROUND_UP_BOX +#define FL_ROUNDED3D_DOWNBOX FL_ROUND_DOWN_BOX +#define FL_OVAL3D_UPBOX FL_ROUND_UP_BOX +#define FL_OVAL3D_DOWNBOX FL_ROUND_DOWN_BOX + +#define FL_MBUTTON1 1 +#define FL_LEFT_MOUSE 1 +#define FL_LEFTMOUSE 1 +#define FL_MBUTTON2 2 +#define FL_MIDDLE_MOUSE 2 +#define FL_MIDDLEMOUSE 2 +#define FL_MBUTTON3 3 +#define FL_RIGHT_MOUSE 3 +#define FL_RIGHTMOUSE 3 +#define FL_MBUTTON4 4 +#define FL_MBUTTON5 5 + +#define FL_INVALID_STYLE 255 +#define FL_NORMAL_STYLE FL_HELVETICA +#define FL_BOLD_STYLE FL_HELVETICA_BOLD +#define FL_ITALIC_STYLE FL_HELVETICA_ITALIC +#define FL_BOLDITALIC_STYLE FL_HELVETICA_BOLD_ITALIC +#define FL_FIXED_STYLE FL_COURIER +#define FL_FIXEDBOLD_STYLE FL_COURIER_BOLD +#define FL_FIXEDITALIC_STYLE FL_COURIER_ITALIC +#define FL_FIXEDBOLDITALIC_STYLE FL_COURIER_BOLD_ITALIC +#define FL_TIMES_STYLE FL_TIMES +#define FL_TIMESBOLD_STYLE FL_TIMES_BOLD +#define FL_TIMESITALIC_STYLE FL_TIMES_ITALIC +#define FL_TIMESBOLDITALIC_STYLE FL_TIMES_BOLD_ITALIC + +// hacks to change the labeltype() when passed to fl_set_object_lstyle(): +#define FL_SHADOW_STYLE (FL_SHADOW_LABEL<<8) +#define FL_ENGRAVED_STYLE (FL_ENGRAVED_LABEL<<8) +#define FL_EMBOSSED_STYLE (FL_EMBOSSED_LABEL<<0) + +// size values are different from XForms, match older Forms: +#define FL_TINY_SIZE 8 +#define FL_SMALL_SIZE 11 // 10 +#define FL_NORMAL_SIZE 14 // 12 +#define FL_MEDIUM_SIZE 18 // 14 +#define FL_LARGE_SIZE 24 // 18 +#define FL_HUGE_SIZE 32 // 24 +#define FL_DEFAULT_SIZE FL_SMALL_SIZE +#define FL_TINY_FONT FL_TINY_SIZE +#define FL_SMALL_FONT FL_SMALL_SIZE +#define FL_NORMAL_FONT FL_NORMAL_SIZE +#define FL_MEDIUM_FONT FL_MEDIUM_SIZE +#define FL_LARGE_FONT FL_LARGE_SIZE +#define FL_HUGE_FONT FL_HUGE_SIZE +#define FL_NORMAL_FONT1 FL_SMALL_FONT +#define FL_NORMAL_FONT2 FL_NORMAL_FONT +#define FL_DEFAULT_FONT FL_SMALL_FONT + +#define FL_RETURN_END_CHANGED FL_WHEN_RELEASE +#define FL_RETURN_CHANGED FL_WHEN_CHANGED +#define FL_RETURN_END FL_WHEN_RELEASE_ALWAYS +#define FL_RETURN_ALWAYS (FL_WHEN_CHANGED|FL_WHEN_NOT_CHANGED) + +#define FL_BOUND_WIDTH 3 + +typedef int FL_Coord; +typedef int FL_COLOR; + +//////////////////////////////////////////////////////////////// +// fltk interaction: + +#define FL_CMD_OPT void +extern void fl_initialize(int*, char*[], const char*, FL_CMD_OPT*, int); +inline void fl_finish() {} + +typedef void (*FL_IO_CALLBACK) (int, void*); +inline void fl_add_io_callback(int fd, short w, FL_IO_CALLBACK cb, void* v) { + Fl::add_fd(fd,w,cb,v);} +inline void fl_remove_io_callback(int fd, short, FL_IO_CALLBACK) { + Fl::remove_fd(fd);} // removes all the callbacks! + +// type of callback is different and no "id" number is returned: +inline void fl_add_timeout(long msec, void (*cb)(void*), void* v) { + Fl::add_timeout(msec*.001, cb, v);} +inline void fl_remove_timeout(int) {} + +// type of callback is different! +inline void fl_set_idle_callback(void (*cb)()) {Fl::set_idle(cb);} + +Fl_Widget* fl_do_forms(void); +Fl_Widget* fl_check_forms(); +inline Fl_Widget* fl_do_only_forms(void) {return fl_do_forms();} +inline Fl_Widget* fl_check_only_forms(void) {return fl_check_forms();} + +// because of new redraw behavior, these are no-ops: +inline void fl_freeze_object(Fl_Widget*) {} +inline void fl_unfreeze_object(Fl_Widget*) {} +inline void fl_freeze_form(Fl_Window*) {} +inline void fl_unfreeze_form(Fl_Window*) {} +inline void fl_freeze_all_forms() {} +inline void fl_unfreeze_all_forms() {} + +inline void fl_set_focus_object(Fl_Window*, Fl_Widget* o) {Fl::focus(o);} +inline void fl_reset_focus_object(Fl_Widget* o) {Fl::focus(o);} +#define fl_set_object_focus fl_set_focus_object + +// void fl_set_form_atclose(Fl_Window*w,int (*cb)(Fl_Window*,void*),void* v) +// void fl_set_atclose(int (*cb)(Fl_Window*,void*),void*) +// fl_set_form_atactivate/atdeactivate not implemented! + +//////////////////////////////////////////////////////////////// +// Fl_Widget: + +inline void fl_set_object_boxtype(Fl_Widget* o, Fl_Boxtype a) {o->box(a);} +inline void fl_set_object_lsize(Fl_Widget* o,int s) {o->labelsize(s);} +inline void fl_set_object_lstyle(Fl_Widget* o,int a) { + o->labelfont((uchar)a); o->labeltype((Fl_Labeltype)(a>>8));} +inline void fl_set_object_lcol(Fl_Widget* o, uchar a) {o->labelcolor(a);} +#define fl_set_object_lcolor fl_set_object_lcol +inline void fl_set_object_lalign(Fl_Widget* o, Fl_Align a) {o->align(a);} +#define fl_set_object_align fl_set_object_lalign +inline void fl_set_object_color(Fl_Widget* o,uchar a,uchar b) {o->color(a,b);} +inline void fl_set_object_label(Fl_Widget* o, const char* a) {o->label(a); o->redraw();} +inline void fl_set_object_position(Fl_Widget*o,int x,int y) {o->position(x,y);} +inline void fl_set_object_size(Fl_Widget* o, int w, int h) {o->size(w,h);} +inline void fl_set_object_geometry(Fl_Widget* o,int x,int y,int w,int h) {o->resize(x,y,w,h);} + +inline void fl_get_object_geometry(Fl_Widget* o,int*x,int*y,int*w,int*h) { + *x = o->x(); *y = o->y(); *w = o->w(); *h = o->h();} +inline void fl_get_object_position(Fl_Widget* o,int*x,int*y) { + *x = o->x(); *y = o->y();} + +typedef void (*Forms_CB)(Fl_Widget*, long); +inline void fl_set_object_callback(Fl_Widget*o,Forms_CB c,long a) {o->callback(c,a);} +#define fl_set_call_back fl_set_object_callback +inline void fl_call_object_callback(Fl_Widget* o) {o->do_callback();} +inline void fl_trigger_object(Fl_Widget* o) {o->do_callback();} +inline void fl_set_object_return(Fl_Widget* o, int v) { + o->when((Fl_When)(v|FL_WHEN_RELEASE));} + +inline void fl_redraw_object(Fl_Widget* o) {o->redraw();} +inline void fl_show_object(Fl_Widget* o) {o->show();} +inline void fl_hide_object(Fl_Widget* o) {o->hide();} +inline void fl_free_object(Fl_Widget* x) {delete x;} +inline void fl_delete_object(Fl_Widget* o) {((Fl_Group*)(o->parent()))->remove(*o);} +inline void fl_activate_object(Fl_Widget* o) {o->activate();} +inline void fl_deactivate_object(Fl_Widget* o) {o->deactivate();} + +inline void fl_add_object(Fl_Window* f, Fl_Widget* x) {f->add(x);} +inline void fl_insert_object(Fl_Widget* o, Fl_Widget* b) { + ((Fl_Group*)(b->parent()))->insert(*o,b);} + +inline Fl_Window* FL_ObjWin(Fl_Widget* o) {return o->window();} + +//////////////////////////////////////////////////////////////// +// things that appered in the demos a lot that I don't emulate, but +// I did not want to edit out of all the demos... + +inline int fl_get_border_width() {return 3;} +inline void fl_set_border_width(int) {} +inline void fl_set_object_dblbuffer(Fl_Widget*, int) {} +inline void fl_set_form_dblbuffer(Fl_Window*, int) {} + +//////////////////////////////////////////////////////////////// +// Fl_Window: + +inline void fl_free_form(Fl_Window* x) {delete x;} +inline void fl_redraw_form(Fl_Window* f) {f->redraw();} + +inline Fl_Window* fl_bgn_form(Fl_Boxtype b,int w,int h) { + Fl_Window* g = new Fl_Window(w,h,0); + g->box(b); + return g; +} +void fl_end_form(); +inline void fl_addto_form(Fl_Window* f) {f->begin();} +inline Fl_Group* fl_bgn_group() {return new Fl_Group(0,0,0,0,0);} +inline void fl_end_group() {Fl_Group::current()->forms_end();} +inline void fl_addto_group(Fl_Widget* o) {((Fl_Group* )o)->begin();} +#define resizebox _ddfdesign_kludge() + +inline void fl_scale_form(Fl_Window* f, double x, double y) { + f->resizable(f); f->size(int(f->w()*x),int(f->h()*y));} +inline void fl_set_form_position(Fl_Window* f,int x,int y) {f->position(x,y);} +inline void fl_set_form_size(Fl_Window* f, int w, int h) {f->size(w,h);} +inline void fl_set_form_geometry(Fl_Window* f,int x,int y,int w,int h) { + f->resize(x,y,w,h);} +#define fl_set_initial_placement fl_set_form_geometry +inline void fl_adjust_form_size(Fl_Window*) {} + +void fl_show_form(Fl_Window* f,int p,int b,const char* n); +enum { // "p" argument values: + FL_PLACE_FREE = 0, // make resizable + FL_PLACE_MOUSE = 1, // mouse centered on form + FL_PLACE_CENTER = 2, // center of the screen + FL_PLACE_POSITION = 4,// fixed position, resizable + FL_PLACE_SIZE = 8, // fixed size, normal fltk behavior + FL_PLACE_GEOMETRY =16,// fixed size and position + FL_PLACE_ASPECT = 32, // keep aspect ratio (ignored) + FL_PLACE_FULLSCREEN=64,// fill screen + FL_PLACE_HOTSPOT = 128,// enables hotspot + FL_PLACE_ICONIC = 256,// iconic (ignored) + FL_FREE_SIZE=(1<<14), // force resizable + FL_FIX_SIZE =(1<<15) // force off resizable +}; +#define FL_PLACE_FREE_CENTER (FL_PLACE_CENTER|FL_FREE_SIZE) +#define FL_PLACE_CENTERFREE (FL_PLACE_CENTER|FL_FREE_SIZE) +enum { // "b" arguement values: + FL_NOBORDER = 0, + FL_FULLBORDER, + FL_TRANSIENT +//FL_MODAL = (1<<8) // not implemented yet in Forms +}; +inline void fl_set_form_hotspot(Fl_Window* w,int x,int y) {w->hotspot(x,y);} +inline void fl_set_form_hotobject(Fl_Window* w, Fl_Widget* o) {w->hotspot(o);} +extern char fl_flip; // in forms.C +inline void fl_flip_yorigin() {fl_flip = 1;} + +#define fl_prepare_form_window fl_show_form +inline void fl_show_form_window(Fl_Window*) {} + +inline void fl_raise_form(Fl_Window* f) {f->show();} + +inline void fl_hide_form(Fl_Window* f) {f->hide();} +inline void fl_pop_form(Fl_Window* f) {f->show();} + +extern char fl_modal_next; // in forms.C +inline void fl_activate_all_forms() {} +inline void fl_deactivate_all_forms() {fl_modal_next = 1;} +inline void fl_deactivate_form(Fl_Window*w) {w->deactivate();} +inline void fl_activate_form(Fl_Window*w) {w->activate();} + +inline void fl_set_form_title(Fl_Window* f, const char* s) {f->label(s);} +inline void fl_title_form(Fl_Window* f, const char* s) {f->label(s);} + +typedef void (*Forms_FormCB)(Fl_Widget*); +inline void fl_set_form_callback(Fl_Window* f,Forms_FormCB c) {f->callback(c);} +#define fl_set_form_call_back fl_set_form_callback + +inline void fl_init() {} +void fl_set_graphics_mode(int,int); + +inline int fl_form_is_visible(Fl_Window* f) {return f->visible();} + +inline int fl_mouse_button() {return Fl::event_button();} +#define fl_mousebutton fl_mouse_button + +#define fl_free free +#define fl_malloc malloc +#define fl_calloc calloc +#define fl_realloc realloc + +//////////////////////////////////////////////////////////////// +// Drawing functions. Only usable inside an Fl_Free object? + +inline void fl_drw_box(Fl_Boxtype b,int x,int y,int w,int h,Fl_Color bgc,int=3) { + fl_draw_box(b,x,y,w,h,bgc);} +inline void fl_drw_frame(Fl_Boxtype b,int x,int y,int w,int h,Fl_Color bgc,int=3) { + fl_draw_box(b,x,y,w,h,bgc);} + +inline void fl_drw_text(Fl_Align align, int x, int y, int w, int h, + Fl_Color fgcolor, int size, Fl_Font style, + const char* s) { + fl_font(style,size); + fl_color(fgcolor); + fl_draw(s,x,y,w,h,align); +} + +// this does not work except for CENTER... +inline void fl_drw_text_beside(Fl_Align align, int x, int y, int w, int h, + Fl_Color fgcolor, int size, Fl_Font style, + const char* s) { + fl_font(style,size); + fl_color(fgcolor); + fl_draw(s,x,y,w,h,align); +} + +inline void fl_set_font_name(Fl_Font n,const char* s) {Fl::set_font(n,s);} + +inline void fl_mapcolor(Fl_Color c, uchar r, uchar g, uchar b) {Fl::set_color(c,r,g,b);} + +#define fl_set_clipping(x,y,w,h) fl_clip(x,y,w,h) +#define fl_unset_clipping() fl_pop_clip() + +//////////////////////////////////////////////////////////////// +// Forms classes: + +inline Fl_Widget* fl_add_new(Fl_Widget* p) {return p;} +inline Fl_Widget* fl_add_new(uchar t,Fl_Widget* p) {p->type(t); return p;} + +#define forms_constructor(type,name) \ +inline type* name(uchar t,int x,int y,int w,int h,const char* l) { \ + return (type*)(fl_add_new(t, new type(x,y,w,h,l)));} +#define forms_constructort(type,name) \ +inline type* name(uchar t,int x,int y,int w,int h,const char* l) { \ + return (type*)(fl_add_new(new type(t,x,y,w,h,l)));} +#define forms_constructorb(type,name) \ +inline type* name(Fl_Boxtype t,int x,int y,int w,int h,const char* l) { \ + return (type*)(fl_add_new(new type(t,x,y,w,h,l)));} + +#include "Fl_FormsBitmap.H" +#define FL_NORMAL_BITMAP FL_NO_BOX +forms_constructorb(Fl_FormsBitmap, fl_add_bitmap) +inline void fl_set_bitmap_data(Fl_Widget* o, int w, int h, const uchar* b) { + ((Fl_FormsBitmap*)o)->set(w,h,b); +} + +#include "Fl_FormsPixmap.H" +#define FL_NORMAL_PIXMAP FL_NO_BOX +forms_constructorb(Fl_FormsPixmap, fl_add_pixmap) +inline void fl_set_pixmap_data(Fl_Widget* o, char*const* b) { + ((Fl_FormsPixmap*)o)->set(b); +} +//inline void fl_set_pixmap_file(Fl_Widget*, const char*); +inline void fl_set_pixmap_align(Fl_Widget* o,Fl_Align a,int,int) {o->align(a);} +//inline void fl_set_pixmap_colorcloseness(int, int, int); + +#include "Fl_Box.H" +forms_constructorb(Fl_Box, fl_add_box) + +#include "Fl_Browser.H" +forms_constructor(Fl_Browser, fl_add_browser) + +inline void fl_clear_browser(Fl_Widget* o) { + ((Fl_Browser*)o)->clear();} +inline void fl_add_browser_line(Fl_Widget* o, const char* s) { + ((Fl_Browser*)o)->add(s);} +inline void fl_addto_browser(Fl_Widget* o, const char* s) { + ((Fl_Browser*)o)->add(s);} /* should also scroll to bottom */ +//inline void fl_addto_browser_chars(Fl_Widget*, const char*) +//#define fl_append_browser fl_addto_browser_chars +inline void fl_insert_browser_line(Fl_Widget* o, int n, const char* s) { + ((Fl_Browser*)o)->insert(n,s);} +inline void fl_delete_browser_line(Fl_Widget* o, int n) { + ((Fl_Browser*)o)->remove(n);} +inline void fl_replace_browser_line(Fl_Widget* o, int n, const char* s) { + ((Fl_Browser*)o)->replace(n,s);} +inline char* fl_get_browser_line(Fl_Widget* o, int n) { + return (char*)(((Fl_Browser*)o)->text(n));} +inline int fl_load_browser(Fl_Widget* o, const char* f) { + return ((Fl_Browser*)o)->load(f);} +inline void fl_select_browser_line(Fl_Widget* o, int n) { + ((Fl_Browser*)o)->select(n,1);} +inline void fl_deselect_browser_line(Fl_Widget* o, int n) { + ((Fl_Browser*)o)->select(n,0);} +inline void fl_deselect_browser(Fl_Widget* o) { + ((Fl_Browser*)o)->deselect();} +inline int fl_isselected_browser_line(Fl_Widget* o, int n) { + return ((Fl_Browser*)o)->selected(n);} +inline int fl_get_browser_topline(Fl_Widget* o) { + return ((Fl_Browser*)o)->topline();} +inline int fl_get_browser(Fl_Widget* o) { + return ((Fl_Browser*)o)->value();} +inline int fl_get_browser_maxline(Fl_Widget* o) { + return ((Fl_Browser*)o)->size();} +//linline int fl_get_browser_screenlines(Fl_Widget*); +inline void fl_set_browser_topline(Fl_Widget* o, int n) { + ((Fl_Browser*)o)->topline(n);} +inline void fl_set_browser_fontsize(Fl_Widget* o, int s) { + ((Fl_Browser*)o)->textsize(s);} +inline void fl_set_browser_fontstyle(Fl_Widget* o, Fl_Font s) { + ((Fl_Browser*)o)->textfont(s);} +inline void fl_set_browser_specialkey(Fl_Widget* o, char c) { + ((Fl_Browser*)o)->format_char(c);} +//inline void fl_set_browser_vscrollbar(Fl_Widget*, int); +//inline void fl_set_browser_hscrollbar(Fl_Widget*, int); +//inline void fl_set_browser_leftslider(Fl_Widget*, int); +//#define fl_set_browser_leftscrollbar fl_set_browser_leftslider +//inline void fl_set_browser_line_selectable(Fl_Widget*, int, int); +//inline void fl_get_browser_dimension(Fl_Widget*,int*,int*,int*,int*); +//inline void fl_set_browser_dblclick_callback(Fl_Widget*,FL_CALLBACKPTR,long); +//inline void fl_set_browser_xoffset(Fl_Widget*, FL_Coord); +//inline void fl_set_browser_scrollbarsize(Fl_Widget*, int, int); +inline void fl_setdisplayed_browser_line(Fl_Widget* o, int n, int i) { + ((Fl_Browser*)o)->display(n,i);} +inline int fl_isdisplayed_browser_line(Fl_Widget* o, int n) { + return ((Fl_Browser*)o)->displayed(n);} + +#include "Fl_Button.H" + +#define FL_NORMAL_BUTTON 0 +#define FL_TOUCH_BUTTON 4 +#define FL_INOUT_BUTTON 5 +#define FL_RETURN_BUTTON 6 +#define FL_HIDDEN_RET_BUTTON 7 +#define FL_PUSH_BUTTON FL_TOGGLE_BUTTON +#define FL_MENU_BUTTON 9 + +Fl_Button* fl_add_button(uchar t,int x,int y,int w,int h,const char* l); +inline int fl_get_button(Fl_Widget* b) {return ((Fl_Button*)b)->value();} +inline void fl_set_button(Fl_Widget* b, int v) {((Fl_Button*)b)->value(v);} +inline int fl_get_button_numb(Fl_Widget*) {return Fl::event_button();} +inline void fl_set_button_shortcut(Fl_Widget* b, const char* s,int=0) { + ((Fl_Button*)b)->shortcut(s);} +//#define fl_set_object_shortcut(b,s) fl_set_button_shortcut(b,s) + +#include "Fl_Light_Button.H" +forms_constructor(Fl_Light_Button, fl_add_lightbutton) + +#include "Fl_Round_Button.H" +forms_constructor(Fl_Round_Button, fl_add_roundbutton) +forms_constructor(Fl_Round_Button, fl_add_round3dbutton) + +#include "Fl_Check_Button.H" +forms_constructor(Fl_Check_Button, fl_add_checkbutton) + +inline Fl_Widget* fl_add_bitmapbutton(int t,int x,int y,int w,int h,const char* l) {Fl_Widget* o = fl_add_button(t,x,y,w,h,l); return o;} +inline void fl_set_bitmapbutton_data(Fl_Widget* o,int a,int b,uchar* c) { + (new Fl_Bitmap(c,a,b))->label(o);} // does not delete old Fl_Bitmap! + +inline Fl_Widget* fl_add_pixmapbutton(int t,int x,int y,int w,int h,const char* l) {Fl_Widget* o = fl_add_button(t,x,y,w,h,l); return o;} +inline void fl_set_pixmapbutton_data(Fl_Widget* o, char*const* c) { + (new Fl_Pixmap(c))->label(o);} // does not delete old Fl_Pixmap! + +// Fl_Canvas object not yet implemented! + +#include "Fl_Chart.H" + +forms_constructor(Fl_Chart, fl_add_chart) +inline void fl_clear_chart(Fl_Widget* o) { + ((Fl_Chart*)o)->clear();} +inline void fl_add_chart_value(Fl_Widget* o,double v,const char* s,uchar c){ + ((Fl_Chart*)o)->add(v,s,c);} +inline void fl_insert_chart_value(Fl_Widget* o, int i, double v, const char* s, uchar c) { + ((Fl_Chart*)o)->insert(i,v,s,c);} +inline void fl_replace_chart_value(Fl_Widget* o, int i, double v, const char* s, uchar c) { + ((Fl_Chart*)o)->replace(i,v,s,c);} +inline void fl_set_chart_bounds(Fl_Widget* o, double a, double b) { + ((Fl_Chart*)o)->bounds(a,b);} +inline void fl_set_chart_maxnumb(Fl_Widget* o, int v) { + ((Fl_Chart*)o)->maxsize(v);} +inline void fl_set_chart_autosize(Fl_Widget* o, int v) { + ((Fl_Chart*)o)->autosize(v);} +inline void fl_set_chart_lstyle(Fl_Widget* o, Fl_Font v) { + ((Fl_Chart*)o)->textfont(v);} +inline void fl_set_chart_lsize(Fl_Widget* o, int v) { + ((Fl_Chart*)o)->textsize(v);} +inline void fl_set_chart_lcolor(Fl_Widget* o, uchar v) { + ((Fl_Chart*)o)->textcolor(v);} +#define fl_set_chart_lcol fl_set_chart_lcolor + +#include "Fl_Choice.H" + +#define FL_NORMAL_CHOICE 0 +#define FL_NORMAL_CHOICE2 0 +#define FL_DROPLIST_CHOICE 0 + +forms_constructor(Fl_Choice, fl_add_choice) +inline void fl_clear_choice(Fl_Widget* o) { + ((Fl_Choice*)o)->clear();} +inline void fl_addto_choice(Fl_Widget* o, const char* s) { + ((Fl_Choice*)o)->add(s);} +inline void fl_replace_choice(Fl_Widget* o, int i, const char* s) { + ((Fl_Choice*)o)->replace(i-1,s);} +inline void fl_delete_choice(Fl_Widget* o, int i) { + ((Fl_Choice*)o)->remove(i-1);} +inline void fl_set_choice(Fl_Widget* o, int i) { + ((Fl_Choice*)o)->value(i-1);} +// inline void fl_set_choice_text(Fl_Widget*, const char*); +inline int fl_get_choice(Fl_Widget* o) { + return ((Fl_Choice*)o)->value()+1;} +// inline const char* fl_get_choice_item_text(Fl_Widget*, int); +// inline int fl_get_choice_maxitems(Fl_Widget*); +inline const char* fl_get_choice_text(Fl_Widget* o) { + return ((Fl_Choice*)o)->text();} +inline void fl_set_choice_fontsize(Fl_Widget* o, int x) { + ((Fl_Choice*)o)->textsize(x);} +inline void fl_set_choice_fontstyle(Fl_Widget* o, Fl_Font x) { + ((Fl_Choice*)o)->textfont(x);} +// inline void fl_set_choice_item_mode(Fl_Widget*, int, unsigned); +// inline void fl_set_choice_item_shortcut(Fl_Widget*, int, const char*); + +#include "Fl_Clock.H" +forms_constructort(Fl_Clock, fl_add_clock) +inline void fl_get_clock(Fl_Widget* o, int* h, int* m, int* s) { + *h = ((Fl_Clock*)o)->hour(); + *m = ((Fl_Clock*)o)->minute(); + *s = ((Fl_Clock*)o)->second(); +} + +#include "Fl_Counter.H" +forms_constructor(Fl_Counter, fl_add_counter) +inline void fl_set_counter_value(Fl_Widget* o, double v) { + ((Fl_Counter*)o)->value(v);} +inline void fl_set_counter_bounds(Fl_Widget* o, double a, double b) { + ((Fl_Counter*)o)->bounds(a,b);} +inline void fl_set_counter_step(Fl_Widget* o, double a, double b) { + ((Fl_Counter*)o)->step(a,b);} +inline void fl_set_counter_precision(Fl_Widget* o, int v) { + ((Fl_Counter*)o)->precision(v);} +inline void fl_set_counter_return(Fl_Widget* o, int v) { + ((Fl_Counter*)o)->when((Fl_When)(v|FL_WHEN_RELEASE));} +inline double fl_get_counter_value(Fl_Widget* o) { + return ((Fl_Counter*)o)->value();} +inline void fl_get_counter_bounds(Fl_Widget* o, float* a, float* b) { + *a = float(((Fl_Counter*)o)->minimum()); + *b = float(((Fl_Counter*)o)->maximum()); +} +//inline void fl_set_counter_filter(Fl_Widget*,const char* (*)(Fl_Widget*,double,int)); + +// Cursor stuff cannot be emulated because it uses X stuff +inline void fl_set_cursor(Fl_Window* w, Fl_Cursor c) {w->cursor(c);} +#define FL_INVISIBLE_CURSOR FL_CURSOR_NONE +#define FL_DEFAULT_CURSOR FL_CURSOR_DEFAULT + +#include "Fl_Dial.H" + +#define FL_DIAL_COL1 FL_GRAY +#define FL_DIAL_COL2 37 + +forms_constructor(Fl_Dial, fl_add_dial) +inline void fl_set_dial_value(Fl_Widget* o, double v) { + ((Fl_Dial*)o)->value(v);} +inline double fl_get_dial_value(Fl_Widget* o) { + return ((Fl_Dial*)o)->value();} +inline void fl_set_dial_bounds(Fl_Widget* o, double a, double b) { + ((Fl_Dial*)o)->bounds(a, b);} +inline void fl_get_dial_bounds(Fl_Widget* o, float* a, float* b) { + *a = float(((Fl_Dial*)o)->minimum()); + *b = float(((Fl_Dial*)o)->maximum()); +} +inline void fl_set_dial_return(Fl_Widget* o, int i) { + ((Fl_Dial*)o)->when((Fl_When)(i|FL_WHEN_RELEASE));} +inline void fl_set_dial_angles(Fl_Widget* o, int a, int b) { + ((Fl_Dial*)o)->angles(a,b);} +//inline void fl_set_dial_cross(Fl_Widget* o, int); +inline void fl_set_dial_direction(Fl_Widget* o, uchar d) { + ((Fl_Dial*)o)->direction(d);} +inline void fl_set_dial_step(Fl_Widget* o, double v) { + ((Fl_Dial*)o)->step(v);} + +// Frames: + +inline Fl_Widget* fl_add_frame(Fl_Boxtype i,int x,int y,int w,int h,const char* l) { + return fl_add_box(i,x-3,y-3,w+6,h+6,l);} + +// labelframe nyi +inline Fl_Widget* fl_add_labelframe(Fl_Boxtype i,int x,int y,int w,int h,const char* l) { + Fl_Widget* o = fl_add_box(i,x-3,y-3,w+6,h+6,l); + o->align(FL_ALIGN_TOP_LEFT); + return o; +} + +#include "Fl_Free.H" +inline Fl_Free* +fl_add_free(int t,double x,double y,double w,double h,const char* l, + FL_HANDLEPTR hdl) { + return (Fl_Free*)(fl_add_new( + new Fl_Free(t,int(x),int(y),int(w),int(h),l,hdl))); +} + +#include "fl_ask.H" +#include "fl_show_colormap.H" + +inline int fl_show_question(const char* c, int) {return fl_ask(c);} +inline void fl_show_alert(const char* a,const char*b,const char*c,int) { + fl_show_alert(a,b,c);} +inline void fl_set_goodies_font(uchar a, uchar b) {fl_message_font(a,b);} +#define fl_show_messages fl_message +inline int fl_show_choices(const char* c,int n,const char* b1,const char* b2, + const char* b3, int) { + return fl_show_choice(0,c,0,n,b1,b2,b3); +} + +#include "filename.H" +#include "fl_file_chooser.H" +inline int do_matching(char* a, const char* b) {return filename_match(a,b);} + +// Forms-compatable file chooser (implementation in fselect.C): +char* fl_show_file_selector(const char* message,const char* dir, + const char* pat,const char* fname); +char* fl_get_directory(); +char* fl_get_pattern(); +char* fl_get_filename(); + +#include "Fl_Input.H" +forms_constructor(Fl_Input, fl_add_input) +inline void fl_set_input(Fl_Widget* o, const char* v) { + ((Fl_Input*)o)->value(v);} +inline void fl_set_input_return(Fl_Widget* o, int x) { + ((Fl_Input*)o)->when((Fl_When)(x | FL_WHEN_RELEASE));} +inline void fl_set_input_color(Fl_Widget* o, uchar a, uchar b) { + ((Fl_Input*)o)->textcolor(a); + ((Fl_Input*)o)->cursor_color(b); +} +// inline void fl_set_input_scroll(Fl_Widget*, int); +inline void fl_set_input_cursorpos(Fl_Widget* o, int x, int /*y*/) { + ((Fl_Input*)o)->position(x);} +// inline void fl_set_input_selected(Fl_Widget*, int); +// inline void fl_set_input_selected_range(Fl_Widget*, int, int); +// inline void fl_set_input_maxchars(Fl_Widget*, int); +// inline void fl_set_input_format(Fl_Widget*, int, int); +// inline void fl_set_input_hscrollbar(Fl_Widget*, int); +// inline void fl_set_input_vscrollbar(Fl_Widget*, int); +// inline void fl_set_input_xoffset(Fl_Widget*, int); +// inline void fl_set_input_topline(Fl_Widget*, int); +// inline void fl_set_input_scrollbarsize(Fl_Widget*, int, int); +// inline int fl_get_input_topline(Fl_Widget*); +// inline int fl_get_input_screenlines(Fl_Widget*); +inline int fl_get_input_cursorpos(Fl_Widget* o, int*x, int*y) { + *x = ((Fl_Input*)o)->position(); *y = 0; return *x;} +// inline int fl_get_input_numberoflines(Fl_Widget*); +// inline void fl_get_input_format(Fl_Widget*, int*, int*); +inline const char* fl_get_input(Fl_Widget* o) {return ((Fl_Input*)o)->value();} + +#include "Fl_Menu_Button.H" + +// types are not implemented, they all act like FL_PUSH_MENU: +#define FL_TOUCH_MENU 0 +#define FL_PUSH_MENU 1 +#define FL_PULLDOWN_MENU 2 +forms_constructor(Fl_Menu_Button, fl_add_menu) + +inline void fl_clear_menu(Fl_Widget* o) { + ((Fl_Menu_Button*)o)->clear();} +inline void fl_set_menu(Fl_Widget* o, const char* s) { + ((Fl_Menu_Button*)o)->clear(); ((Fl_Menu_Button*)o)->add(s);} +inline void fl_addto_menu(Fl_Widget* o, const char* s) { + ((Fl_Menu_Button*)o)->add(s);} +inline void fl_replace_menu_item(Fl_Widget* o, int i, const char* s) { + ((Fl_Menu_Button*)o)->replace(i-1,s);} +inline void fl_delete_menu_item(Fl_Widget* o, int i) { + ((Fl_Menu_Button*)o)->remove(i-1);} +inline void fl_set_menu_item_shortcut(Fl_Widget* o, int i, const char* s) { + ((Fl_Menu_Button*)o)->shortcut(i-1,fl_old_shortcut(s));} +inline void fl_set_menu_item_mode(Fl_Widget* o, int i, long x) { + ((Fl_Menu_Button*)o)->mode(i-1,x);} +inline void fl_show_menu_symbol(Fl_Widget*, int ) { +/* ((Fl_Menu_Button*)o)->show_menu_symbol(i); */} +// inline void fl_set_menu_popup(Fl_Widget*, int); +inline int fl_get_menu(Fl_Widget* o) { + return ((Fl_Menu_Button*)o)->value()+1;} +inline const char* fl_get_menu_item_text(Fl_Widget* o, int i) { + return ((Fl_Menu_Button*)o)->text(i);} +inline int fl_get_menu_maxitems(Fl_Widget* o) { + return ((Fl_Menu_Button*)o)->size();} +inline int fl_get_menu_item_mode(Fl_Widget* o, int i) { + return ((Fl_Menu_Button*)o)->mode(i);} +inline const char* fl_get_menu_text(Fl_Widget* o) { + return ((Fl_Menu_Button*)o)->text();} + +#include "Fl_Positioner.H" +#define FL_NORMAL_POSITIONER 0 +forms_constructor(Fl_Positioner, fl_add_positioner) +inline void fl_set_positioner_xvalue(Fl_Widget* o, double v) { + ((Fl_Positioner*)o)->xvalue(v);} +inline double fl_get_positioner_xvalue(Fl_Widget* o) { + return ((Fl_Positioner*)o)->xvalue();} +inline void fl_set_positioner_xbounds(Fl_Widget* o, double a, double b) { + ((Fl_Positioner*)o)->xbounds(a,b);} +inline void fl_get_positioner_xbounds(Fl_Widget* o, float* a, float* b) { + *a = float(((Fl_Positioner*)o)->xminimum()); + *b = float(((Fl_Positioner*)o)->xmaximum()); +} +inline void fl_set_positioner_yvalue(Fl_Widget* o, double v) { + ((Fl_Positioner*)o)->yvalue(v);} +inline double fl_get_positioner_yvalue(Fl_Widget* o) { + return ((Fl_Positioner*)o)->yvalue();} +inline void fl_set_positioner_ybounds(Fl_Widget* o, double a, double b) { + ((Fl_Positioner*)o)->ybounds(a,b);} +inline void fl_get_positioner_ybounds(Fl_Widget* o, float* a, float* b) { + *a = float(((Fl_Positioner*)o)->yminimum()); + *b = float(((Fl_Positioner*)o)->ymaximum()); +} +inline void fl_set_positioner_xstep(Fl_Widget* o, double v) { + ((Fl_Positioner*)o)->xstep(v);} +inline void fl_set_positioner_ystep(Fl_Widget* o, double v) { + ((Fl_Positioner*)o)->ystep(v);} +inline void fl_set_positioner_return(Fl_Widget* o, int v) { + ((Fl_Positioner*)o)->when((Fl_When)(v|FL_WHEN_RELEASE));} + +#include "Fl_Slider.H" + +#define FL_HOR_BROWSER_SLIDER FL_HOR_SLIDER +#define FL_VERT_BROWSER_SLIDER FL_VERT_SLIDER + +forms_constructort(Fl_Slider, fl_add_slider) +#define FL_SLIDER_COL1 FL_GRAY +inline void fl_set_slider_value(Fl_Widget* o, double v) { + ((Fl_Slider*)o)->value(v);} +inline double fl_get_slider_value(Fl_Widget* o) { + return ((Fl_Slider*)o)->value();} +inline void fl_set_slider_bounds(Fl_Widget* o, double a, double b) { + ((Fl_Slider*)o)->bounds(a, b);} +inline void fl_get_slider_bounds(Fl_Widget* o, float* a, float* b) { + *a = float(((Fl_Slider*)o)->minimum()); + *b = float(((Fl_Slider*)o)->maximum()); +} +inline void fl_set_slider_return(Fl_Widget* o, int i) { + ((Fl_Slider*)o)->when((Fl_When)(i|FL_WHEN_RELEASE));} +inline void fl_set_slider_step(Fl_Widget* o, double v) { + ((Fl_Slider*)o)->step(v);} +// inline void fl_set_slider_increment(Fl_Widget* o, double v, double); +inline void fl_set_slider_size(Fl_Widget* o, double v) { + ((Fl_Slider*)o)->slider_size(v);} + +#include "Fl_Value_Slider.H" +forms_constructor(Fl_Value_Slider, fl_add_valslider) + +inline void fl_set_slider_precision(Fl_Widget* o, int i) { + ((Fl_Value_Slider*)o)->precision(i);} +// filter function! + +// The forms text object was the same as an Fl_Box except it inverted the +// meaning of FL_ALIGN_INSIDE. Implementation in forms.C +class Fl_FormsText : public Fl_Widget { +protected: + void draw(); +public: + Fl_FormsText(Fl_Boxtype b, int x, int y, int w, int h, const char* l=0) + : Fl_Widget(x,y,w,h,l) {box(b); align(FL_ALIGN_LEFT);} +}; +#define FL_NORMAL_TEXT FL_NO_BOX +forms_constructorb(Fl_FormsText, fl_add_text) + +#include "Fl_Timer.H" +forms_constructort(Fl_Timer, fl_add_timer) +inline void fl_set_timer(Fl_Widget* o, double v) {((Fl_Timer*)o)->value(v);} +inline double fl_get_timer(Fl_Widget* o) {return ((Fl_Timer*)o)->value();} +inline void fl_suspend_timer(Fl_Widget* o) {((Fl_Timer*)o)->suspended(1);} +inline void fl_resume_timer(Fl_Widget* o) {((Fl_Timer*)o)->suspended(0);} +inline void fl_set_timer_countup(Fl_Widget* o,char d) {((Fl_Timer*)o)->direction(d);} +void fl_gettime(long* sec, long* usec); + +// Fl_XYPlot nyi + + +// stuff from DDForms: + +inline int fl_double_click() {return Fl::event_clicks();} +inline void fl_draw() {Fl::flush();} + +#endif /* define __FORMS_H__ */ diff --git a/FL/gl.h b/FL/gl.h new file mode 100644 index 000000000..5db50e046 --- /dev/null +++ b/FL/gl.h @@ -0,0 +1,42 @@ +// gl.H +// Fltk gl drawing functions. +// You must include this instead of GL/gl.h to get around a stupid +// fuck up by our good friends at Microsloth. +// This file also provides "missing" OpenGL functions, and +// gl_start() and gl_finish() to allow OpenGL to be used in any window + +#ifndef gl_draw_H +#define gl_draw_H + +#include "Enumerations.H" // for color names +#ifdef WIN32 +# include +#endif +#include + +void gl_start(); +void gl_finish(); + +void gl_color(Fl_Color); +inline void gl_color(int c) {gl_color((Fl_Color)c);} // back compatability + +void gl_rect(int x,int y,int w,int h); +inline void gl_rectf(int x,int y,int w,int h) {glRecti(x,y,x+w,y+h);} + +void gl_font(int fontid, int size); +int gl_height(); +int gl_descent(); +double gl_width(const char *); +double gl_width(const char *, int n); +double gl_width(uchar); + +void gl_draw(const char*); +void gl_draw(const char*, int n); +void gl_draw(const char*, int x, int y); +void gl_draw(const char*, int n, int x, int y); +void gl_draw(const char*, int x, int y, int w, int h, Fl_Align); +void gl_measure(const char*, int& x, int& y); + +void gl_draw_image(const uchar *, int x,int y,int w,int h, int d=3, int ld=0); + +#endif diff --git a/FL/gl2opengl.h b/FL/gl2opengl.h new file mode 100644 index 000000000..b89614e0f --- /dev/null +++ b/FL/gl2opengl.h @@ -0,0 +1,35 @@ +/* gl.h + + GL to OpenGL translator. + If you include this, you might be able to port old GL programs. + There are also much better emulators available on the net. + +*/ + +#include +#include "gl_draw.H" + +inline void clear() {glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);} +#define RGBcolor(r,g,b) glColor3ub(r,g,b) +#define bgnline() glBegin(GL_LINE_STRIP) +#define bgnpolygon() glBegin(GL_POLYGON) +#define bgnclosedline() glBegin(GL_LINE_LOOP) +#define endline() glEnd() +#define endpolygon() glEnd() +#define endclosedline() glEnd() +#define v2f(v) glVertex2fv(v) +#define v2s(v) glVertex2sv(v) +#define cmov(x,y,z) glRasterPos3f(x,y,z) +#define charstr(s) gl_draw(s) +#define fmprstr(s) gl_draw(s) +typedef float Matrix[4][4]; +inline void pushmatrix() {glPushMatrix();} +inline void popmatrix() {glPopMatrix();} +inline void multmatrix(Matrix m) {glMultMatrixf((float *)m);} +inline void color(int n) {glIndexi(n);} +inline void rect(int x,int y,int r,int t) {gl_rect(x,y,r-x,t-y);} +inline void rectf(int x,int y,int r,int t) {glRectf(x,y,r+1,t+1);} +inline void recti(int x,int y,int r,int t) {gl_rect(x,y,r-x,t-y);} +inline void rectfi(int x,int y,int r,int t) {glRecti(x,y,r+1,t+1);} +inline void rects(int x,int y,int r,int t) {gl_rect(x,y,r-x,t-y);} +inline void rectfs(int x,int y,int r,int t) {glRects(x,y,r+1,t+1);} diff --git a/FL/gl_draw.H b/FL/gl_draw.H new file mode 100644 index 000000000..b65c50f1f --- /dev/null +++ b/FL/gl_draw.H @@ -0,0 +1,2 @@ +// gl_draw.H +#include "gl.h" diff --git a/FL/glut.H b/FL/glut.H new file mode 100644 index 000000000..0d72acb9f --- /dev/null +++ b/FL/glut.H @@ -0,0 +1,443 @@ +// glut.h + +// Emulation of Glut using fltk. + +// GLUT is Copyright (c) Mark J. Kilgard, 1994, 1995, 1996: +// "This program is freely distributable without licensing fees and is +// provided without guarantee or warrantee expressed or implied. This +// program is -not- in the public domain." + +// Although I have copied the GLUT API, none of my code is based on +// any Glut implementation details and is therefore covered by the LGPL. + +// Fltk does not include the Glut drawing functions (such as +// glutWireTeapot()) or the stroke fonts but the declarations for the +// drawing functions are included here because otherwise there is no +// way to get them along with this. To use them you will have to +// link in the original Glut library, put -lglut *after* -lfltk. + +// Commented out lines indicate parts of Glut that are not emulated. + +#ifndef __glut_h__ +#define __glut_h__ + +#include +#include + +//////////////////////////////////////////////////////////////// +// Glut is emulated using this window class and these static variables +// (plus several more static variables hidden in glut.C): + +#include "Fl.H" +#include "Fl_Gl_Window.H" + +class Fl_Glut_Window : public Fl_Gl_Window { + void draw(); + void draw_overlay(); + int handle(int); + void _init(); + int mouse_down; +public: // so the inline functions work + int number; + int menu[3]; + void make_current(); + void (*display)(); + void (*overlaydisplay)(); + void (*reshape)(int w, int h); + void (*keyboard)(uchar, int x, int y); + void (*mouse)(int b, int state, int x, int y); + void (*motion)(int x, int y); + void (*passivemotion)(int x, int y); + void (*entry)(int); + void (*visibility)(int); + void (*special)(int, int x, int y); + Fl_Glut_Window(int w, int h, const char *); + Fl_Glut_Window(int x, int y, int w, int h, const char *); + ~Fl_Glut_Window(); +}; + +extern Fl_Glut_Window *glut_window; // the current window +extern int glut_menu; // the current menu + +// function pointers that are not per-window: +extern void (*glut_idle_function)(); +extern void (*glut_menustate_function)(int); +extern void (*glut_menustatus_function)(int,int,int); + +//////////////////////////////////////////////////////////////// + +//#define GLUT_API_VERSION This does not match any version of Glut exactly... + +void glutInit(int *argcp, char **argv); // creates first window + +void glutInitDisplayMode(unsigned int mode); +// the FL_ symbols have the same value as the GLUT ones: +#define GLUT_RGB FL_RGB +#define GLUT_RGBA FL_RGB +#define GLUT_INDEX FL_INDEX +#define GLUT_SINGLE FL_SINGLE +#define GLUT_DOUBLE FL_DOUBLE +#define GLUT_ACCUM FL_ACCUM +#define GLUT_ALPHA FL_ALPHA +#define GLUT_DEPTH FL_DEPTH +#define GLUT_STENCIL FL_STENCIL +#define GLUT_MULTISAMPLE FL_MULTISAMPLE +// #define GLUT_STEREO 256 +// #define GLUT_LUMINANCE 512 + +void glutInitWindowPosition(int x, int y); + +void glutInitWindowSize(int w, int h); + +void glutMainLoop(); + +int glutCreateWindow(char *title); + +int glutCreateSubWindow(int win, int x, int y, int width, int height); + +void glutDestroyWindow(int win); + +inline void glutPostRedisplay() {glut_window->redraw();} + +void glutSwapBuffers(); + +inline int glutGetWindow() {return glut_window->number;} + +void glutSetWindow(int win); + +inline void glutSetWindowTitle(char *t) {glut_window->label(t);} + +inline void glutSetIconTitle(char *t) {glut_window->iconlabel(t);} + +inline void glutPositionWindow(int x, int y) {glut_window->position(x,y);} + +inline void glutReshapeWindow(int w, int h) {glut_window->size(w,h);} + +inline void glutPopWindow() {glut_window->show();} + +//inline void glutPushWindow(); + +inline void glutIconifyWindow() {glut_window->iconize();} + +inline void glutShowWindow() {glut_window->show();} + +inline void glutHideWindow() {glut_window->hide();} + +inline void glutFullScreen() {glut_window->fullscreen();} + +inline void glutSetCursor(Fl_Cursor cursor) {glut_window->cursor(cursor);} +// notice that the numeric values are different than glut: +#define GLUT_CURSOR_RIGHT_ARROW ((Fl_Cursor)2) +#define GLUT_CURSOR_LEFT_ARROW ((Fl_Cursor)67) +#define GLUT_CURSOR_INFO FL_CURSOR_HAND +#define GLUT_CURSOR_DESTROY ((Fl_Cursor)45) +#define GLUT_CURSOR_HELP FL_CURSOR_HELP +#define GLUT_CURSOR_CYCLE ((Fl_Cursor)26) +#define GLUT_CURSOR_SPRAY ((Fl_Cursor)63) +#define GLUT_CURSOR_WAIT FL_CURSOR_WAIT +#define GLUT_CURSOR_TEXT FL_CURSOR_INSERT +#define GLUT_CURSOR_CROSSHAIR FL_CURSOR_CROSS +#define GLUT_CURSOR_UP_DOWN FL_CURSOR_NS +#define GLUT_CURSOR_LEFT_RIGHT FL_CURSOR_WE +#define GLUT_CURSOR_TOP_SIDE FL_CURSOR_N +#define GLUT_CURSOR_BOTTOM_SIDE FL_CURSOR_S +#define GLUT_CURSOR_LEFT_SIDE FL_CURSOR_W +#define GLUT_CURSOR_RIGHT_SIDE FL_CURSOR_E +#define GLUT_CURSOR_TOP_LEFT_CORNER FL_CURSOR_NW +#define GLUT_CURSOR_TOP_RIGHT_CORNER FL_CURSOR_NE +#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER FL_CURSOR_SE +#define GLUT_CURSOR_BOTTOM_LEFT_CORNER FL_CURSOR_SW +#define GLUT_CURSOR_INHERIT FL_CURSOR_DEFAULT +#define GLUT_CURSOR_NONE FL_CURSOR_NONE +#define GLUT_CURSOR_FULL_CROSSHAIR FL_CURSOR_CROSS + +//inline void glutWarpPointer(int x, int y); + +inline void glutEstablishOverlay() {glut_window->make_overlay_current();} + +inline void glutRemoveOverlay() {glut_window->hide_overlay();} + +inline void glutUseLayer(GLenum layer) { + layer ? glut_window->make_overlay_current() : glut_window->make_current();} +enum {GLUT_NORMAL, GLUT_OVERLAY}; + +inline void glutPostOverlayRedisplay() {glut_window->redraw_overlay();} + +inline void glutShowOverlay() {glut_window->redraw_overlay();} + +inline void glutHideOverlay() {glut_window->hide_overlay();} + +int glutCreateMenu(void (*)(int)); + +void glutDestroyMenu(int menu); + +inline int glutGetMenu() {return glut_menu;} + +inline void glutSetMenu(int m) {glut_menu = m;} + +void glutAddMenuEntry(char *label, int value); + +void glutAddSubMenu(char *label, int submenu); + +void glutChangeToMenuEntry(int item, char *label, int value); + +void glutChangeToSubMenu(int item, char *label, int submenu); + +void glutRemoveMenuItem(int item); + +inline void glutAttachMenu(int b) {glut_window->menu[b] = glut_menu;} + +inline void glutDetachMenu(int b) {glut_window->menu[b] = 0;} + +inline void glutDisplayFunc(void (*f)()) {glut_window->display = f;} + +inline void glutReshapeFunc(void (*f)(int w, int h)) {glut_window->reshape=f;} + +inline void glutKeyboardFunc(void (*f)(uchar key, int x, int y)) { + glut_window->keyboard = f;} + +inline void glutMouseFunc(void (*f)(int b, int state, int x, int y)) { + glut_window->mouse = f;} +#define GLUT_LEFT_BUTTON 0 +#define GLUT_MIDDLE_BUTTON 1 +#define GLUT_RIGHT_BUTTON 2 +#define GLUT_DOWN 0 +#define GLUT_UP 1 + +inline void glutMotionFunc(void (*f)(int x, int y)) {glut_window->motion= f;} + +inline void glutPassiveMotionFunc(void (*f)(int x, int y)) { + glut_window->passivemotion= f;} + +inline void glutEntryFunc(void (*f)(int s)) {glut_window->entry = f;} +enum {GLUT_LEFT, GLUT_ENTERED}; + +inline void glutVisibilityFunc(void (*f)(int s)) {glut_window->visibility=f;} +enum {GLUT_NOT_VISIBLE, GLUT_VISIBLE}; + +inline void glutIdleFunc(void (*f)()) {Fl::set_idle(f);} + +// Warning: this cast may not work on all machines: +inline void glutTimerFunc(unsigned int msec, void (*f)(int), int value) { + Fl::add_timeout(msec*.001, (void (*)(void *))f, (void *)value); +} + +inline void glutMenuStateFunc(void (*f)(int state)) { + glut_menustate_function = f;} + +inline void glutMenuStatusFunc(void (*f)(int status, int x, int y)) { + glut_menustatus_function = f;} +enum {GLUT_MENU_NOT_IN_USE, GLUT_MENU_IN_USE}; + +inline void glutSpecialFunc(void (*f)(int key, int x, int y)) { + glut_window->special = f;} +#define GLUT_KEY_F1 1 +#define GLUT_KEY_F2 2 +#define GLUT_KEY_F3 3 +#define GLUT_KEY_F4 4 +#define GLUT_KEY_F5 5 +#define GLUT_KEY_F6 6 +#define GLUT_KEY_F7 7 +#define GLUT_KEY_F8 8 +#define GLUT_KEY_F9 9 +#define GLUT_KEY_F10 10 +#define GLUT_KEY_F11 11 +#define GLUT_KEY_F12 12 +// WARNING: Different values than Glut uses: +#define GLUT_KEY_LEFT FL_Left +#define GLUT_KEY_UP FL_Up +#define GLUT_KEY_RIGHT FL_Right +#define GLUT_KEY_DOWN FL_Down +#define GLUT_KEY_PAGE_UP FL_Page_Up +#define GLUT_KEY_PAGE_DOWN FL_Page_Down +#define GLUT_KEY_HOME FL_Home +#define GLUT_KEY_END FL_End +#define GLUT_KEY_INSERT FL_Insert + +//inline void glutSpaceballMotionFunc(void (*)(int x, int y, int z)); + +//inline void glutSpaceballRotateFunc(void (*)(int x, int y, int z)); + +//inline void glutSpaceballButtonFunc(void (*)(int button, int state)); + +//inline void glutButtonBoxFunc(void (*)(int button, int state)); + +//inline void glutDialsFunc(void (*)(int dial, int value)); + +//inline void glutTabletMotionFunc(void (*)(int x, int y)); + +//inline void glutTabletButtonFunc(void (*)(int button, int state, int x, int y)); + +inline void glutOverlayDisplayFunc(void (*f)()) { + glut_window->overlaydisplay = f;} + +//inline void glutWindowStatusFunc(void (*)(int state)); +//enum {GLUT_HIDDEN, GLUT_FULLY_RETAINED, GLUT_PARTIALLY_RETAINED, +// GLUT_FULLY_COVERED}; + +//inline void glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); + +//inline GLfloat glutGetColor(int ndx, int component); +//#define GLUT_RED 0 +//#define GLUT_GREEN 1 +//#define GLUT_BLUE 2 + +//inline void glutCopyColormap(int win); + +// Warning: values are changed from Glut! +// Also relies on the GL_ symbols having values greater than 100 +int glutGet(GLenum type); +enum { + GLUT_RETURN_ZERO = 0, + GLUT_WINDOW_X, + GLUT_WINDOW_Y, + GLUT_WINDOW_WIDTH, + GLUT_WINDOW_HEIGHT, + GLUT_WINDOW_PARENT, +//GLUT_WINDOW_NUM_CHILDREN, +//GLUT_WINDOW_CURSOR, + GLUT_SCREEN_WIDTH, + GLUT_SCREEN_HEIGHT, +//GLUT_SCREEN_WIDTH_MM, +//GLUT_SCREEN_HEIGHT_MM, + GLUT_MENU_NUM_ITEMS, + GLUT_DISPLAY_MODE_POSSIBLE, + GLUT_INIT_WINDOW_X, + GLUT_INIT_WINDOW_Y, + GLUT_INIT_WINDOW_WIDTH, + GLUT_INIT_WINDOW_HEIGHT, + GLUT_INIT_DISPLAY_MODE, +//GLUT_ELAPSED_TIME, + GLUT_WINDOW_BUFFER_SIZE +}; + +#define GLUT_WINDOW_STENCIL_SIZE GL_STENCIL_BITS +#define GLUT_WINDOW_DEPTH_SIZE GL_DEPTH_BITS +#define GLUT_WINDOW_RED_SIZE GL_RED_BITS +#define GLUT_WINDOW_GREEN_SIZE GL_GREEN_BITS +#define GLUT_WINDOW_BLUE_SIZE GL_BLUE_BITS +#define GLUT_WINDOW_ALPHA_SIZE GL_ALPHA_BITS +#define GLUT_WINDOW_ACCUM_RED_SIZE GL_ACCUM_RED_BITS +#define GLUT_WINDOW_ACCUM_GREEN_SIZE GL_ACCUM_GREEN_BITS +#define GLUT_WINDOW_ACCUM_BLUE_SIZE GL_ACCUM_BLUE_BITS +#define GLUT_WINDOW_ACCUM_ALPHA_SIZE GL_ACCUM_ALPHA_BITS +#define GLUT_WINDOW_DOUBLEBUFFER GL_DOUBLEBUFFER +#define GLUT_WINDOW_RGBA GL_RGBA +#define GLUT_WINDOW_COLORMAP_SIZE GL_INDEX_BITS +#ifdef GL_SAMPLES_SGIS +#define GLUT_WINDOW_NUM_SAMPLES GL_SAMPLES_SGIS +#else +#define GLUT_WINDOW_NUM_SAMPLES GLUT_RETURN_ZERO +#endif +#define GLUT_WINDOW_STEREO GL_STEREO + +//int glutDeviceGet(GLenum type); +//#define GLUT_HAS_KEYBOARD 600 +//#define GLUT_HAS_MOUSE 601 +//#define GLUT_HAS_SPACEBALL 602 +//#define GLUT_HAS_DIAL_AND_BUTTON_BOX 603 +//#define GLUT_HAS_TABLET 604 +//#define GLUT_NUM_MOUSE_BUTTONS 605 +//#define GLUT_NUM_SPACEBALL_BUTTONS 606 +//#define GLUT_NUM_BUTTON_BOX_BUTTONS 607 +//#define GLUT_NUM_DIALS 608 +//#define GLUT_NUM_TABLET_BUTTONS 609 + +inline int glutGetModifiers() {return Fl::event_state();} +// WARNING: these values are different than Glut uses: +#define GLUT_ACTIVE_SHIFT FL_SHIFT +#define GLUT_ACTIVE_CTRL FL_CTRL +#define GLUT_ACTIVE_ALT FL_ALT + +int glutLayerGet(GLenum); +#define GLUT_OVERLAY_POSSIBLE 800 +//#define GLUT_LAYER_IN_USE 801 +//#define GLUT_HAS_OVERLAY 802 +#define GLUT_TRANSPARENT_INDEX 803 +#define GLUT_NORMAL_DAMAGED 804 +#define GLUT_OVERLAY_DAMAGED 805 + +//inline int glutVideoResizeGet(GLenum param); +//#define GLUT_VIDEO_RESIZE_POSSIBLE 900 +//#define GLUT_VIDEO_RESIZE_IN_USE 901 +//#define GLUT_VIDEO_RESIZE_X_DELTA 902 +//#define GLUT_VIDEO_RESIZE_Y_DELTA 903 +//#define GLUT_VIDEO_RESIZE_WIDTH_DELTA 904 +//#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 905 +//#define GLUT_VIDEO_RESIZE_X 906 +//#define GLUT_VIDEO_RESIZE_Y 907 +//#define GLUT_VIDEO_RESIZE_WIDTH 908 +//#define GLUT_VIDEO_RESIZE_HEIGHT 909 + +//inline void glutSetupVideoResizing(); + +//inline void glutStopVideoResizing(); + +//inline void glutVideoResize(int x, int y, int width, int height); + +//inline void glutVideoPan(int x, int y, int width, int height); + +//////////////////////////////////////////////////////////////// +// Emulated Glut drawing functions: + +// Font argument must be a void* for compatability, so... +extern struct Glut_Bitmap_Font {uchar font; int size;} + glutBitmap9By15, glutBitmap8By13, glutBitmapTimesRoman10, + glutBitmapTimesRoman24, glutBitmapHelvetica10, glutBitmapHelvetica12, + glutBitmapHelvetica18; +#define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15) +#define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13) +#define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10) +#define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24) +#define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10) +#define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12) +#define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18) + +void glutBitmapCharacter(void *font, int character); +int glutBitmapWidth(void *font, int character); + +//////////////////////////////////////////////////////////////// +// Glut drawing functions. These are NOT emulated but you can +// link in the glut library to get them. This assummes the object +// files in Glut remain as they currently are so that there are +// not symbol conflicts with the above. + +extern "C" { + +extern int glutExtensionSupported(char *name); + +/* Stroke font opaque addresses (use constants instead in source code). */ +extern void *glutStrokeRoman; +extern void *glutStrokeMonoRoman; + +/* Stroke font constants (use these in GLUT program). */ +#define GLUT_STROKE_ROMAN (&glutStrokeRoman) +#define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) + +/* GLUT font sub-API */ +extern void glutStrokeCharacter(void *font, int character); +extern int glutStrokeWidth(void *font, int character); + +/* GLUT pre-built models sub-API */ +extern void glutWireSphere(GLdouble radius, GLint slices, GLint stacks); +extern void glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); +extern void glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +extern void glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +extern void glutWireCube(GLdouble size); +extern void glutSolidCube(GLdouble size); +extern void glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +extern void glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +extern void glutWireDodecahedron(); +extern void glutSolidDodecahedron(); +extern void glutWireTeapot(GLdouble size); +extern void glutSolidTeapot(GLdouble size); +extern void glutWireOctahedron(); +extern void glutSolidOctahedron(); +extern void glutWireTetrahedron(); +extern void glutSolidTetrahedron(); +extern void glutWireIcosahedron(); +extern void glutSolidIcosahedron(); + +} + +#endif /* __glut_h__ */ diff --git a/FL/math.h b/FL/math.h new file mode 100644 index 000000000..57dc3f9c8 --- /dev/null +++ b/FL/math.h @@ -0,0 +1,27 @@ +#include + +#ifdef WIN32 +// things missing from : + +#define M_PI 3.14159265358979323846 +#define M_PI_2 1.57079632679489661923 +#define M_PI_4 0.78539816339744830962 +#define M_1_PI 0.31830988618379067154 +#define M_2_PI 0.63661977236758134308 +#define M_SQRT2 1.41421356237309504880 +#define M_SQRT1_2 0.70710678118654752440 + +#else + +#ifdef __EMX__ +#include +#endif + +#endif + +#if defined(WIN32) || defined(CRAY) + +inline double rint(double v) {return floor(v+.5);} +inline double copysign(double a, double b) {return b<0 ? -a : a;} + +#endif diff --git a/FL/menubar.h b/FL/menubar.h new file mode 100644 index 000000000..1dc7cc8bd --- /dev/null +++ b/FL/menubar.h @@ -0,0 +1,64 @@ +// This is an additional header file for "DDForms", which was our internal +// enhancement of Forms. This defines the precursor of the Fl_Menu class. +// +// Unfortunately it defined the callbacks as taking a long rather +// than a void* argument, requiring some dubious casts to emulate it: + +#include "Fl_Menu_Bar.H" + +struct MenuEntry { + const char *text; /*initial character indicates "type", 0 = end of menu*/ + ulong bind; /* key binding in forms format (#x, etc) */ + void (*cb)(Fl_Widget *,long); /* callback */ + long data; /* value for callback */ + int flags; /* see below for flags */ + uchar labeltype; + uchar labelfont; + uchar labelsize; + uchar labelcolor; +}; + +#define CHECKED FL_MENU_CHECK +#define UNCHECKED FL_MENU_BOX +#define DISABLED FL_MENU_INACTIVE + +/* Turn a box into a menu bar: */ +inline void MenuBar(Fl_Widget *o,MenuEntry *m) { + Fl_Menu_Bar *mb = new Fl_Menu_Bar(o->x(),o->y(),o->w(),o->h()); + mb->menu((Fl_Menu_Item*)m); + mb->box(0); + Fl_Group *g = (Fl_Group *)(o->parent()); + int i = g->find(*o); + g->insert(*mb, ichildren()-1 ? g->child(i+1) : 0); +} + +/* advance to the Nth item in menu, skipping submenus: */ +inline MenuEntry *MenuGetEntry(MenuEntry *m,int i) { + return (MenuEntry*)(((Fl_Menu_Item*)m)->next(i)); +} + +/* Init the shortcuts for a widget with a popup menu: */ +inline void MenuSetShortcuts(Fl_Widget *, MenuEntry *) {} + +inline void MenuAdd( + MenuEntry m[], + int, /* number of entries in menutable, ignored here */ + const char *text, + const char *bind, + void (*cb)(Fl_Widget *,long), + long data, + int flags) { + ((Fl_Menu_Item*)m)->add(text,bind,(Fl_Callback*)cb,(void *)data,flags); +} + +inline MenuEntry *MenuPopup(Fl_Widget *o,const char *title,MenuEntry *m,double x,double y) { + const Fl_Menu_Item* v = ((Fl_Menu_Item*)m)->popup(x,y,title); + if (v && v->callback_) v->do_callback(o); + return (MenuEntry *)v; +} + +inline MenuEntry *MenuHandleShortcut(Fl_Widget *o,MenuEntry *m,char) { + const Fl_Menu_Item* v = ((Fl_Menu_Item*)m)->test_shortcut(); + if (v && v->callback_) v->do_callback(o); + return (MenuEntry *)v; +} diff --git a/FL/win32.H b/FL/win32.H new file mode 100644 index 000000000..1572c9e73 --- /dev/null +++ b/FL/win32.H @@ -0,0 +1,80 @@ +// win32.H + +// Do not directly include this file, instead use . It will +// include this file if WIN32 is defined. This is to encourage +// portability of even the system-specific code... + +#include +#ifndef LPMINMAXINFO +// the gcc header files are missing some stuff: +#define LPMINMAXINFO MINMAXINFO* +#define VK_LWIN 0x5B +#define VK_RWIN 0x5C +#define VK_APPS 0x5D +#endif + +// some random X equivalents +#define Window HWND +#define XPoint POINT +struct XRectangle {int x, y, width, height;}; +struct Region {int x, y, r, b; void operator=(int x) {r = x;}}; +inline void XClipBox(Region& i, XRectangle* o) { + o->x = i.x; o->y = i.y; o->width = i.r-i.x; o->height = i.b-i.y;} +#define fl_clip_region(R) fl_clip((R).x,(R).y,(R).r-(R).x,(R).b-(R).y) +#define XDestroyWindow(a,b) DestroyWindow(b) +#define XMapWindow(a,b) ShowWindow(b, SW_RESTORE) +#define XUnmapWindow(a,b) ShowWindow(b, SW_HIDE) + +#include "Fl_Window.H" +// this object contains all win32-specific stuff about a window: +// Warning: this object is highly subject to change! +class Fl_X { +public: + Window xid; + HBITMAP other_xid; // for double-buffered windows + Fl_Window* w; + Region region; + Fl_X *next; + HDC private_dc; // used for OpenGL + HCURSOR cursor; + static Fl_X* first; + static Fl_X* i(const Fl_Window* w) {return w->i;} + void setwindow(Fl_Window* wi) {w=wi; wi->i=this;} + void flush() {w->flush();} + void set_minmax(LPMINMAXINFO minmax); + void mapraise(); + static Fl_X* make(Fl_Window*); +}; +extern HCURSOR fl_default_cursor; +inline Window fl_xid(const Fl_Window*w) {return Fl_X::i(w)->xid;} +Fl_Window* fl_find(Window xid); +extern char fl_override_redirect; // hack into Fl_Window::make_xid() +extern int fl_background_pixel; // hack into Fl_Window::make_xid() + +// most recent fl_color() or fl_rgbcolor() points at one of these: +extern struct Fl_XMap { + COLORREF rgb; // this should be the type the RGB() macro returns + HPEN pen; // pen, 0 if none created yet + int brush; // ref to solid brush, 0 if none created yet +} *fl_current_xmap; +inline COLORREF fl_RGB() {return fl_current_xmap->rgb;} +inline HPEN fl_pen() {return fl_current_xmap->pen;} +HBRUSH fl_brush(); // allocates a brush if necessary + +extern HINSTANCE fl_display; +extern Window fl_window; +extern HDC fl_gc; +extern HPALETTE fl_palette; // non-zero only on 8-bit displays! +extern HDC fl_DC(Window); +extern MSG fl_msg; + +// off-screen pixmaps: create, destroy, draw into, copy to window +#define Fl_Offscreen HBITMAP +#define fl_create_offscreen(w, h) CreateCompatibleBitmap(fl_gc, w, h) +extern void fl_switch_offscreen(HBITMAP); +#define fl_begin_offscreen(b) HDC _sw=fl_gc; fl_switch_offscreen(b) +#define fl_end_offscreen() fl_gc = _sw +void fl_make_current(HBITMAP bitmap); +void fl_copy_offscreen(int x,int y,int w,int h,HBITMAP pixmap,int srcx,int srcy); +#define fl_delete_offscreen(bitmap) DeleteObject(bitmap); + diff --git a/FL/x.H b/FL/x.H new file mode 100644 index 000000000..39d1e7bb3 --- /dev/null +++ b/FL/x.H @@ -0,0 +1,87 @@ +// x.H + +// These are internal fltk symbols that are necessary or useful for +// calling Xlib. You should include this file if (and ONLY if) you +// need to call Xlib directly. These symbols may not exist on non-X +// systems. + +#ifndef Fl_X_H +#define Fl_X_H + +#include "Enumerations.H" + +#ifdef WIN32 + +#include "win32.H" + +#else + +#include +#include +#include +#include "Fl_Window.H" + +void fl_open_display(); +void fl_close_display(); + +// constant info about the X server connection: +extern Display *fl_display; +extern int fl_screen; +extern XVisualInfo *fl_visual; +extern Colormap fl_colormap; + +// drawing functions: +extern GC fl_gc; +extern Window fl_window; +ulong fl_xpixel(Fl_Color i); +ulong fl_xpixel(uchar r, uchar g, uchar b); +void fl_clip_region(Region); + +// feed events into fltk: +int fl_handle(const XEvent&); + +// you can use these in Fl::add_handler() to look at events: +extern const XEvent* fl_xevent; +extern ulong fl_event_time; + +// off-screen pixmaps: create, destroy, draw into, copy to window: +#define Fl_Offscreen ulong +#define fl_create_offscreen(w,h) \ +XCreatePixmap(fl_display, fl_window, w, h, fl_visual->depth) +#define fl_begin_offscreen(pixmap) Window _sw=fl_window;fl_window=pixmap;fl_push_no_clip() +#define fl_end_offscreen() fl_pop_clip();fl_window = _sw +#define fl_copy_offscreen(x,y,w,h,pixmap,srcx,srcy) \ + XCopyArea(fl_display, pixmap, fl_window, fl_gc, srcx, srcy, w, h, x, y) +#define fl_delete_offscreen(pixmap) XFreePixmap(fl_display, pixmap) + +// this object contains all X-specific stuff about a window: +// Warning: this object is highly subject to change! It's definition +// is only here so that fl_xid can be declared inline: +class Fl_X { +public: + Window xid; + Window other_xid; + Fl_Window *w; + Region region; + Fl_X *next; + static Fl_X* first; + static Fl_X* i(const Fl_Window* w) {return w->i;} + void setwindow(Fl_Window* wi) {w=wi; wi->i=this;} + void sendxjunk(); + static void make_xid(Fl_Window*,XVisualInfo* =fl_visual, Colormap=fl_colormap); + static Fl_X* set_xid(Fl_Window*, Window); + // kludges to get around protection: + void flush() {w->flush();} + static void x(Fl_Window* w, int X) {w->x(X);} + static void y(Fl_Window* w, int Y) {w->y(Y);} +}; + +// convert xid <-> Fl_Window: +inline Window fl_xid(const Fl_Window*w) {return Fl_X::i(w)->xid;} +Fl_Window* fl_find(Window xid); + +extern char fl_override_redirect; // hack into Fl_X::make_xid() +extern int fl_background_pixel; // hack into Fl_X::make_xid() + +#endif +#endif diff --git a/GL/glut.h b/GL/glut.h new file mode 100644 index 000000000..367bf8929 --- /dev/null +++ b/GL/glut.h @@ -0,0 +1,3 @@ +// this file allows some glut programs to be compiled with no change. +// Put this in a directory "GL" in your include path. +#include diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..5df40f8f2 --- /dev/null +++ b/Makefile @@ -0,0 +1,49 @@ +SHELL=/bin/sh + +all : src fluid test +shared : srcshared fluid test +lib : SRC +src : SRC + +SRC : makeinclude src/makedepend + cd src && $(MAKE) +src/makedepend : + touch src/makedepend +srcshared : makeinclude src/makedepend + cd src && $(MAKE) shared + +fluid : FLUID +FLUID : makeinclude fluid/makedepend + cd fluid && $(MAKE) +fluid/makedepend : + touch fluid/makedepend + +test : TEST +TEST : makeinclude + cd test && $(MAKE) + +install : SRC FLUID + cd src && $(MAKE) install + cd fluid && $(MAKE) install + +uninstall : makeinclude src/makedepend fluid/makedepend + cd src && $(MAKE) uninstall + cd fluid && $(MAKE) uninstall + +clean : + -@ rm -f *.o core *~ + cd src && $(MAKE) clean + cd fluid && $(MAKE) clean + cd test && $(MAKE) clean + +distclean : clean + -@ rm config.* makeinclude + +realclean : distclean + +include ./version +dist : + ./makedist $(VERSION).$(REVISION) + +makeinclude : + ./configure diff --git a/README b/README new file mode 100644 index 000000000..04ce612f6 --- /dev/null +++ b/README @@ -0,0 +1,123 @@ +Fast Light Tool Kit (fltk) Version 0.99 + +---------------------------------------------------------------- +How to build and install fltk: +---------------------------------------------------------------- + +See the file win32/README for information for Windoze95/NT. + +1. Type "./configure", and then examine config.h and makeinclude. +1. Edit the file ./style.h to customize the appearance of fltk +3. Type "make", or (Linux and gcc only) type "make shared" to make + a shared library. +4. For shared libraries, type "setenv LD_LIBRARY_PATH $PWD/lib" +5. Test it by running "test/demo". + +To install the new version of Fltk and fluid (this puts the library in +/usr/local/lib, the include files in /usr/local/include/FL, and fluid +into /usr/local/bin): + +1. If you made the shared version, type "unsetenv LD_LIBRARY_PATH" +2. Type "su" and then your password +3. Type "make install" +4. If you made the shared version, type "/sbin/ldconfig" +5. Type ^D to get out of su. + +---------------------------------------------------------------- +On-line documentation: +---------------------------------------------------------------- + +All the documentation is in html in the subdirectory "documentation". +Use file:/documentation/index.html to get started. Install +should put the documentation in /usr/doc/fltk but this is not yet +implemented. + +These files are readable without a browser: + +Change log is in documentation/CHANGES +To Do list is in documentatoin/TODO.html + +---------------------------------------------------------------- +WWW resources: +---------------------------------------------------------------- + +The Fltk home page: http://www.cinenet.net/users/spitzak/fltk + +Mirror site: http://fltk.easysw.com + +To post to the fltk mailing list: fltk@easysw.com + +To subscribe, send "subscribe fltk" to majordomo@easysw.com + +Send mail to Bill Spitzak (the author of fltk): spitzak@d2.com + +Get Mesa (necessary to run OpenGl on most Linux machines): + http://www.ssec.wisc.edu/~brianp/Mesa.html + +---------------------------------------------------------------- +Window managers +---------------------------------------------------------------- + +Fltk now uses X transient windows for modal() windows. This may +confuse some window managers. Mostly it causes them to not put +any borders on the modal windows and prevent you from moving them. + +For FVWM I recommend you put "DecorateTransients" into your .fvwmrc. + +---------------------------------------------------------------- +Mesa: +---------------------------------------------------------------- + +Currently the best way to get OpenGL on your Linux system is to use +Mesa. Fltk has been tested with Mesa on several machines (and also +with "real" OpenGL on SGI machines). + +Mesa is at: http://www.ssec.wisc.edu/~brianp/Mesa.html + +./configure will not see Mesa unless it is installed as either libGL +or libMesa. If you don't want to do this you will have to edit +config.h (set HAVE_GL to 1) and makeinclude (add the libraries). + +---------------------------------------------------------------- +How to write programs that use Fltk: +---------------------------------------------------------------- + +The proper way to include Fltk header files is "#include ". +If Fltk is installed this will work without switches. If not you will +need to provide a -I switch pointing to this directory (all the +headers are in ./FL). + +Linker switches will be something like "-lfltk -L/usr/X11R6/lib -lX11". +Some programs may require -lXext or -lm. If Fltk is not installed you +will need to add a -L switch pointing at ./lib. + +If you wish to distribute a program (in source form) that uses Fltk, +you are allowed by the license to directly include the portions of +Fltk that you need. This may make it easier for a user to compile +your program since they don't need to install the library. Please +provide instructions for the user on how they can get the entire +source of Fltk. + +If you wish to distribute a compiled program without source code: this +is allowed. See the license. + +---------------------------------------------------------------- +Copyright (C) 1998 Bill Spitzak +---------------------------------------------------------------- +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library 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. + +Written by Bill Spitzak spitzak@d2.com +---------------------------------------------------------------- diff --git a/configh.in b/configh.in new file mode 100644 index 000000000..0ff8d77a5 --- /dev/null +++ b/configh.in @@ -0,0 +1,53 @@ +/* configh.in: this file is read by ./configure to produce config.h */ + +/* Thickness of FL_UP_BOX and FL_DOWN_BOX. Current 1,2, and 3 are + supported. 3 is the historic fltk look. 2 looks more like windoze + (and KDE and Qt). 1 is a plausible future evolution... Notice + that this may be simulated at runtime by redefining the boxtypes + using Fl::set_boxtype() */ +#define BORDER_WIDTH 3 + +/* Do you have OpenGL? + Set this to 0 if you don't plan to use OpenGL, and fltk will be smaller */ +#define HAVE_GL 0 + +/* Use XAllocColor + Setting this to zero will save a good deal of code (esp for + fl_draw_image), but fltk will only work on TrueColor visuals. */ +#define USE_COLORMAP 1 + +/* Do we have the X double-buffer extension? */ +#define HAVE_XDBE 0 + +/* Actually try to use the double-buffer extension? + Set this to zero disable use of XDBE without breaking the + list_visuals program: */ +#define USE_XDBE HAVE_XDBE + +/* Use the X overlay extension? Fltk will try to use an overlay + visual for Fl_Overlay_Window, the Gl_Window overlay, and for the + menus. Setting this to zero will remove a substatial amount of + code from fltk. Overlays have only been tested on SGI servers! */ +#define HAVE_OVERLAY 0 +/* It is possible your GL has an overlay even if X does not, if so + turn this on: */ +#define HAVE_GL_OVERLAY HAVE_OVERLAY + +/* Byte order of your machine: */ +#define WORDS_BIGENDIAN 0 + +/* Types used by fl_draw_image. One of U32 or U64 must be defined. + U16 is optional but fltk will work better with it! */ +#undef U16 +#undef U32 +#undef U64 + +/* Where is (used only by fl_file_chooser and scandir): */ +#define HAVE_DIRENT_H 1 +#define HAVE_SYS_NDIR_H 0 +#define HAVE_SYS_DIR_H 0 +#define HAVE_NDIR_H 0 +#define HAVE_SCANDIR 0 + +/* use poll() instead of select(): */ +#define HAVE_POLL 0 diff --git a/configure b/configure new file mode 100755 index 000000000..b67eb4535 --- /dev/null +++ b/configure @@ -0,0 +1,2721 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --with-x use the X Window System" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +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' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +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 + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # 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 ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$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" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) 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) + # 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 << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$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) + 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 ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + 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 "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# 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 + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=src/Fl.C + +# 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_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + 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 "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# 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 "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:527: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +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 $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:556: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +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 $# -gt 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 + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:604: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:638: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:643: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS= + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:667: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + elif test $ac_cv_prog_cc_g = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-O2" + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi + +for ac_prog in $CCC c++ g++ gcc CC cxx cc++ +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 $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:699: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CXX="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CXX="$ac_cv_prog_CXX" +if test -n "$CXX"; then + echo "$ac_t""$CXX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$CXX" && break +done +test -n "$CXX" || CXX="gcc" + + +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:730: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 + +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_cv_prog_cxx_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cxx_cross=no + else + ac_cv_prog_cxx_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cxx_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 +if test $ac_cv_prog_cxx_works = no; then + { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:770: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 +cross_compiling=$ac_cv_prog_cxx_cross + +echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 +echo "configure:775: checking whether we are using GNU C++" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.C <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gxx=yes +else + ac_cv_prog_gxx=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gxx" 1>&6 + +if test $ac_cv_prog_gxx = yes; then + GXX=yes + ac_test_CXXFLAGS="${CXXFLAGS+set}" + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS= + echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 +echo "configure:799: checking whether ${CXX-g++} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.cc +if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then + ac_cv_prog_cxx_g=yes +else + ac_cv_prog_cxx_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6 + if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS="$ac_save_CXXFLAGS" + elif test $ac_cv_prog_cxx_g = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-O2" + fi +else + GXX= + test "${CXXFLAGS+set}" = set || CXXFLAGS="-g" +fi + + +echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 +echo "configure:828: checking whether byte ordering is bigendian" >&5 +if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_bigendian=unknown +# See if sys/param.h defines the BYTE_ORDER macro. +cat > conftest.$ac_ext < +#include +int main() { + +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif +; return 0; } +EOF +if { (eval echo configure:846: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + # It does; now see whether it defined to BIG_ENDIAN or not. +cat > conftest.$ac_ext < +#include +int main() { + +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif +; return 0; } +EOF +if { (eval echo configure:861: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_bigendian=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_bigendian=no +fi +rm -f conftest* +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +if test $ac_cv_c_bigendian = unknown; then +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + ac_cv_c_bigendian=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_bigendian=yes +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_c_bigendian" 1>&6 +if test $ac_cv_c_bigendian = yes; then + cat >> confdefs.h <<\EOF +#define WORDS_BIGENDIAN 1 +EOF + +fi + + +echo $ac_n "checking size of short""... $ac_c" 1>&6 +echo "configure:919: checking size of short" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_sizeof_short=2 +else + cat > conftest.$ac_ext < +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(short)); + exit(0); +} +EOF +if { (eval echo configure:938: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + ac_cv_sizeof_short=`cat conftestval` +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_sizeof_short=0 +fi +rm -fr conftest* +fi + +fi +echo "$ac_t""$ac_cv_sizeof_short" 1>&6 +cat >> confdefs.h <&6 +echo "configure:958: checking size of int" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_sizeof_int=4 +else + cat > conftest.$ac_ext < +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(int)); + exit(0); +} +EOF +if { (eval echo configure:977: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + ac_cv_sizeof_int=`cat conftestval` +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_sizeof_int=0 +fi +rm -fr conftest* +fi + +fi +echo "$ac_t""$ac_cv_sizeof_int" 1>&6 +cat >> confdefs.h <&6 +echo "configure:997: checking size of long" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_sizeof_long=4 +else + cat > conftest.$ac_ext < +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(long)); + exit(0); +} +EOF +if { (eval echo configure:1016: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + ac_cv_sizeof_long=`cat conftestval` +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_sizeof_long=0 +fi +rm -fr conftest* +fi + +fi +echo "$ac_t""$ac_cv_sizeof_long" 1>&6 +cat >> confdefs.h <> confdefs.h <<\EOF +#define U16 unsigned short +EOF + +fi +if test $ac_cv_sizeof_int -eq 4; then +cat >> confdefs.h <<\EOF +#define U32 unsigned +EOF + +else +if test $ac_cv_sizeof_long -eq 4; then +cat >> confdefs.h <<\EOF +#define U32 unsigned long +EOF + +fi +fi +if test $ac_cv_sizeof_int -eq 8; then +cat >> confdefs.h <<\EOF +#define U64 unsigned +EOF + +else +if test $ac_cv_sizeof_long -eq 8; then +cat >> confdefs.h <<\EOF +#define U64 unsigned long +EOF + +fi +fi + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 +echo "configure:1073: checking for $ac_hdr that defines DIR" >&5 +if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include <$ac_hdr> +int main() { +DIR *dirp = 0; +; return 0; } +EOF +if { (eval echo configure:1086: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_header_dirent_$ac_safe=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_dirent_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then +echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 +echo "configure:1111: checking for opendir in -ldir" >&5 +ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldir $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -ldir" +else + echo "$ac_t""no" 1>&6 +fi + +else +echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 +echo "configure:1152: checking for opendir in -lx" >&5 +ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lx $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -lx" +else + echo "$ac_t""no" 1>&6 +fi + +fi + + +for ac_func in scandir +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1197: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* 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(); + +int main() { + +/* 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 +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1225: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1253: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1281: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1302: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1319: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +# If we find X, set shell vars x_includes and x_libraries to the +# paths, otherwise set no_x=yes. +# Uses ac_ vars as temps to allow command line to override cache and checks. +# --without-x overrides everything else, but does not touch the cache. +echo $ac_n "checking for X""... $ac_c" 1>&6 +echo "configure:1346: checking for X" >&5 + +# Check whether --with-x or --without-x was given. +if test "${with_x+set}" = set; then + withval="$with_x" + : +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then + # Both variables are already set. + have_x=yes + else +if eval "test \"`echo '$''{'ac_cv_have_x'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=NO ac_x_libraries=NO +rm -fr conftestdir +if mkdir conftestdir; then + cd conftestdir + # Make sure to not put "make" in the Imakefile rules, since we grep it out. + cat > Imakefile <<'EOF' +acfindx: + @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"' +EOF + if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering...", which would confuse us. + eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl; do + if test ! -f $ac_im_usrlibdir/libX11.$ac_extension && + test -f $ac_im_libdir/libX11.$ac_extension; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case "$ac_im_incroot" in + /usr/include) ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;; + esac + case "$ac_im_usrlibdir" in + /usr/lib | /lib) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries="$ac_im_usrlibdir" ;; + esac + fi + cd .. + rm -fr conftestdir +fi + +if test "$ac_x_includes" = NO; then + # Guess where to find include files, by looking for this one X11 .h file. + test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h + + # First, try using that file with no special directory specified. +cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1413: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + # We can compile using X headers with no special include directory. +ac_x_includes= +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + # Look for the header file in a standard set of common directories. +# Check X11 before X11Rn because it is often a symlink to the current release. + for ac_dir in \ + /usr/X11/include \ + /usr/X11R6/include \ + /usr/X11R5/include \ + /usr/X11R4/include \ + \ + /usr/include/X11 \ + /usr/include/X11R6 \ + /usr/include/X11R5 \ + /usr/include/X11R4 \ + \ + /usr/local/X11/include \ + /usr/local/X11R6/include \ + /usr/local/X11R5/include \ + /usr/local/X11R4/include \ + \ + /usr/local/include/X11 \ + /usr/local/include/X11R6 \ + /usr/local/include/X11R5 \ + /usr/local/include/X11R4 \ + \ + /usr/X386/include \ + /usr/x386/include \ + /usr/XFree86/include/X11 \ + \ + /usr/include \ + /usr/local/include \ + /usr/unsupported/include \ + /usr/athena/include \ + /usr/local/x11r5/include \ + /usr/lpp/Xamples/include \ + \ + /usr/openwin/include \ + /usr/openwin/share/include \ + ; \ + do + if test -r "$ac_dir/$x_direct_test_include"; then + ac_x_includes=$ac_dir + break + fi + done +fi +rm -f conftest* +fi # $ac_x_includes = NO + +if test "$ac_x_libraries" = NO; then + # Check for the libraries. + + test -z "$x_direct_test_library" && x_direct_test_library=Xt + test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc + + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS="$LIBS" + LIBS="-l$x_direct_test_library $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + LIBS="$ac_save_LIBS" +# We can link X programs with no special library path. +ac_x_libraries= +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + LIBS="$ac_save_LIBS" +# First see if replacing the include by lib works. +# Check X11 before X11Rn because it is often a symlink to the current release. +for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \ + /usr/X11/lib \ + /usr/X11R6/lib \ + /usr/X11R5/lib \ + /usr/X11R4/lib \ + \ + /usr/lib/X11 \ + /usr/lib/X11R6 \ + /usr/lib/X11R5 \ + /usr/lib/X11R4 \ + \ + /usr/local/X11/lib \ + /usr/local/X11R6/lib \ + /usr/local/X11R5/lib \ + /usr/local/X11R4/lib \ + \ + /usr/local/lib/X11 \ + /usr/local/lib/X11R6 \ + /usr/local/lib/X11R5 \ + /usr/local/lib/X11R4 \ + \ + /usr/X386/lib \ + /usr/x386/lib \ + /usr/XFree86/lib/X11 \ + \ + /usr/lib \ + /usr/local/lib \ + /usr/unsupported/lib \ + /usr/athena/lib \ + /usr/local/x11r5/lib \ + /usr/lpp/Xamples/lib \ + /lib/usr/lib/X11 \ + \ + /usr/openwin/lib \ + /usr/openwin/share/lib \ + ; \ +do + for ac_extension in a so sl; do + if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f conftest* +fi # $ac_x_libraries = NO + +if test "$ac_x_includes" = NO || test "$ac_x_libraries" = NO; then + # Didn't find X anywhere. Cache the known absence of X. + ac_cv_have_x="have_x=no" +else + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries" +fi +fi + fi + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + echo "$ac_t""$have_x" 1>&6 + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$x_includes ac_x_libraries=$x_libraries" + echo "$ac_t""libraries $x_libraries, headers $x_includes" 1>&6 +fi + +if test "$no_x" = yes; then + # Not all programs may use this symbol, but it does not hurt to define it. + cat >> confdefs.h <<\EOF +#define X_DISPLAY_MISSING 1 +EOF + + X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= +else + if test -n "$x_includes"; then + X_CFLAGS="$X_CFLAGS -I$x_includes" + fi + + # It would also be nice to do this for all -L options, not just this one. + if test -n "$x_libraries"; then + X_LIBS="$X_LIBS -L$x_libraries" + # For Solaris; some versions of Sun CC require a space after -R and + # others require no space. Words are not sufficient . . . . + case "`(uname -sr) 2>/dev/null`" in + "SunOS 5"*) + echo $ac_n "checking whether -R must be followed by a space""... $ac_c" 1>&6 +echo "configure:1595: checking whether -R must be followed by a space" >&5 + ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries" + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + ac_R_nospace=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_R_nospace=no +fi +rm -f conftest* + if test $ac_R_nospace = yes; then + echo "$ac_t""no" 1>&6 + X_LIBS="$X_LIBS -R$x_libraries" + else + LIBS="$ac_xsave_LIBS -R $x_libraries" + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + ac_R_space=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_R_space=no +fi +rm -f conftest* + if test $ac_R_space = yes; then + echo "$ac_t""yes" 1>&6 + X_LIBS="$X_LIBS -R $x_libraries" + else + echo "$ac_t""neither works" 1>&6 + fi + fi + LIBS="$ac_xsave_LIBS" + esac + fi + + # Check for system-dependent libraries X programs must link with. + # Do this before checking for the system-independent R6 libraries + # (-lICE), since we may need -lsocket or whatever for X linking. + + if test "$ISC" = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" + else + # Martyn.Johnson@cl.cam.ac.uk says this is needed for Ultrix, if the X + # libraries were built with DECnet support. And karl@cs.umb.edu says + # the Alpha needs dnet_stub (dnet does not exist). + echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6 +echo "configure:1660: checking for dnet_ntoa in -ldnet" >&5 +ac_lib_var=`echo dnet'_'dnet_ntoa | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldnet $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6 +echo "configure:1701: checking for dnet_ntoa in -ldnet_stub" >&5 +ac_lib_var=`echo dnet_stub'_'dnet_ntoa | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldnet_stub $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" +else + echo "$ac_t""no" 1>&6 +fi + + fi + + # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, + # to get the SysV transport functions. + # chad@anasazi.com says the Pyramis MIS-ES running DC/OSx (SVR4) + # needs -lnsl. + # The nsl library prevents programs from opening the X display + # on Irix 5.2, according to dickey@clark.net. + echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6 +echo "configure:1749: checking for gethostbyname" >&5 +if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname(); + +int main() { + +/* 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_gethostbyname) || defined (__stub___gethostbyname) +choke me +#else +gethostbyname(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1777: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_gethostbyname=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_gethostbyname=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_gethostbyname = no; then + echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 +echo "configure:1798: checking for gethostbyname in -lnsl" >&5 +ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lnsl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" +else + echo "$ac_t""no" 1>&6 +fi + + fi + + # lieder@skyler.mavd.honeywell.com says without -lsocket, + # socket/setsockopt and other routines are undefined under SCO ODT + # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary + # on later versions), says simon@lia.di.epfl.ch: it contains + # gethostby* variants that don't use the nameserver (or something). + # -lsocket must be given before -lnsl if both are needed. + # We assume that if connect needs -lnsl, so does gethostbyname. + echo $ac_n "checking for connect""... $ac_c" 1>&6 +echo "configure:1847: checking for connect" >&5 +if eval "test \"`echo '$''{'ac_cv_func_connect'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect(); + +int main() { + +/* 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_connect) || defined (__stub___connect) +choke me +#else +connect(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1875: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_connect=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_connect=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'connect`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_connect = no; then + echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6 +echo "configure:1896: checking for connect in -lsocket" >&5 +ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocket $X_EXTRA_LIBS $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" +else + echo "$ac_t""no" 1>&6 +fi + + fi + + # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX. + echo $ac_n "checking for remove""... $ac_c" 1>&6 +echo "configure:1939: checking for remove" >&5 +if eval "test \"`echo '$''{'ac_cv_func_remove'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char remove(); + +int main() { + +/* 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_remove) || defined (__stub___remove) +choke me +#else +remove(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1967: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_remove=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_remove=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'remove`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_remove = no; then + echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6 +echo "configure:1988: checking for remove in -lposix" >&5 +ac_lib_var=`echo posix'_'remove | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lposix $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" +else + echo "$ac_t""no" 1>&6 +fi + + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + echo $ac_n "checking for shmat""... $ac_c" 1>&6 +echo "configure:2031: checking for shmat" >&5 +if eval "test \"`echo '$''{'ac_cv_func_shmat'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shmat(); + +int main() { + +/* 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_shmat) || defined (__stub___shmat) +choke me +#else +shmat(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2059: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_shmat=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_shmat=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'shmat`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_shmat = no; then + echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6 +echo "configure:2080: checking for shmat in -lipc" >&5 +ac_lib_var=`echo ipc'_'shmat | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lipc $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" +else + echo "$ac_t""no" 1>&6 +fi + + fi + fi + + # Check for libraries that X11R6 Xt/Xaw programs need. + ac_save_LDFLAGS="$LDFLAGS" + test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" + # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to + # check for ICE first), but we must link in the order -lSM -lICE or + # we get undefined symbols. So assume we have SM if we have ICE. + # These have to be linked with before -lX11, unlike the other + # libraries we check for below, so use a different variable. + # --interran@uluru.Stanford.EDU, kb@cs.umb.edu. + echo $ac_n "checking for IceConnectionNumber in -lICE""... $ac_c" 1>&6 +echo "configure:2132: checking for IceConnectionNumber in -lICE" >&5 +ac_lib_var=`echo ICE'_'IceConnectionNumber | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lICE $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" +else + echo "$ac_t""no" 1>&6 +fi + + LDFLAGS="$ac_save_LDFLAGS" + +fi + +echo "Ignoring libraries \"$X_PRE_LIBS\" requested by configure." +LIBS="$LIBS$X_LIBS" +CFLAGS="$CFLAGS $X_CFLAGS" +CPPFLAGS="$CPPFLAGS $X_CFLAGS" + +GLLIB= +echo $ac_n "checking for glXMakeCurrent in -lGL""... $ac_c" 1>&6 +echo "configure:2182: checking for glXMakeCurrent in -lGL" >&5 +ac_lib_var=`echo GL'_'glXMakeCurrent | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lGL \ + -lX11 -lXext $X_EXTRA_LIBS -lm $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_GL 1 +EOF + GLLIB=" -lGLU -lGL" +else + echo "$ac_t""no" 1>&6 +\ + echo $ac_n "checking for glXMakeCurrent in -lMesaGL""... $ac_c" 1>&6 +echo "configure:2225: checking for glXMakeCurrent in -lMesaGL" >&5 +ac_lib_var=`echo MesaGL'_'glXMakeCurrent | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lMesaGL \ + -lX11 -lXext $X_EXTRA_LIBS -lm $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_GL 1 +EOF + GLLIB=" -lMesaGLU -lMesaGL" +else + echo "$ac_t""no" 1>&6 +fi + +fi + + + +ac_safe=`echo "X11/extensions/Xdbe.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for X11/extensions/Xdbe.h""... $ac_c" 1>&6 +echo "configure:2274: checking for X11/extensions/Xdbe.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2284: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_XDBE 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + + +echo $ac_n "checking "for X overlay visuals"""... $ac_c" 1>&6 +echo "configure:2310: checking "for X overlay visuals"" >&5 +if eval "test \"`echo '$''{'ac_cv_have_overlay'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if xprop -root 2>/dev/null | grep -c "SERVER_OVERLAY_VISUALS" >/dev/null; then + ac_cv_have_overlay=yes +else + ac_cv_have_overlay=no +fi +fi + +echo "$ac_t""$ac_cv_have_overlay" 1>&6 +if test "$ac_cv_have_overlay" = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_OVERLAY 1 +EOF + +fi + +MAKEDEPEND="\$(CXX) -M" + +if test -n "$GXX"; then + CFLAGS="-Wall -O2" + CFLAGS_D="-Wall -Wno-return-type -g -DDEBUG" + CXXFLAGS="-Wall -Wno-return-type -O2" + CXXFLAGS_D="-Wall -Wno-return-type -g -DDEBUG" +else +if test "`(uname) 2>/dev/null`" = IRIX; then + if expr "`(uname -r)`" \>= 6.2; then + # compiler names: + CXX="CC -n32" + CC="cc -n32" + LD="ld -n32" + MAKEDEPEND="CC -M" + # -woff 3322 is necessary due to errors in Xlib headers on IRIX + CFLAGS="-fullwarn -O2" + CFLAGS_D="-fullwarn -gslim -DDEBUG" + CXXFLAGS="-fullwarn -woff 1685 -woff 3322 -O2" + CXXFLAGS_D="-fullwarn -woff 1685 -woff 3322 -gslim -DDEBUG" + else + CFLAGS="-O2" + CFLAGS_D="-g -DDEBUG" + CXXFLAGS="+w +pp -O2" + CXXFLAGS_D="+w +pp -g -DDEBUG" + fi +else + CFLAGS="-O" + CFLAGS_D="-g -DDEBUG" + CXXFLAGS="-O" + CXXFLAGS_D="-g -DDEBUG" +fi +fi + + + + +trap '' 1 2 15 +cat > confcache <<\EOF +# 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. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# 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) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir + +trap 'rm -fr `echo "makeinclude config.h:configh.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@CC@%$CC%g +s%@CXX@%$CXX%g +s%@RANLIB@%$RANLIB%g +s%@CPP@%$CPP%g +s%@X_CFLAGS@%$X_CFLAGS%g +s%@X_PRE_LIBS@%$X_PRE_LIBS%g +s%@X_LIBS@%$X_LIBS%g +s%@X_EXTRA_LIBS@%$X_EXTRA_LIBS%g +s%@GLLIB@%$GLLIB%g +s%@MAKEDEPEND@%$MAKEDEPEND%g +s%@CFLAGS_D@%$CFLAGS_D%g +s%@CXXFLAGS_D@%$CXXFLAGS_D%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# 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_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # 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" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + diff --git a/configure.in b/configure.in new file mode 100644 index 000000000..46b856b68 --- /dev/null +++ b/configure.in @@ -0,0 +1,106 @@ +dnl# -*- sh -*- +dnl# the "configure" script is made from this by running GNU "autoconf" + +AC_INIT(src/Fl.C) +AC_PROG_CC +AC_PROG_CXX +dnl# AC_PROG_INSTALL + +AC_C_BIGENDIAN + +AC_CHECK_SIZEOF(short, 2) +AC_CHECK_SIZEOF(int, 4) +AC_CHECK_SIZEOF(long, 4) +if test $ac_cv_sizeof_short -eq 2; then +AC_DEFINE(U16,unsigned short) +fi +if test $ac_cv_sizeof_int -eq 4; then +AC_DEFINE(U32,unsigned) +else +if test $ac_cv_sizeof_long -eq 4; then +AC_DEFINE(U32,unsigned long) +fi +fi +if test $ac_cv_sizeof_int -eq 8; then +AC_DEFINE(U64,unsigned) +else +if test $ac_cv_sizeof_long -eq 8; then +AC_DEFINE(U64,unsigned long) +fi +fi + +AC_HEADER_DIRENT + +AC_CHECK_FUNCS(scandir) + +AC_PROG_RANLIB + +AC_PATH_XTRA +echo "Ignoring libraries \"$X_PRE_LIBS\" requested by configure." +dnl# LIBS="$LIBS$X_LIBS$X_PRE_LIBS" +LIBS="$LIBS$X_LIBS" +CFLAGS="$CFLAGS $X_CFLAGS" +CPPFLAGS="$CPPFLAGS $X_CFLAGS" + +dnl# My test to see if OpenGL is on this machine: +GLLIB= +AC_CHECK_LIB(GL, glXMakeCurrent, AC_DEFINE(HAVE_GL) GLLIB=" -lGLU -lGL", \ + AC_CHECK_LIB(MesaGL,glXMakeCurrent, AC_DEFINE(HAVE_GL) GLLIB=" -lMesaGLU -lMesaGL",,\ + -lX11 -lXext $X_EXTRA_LIBS -lm), \ + -lX11 -lXext $X_EXTRA_LIBS -lm) +AC_SUBST(GLLIB) + +AC_CHECK_HEADER(X11/extensions/Xdbe.h, AC_DEFINE(HAVE_XDBE)) + +AC_CACHE_CHECK("for X overlay visuals", ac_cv_have_overlay, +if xprop -root 2>/dev/null | grep -c "SERVER_OVERLAY_VISUALS" >/dev/null; then + ac_cv_have_overlay=yes +else + ac_cv_have_overlay=no +fi) +if test "$ac_cv_have_overlay" = yes; then + AC_DEFINE(HAVE_OVERLAY) +fi + +MAKEDEPEND="\$(CXX) -M" + +dnl# add warnings and optimization to compiler switches: +dnl# do this last so messing with switches does not break tests +if test -n "$GXX"; then + CFLAGS="-Wall -O2" + CFLAGS_D="-Wall -Wno-return-type -g -DDEBUG" + CXXFLAGS="-Wall -Wno-return-type -O2" + CXXFLAGS_D="-Wall -Wno-return-type -g -DDEBUG" +else +if test "`(uname) 2>/dev/null`" = IRIX; then + if expr "`(uname -r)`" \>= 6.2; then + # compiler names: + CXX="CC -n32" + CC="cc -n32" + LD="ld -n32" + MAKEDEPEND="CC -M" + # -woff 3322 is necessary due to errors in Xlib headers on IRIX + CFLAGS="-fullwarn -O2" + CFLAGS_D="-fullwarn -gslim -DDEBUG" + CXXFLAGS="-fullwarn -woff 1685 -woff 3322 -O2" + CXXFLAGS_D="-fullwarn -woff 1685 -woff 3322 -gslim -DDEBUG" + else + CFLAGS="-O2" + CFLAGS_D="-g -DDEBUG" + CXXFLAGS="+w +pp -O2" + CXXFLAGS_D="+w +pp -g -DDEBUG" + fi +else + CFLAGS="-O" + CFLAGS_D="-g -DDEBUG" + CXXFLAGS="-O" + CXXFLAGS_D="-g -DDEBUG" +fi +fi +AC_SUBST(MAKEDEPEND) +AC_SUBST(CFLAGS_D) +AC_SUBST(CXXFLAGS_D) +AC_CONFIG_HEADER(config.h:configh.in) +AC_OUTPUT(makeinclude ) + +dnl# end of configure.in diff --git a/documentation/CHANGES b/documentation/CHANGES new file mode 100644 index 000000000..0624e8679 --- /dev/null +++ b/documentation/CHANGES @@ -0,0 +1,411 @@ +Fltk modification history
+
+9/22/98: uses X regions for update
+9/16/98: added Fl_Widget::output(), works like inactive but draws normally
+9/15/98: multi-browser has some keyboard navigation
+9/10/98: fl_ok, fl_cancel, fl_yes, fl_no pointers added to change language
+9/09/98: default_font() & default_size() added, made style demo
+9/09/98: fixed so child windows activate/deactivate correctly
+9/08/98: does not set colormap, relies on WM_COLORMAP_WINDOWS working
+9/08/98: added default_box, _font, _size to Fl_Input & Fl_Browser
+9/04/98: Fl_Tabs changes cursor to show what you can move
+9/03/98: child windows respond to FL_SHOW/FL_HIDE (so OpenGL in Fl_Tabs works!)
+9/03/98: Fl_Group::add() calls Fl_Group::remove() if child already in a group
+9/02/98: moved textsize/font/color from Fl_Browser to Fl_Browser_.
+9/02/98: most boxtypes draw inactive when widget is inactive
+9/01/98: Fl_Browser can store a void* data() value with each line
+9/01/98: added Fl_Browser_::has_scrollbar(uchar)
+8/31/98: Fl_Valuator step 'A' value is now a double instead of int
+8/27/98: transparecy in Fl_Pixmap handled correctly! (X only)
+8/26/98: fl_rotate(0,90,180,270,-90) fixed to not have math rounding errors
+8/26/98: added fl_point and fl_begin/end_points drawing functions
+8/24/98: Added ability to #define WINDOWS_STYLE in config.h (try it)
+8/24/98: Made default color be 75% gray to match KDE & Gnome (and Windows)
+8/23/98: All widgets draw their labels gray if inactive (try inactive demo)
+8/23/98: Fl_Color, Fl_Font, Fl_Boxtype, Fl_Labeltype enumerations
+	 (this may break some existing code and need casts added)
+8/21/98: filename_list() and filename_isdir() made public and documented
+8/21/98: fl_draw_image will use 64 bit data types if available (Cray fix)
+8/18/98: fluid can set the output file names (on preferences panel)
+8/18/98: fluid lets you set textfont() and textsize() of Fl_Menu_ widgets
+8/16/98: Added Fl_Scrollbar, and used for Fl_Browser & Fl_Scroll
+8/14/98: Fluid didn't put variable into .h file if 'o' variable not needed
+8/14/98: Vastly improved display on MSWindows in 8-bit mode, matches X 8bit mode
+8/11/98: fixed stupid error that broke the menus on MSWindows
+8/11/98: Fl::args(a,b,&i,c) no longer depends on initial value of i
+8/10/98: fixed the mouse position during grab() on MSWindows!
+8/10/98: some bugs with resizing in fluid fixed, does not raise panel
+8/10/98: Fl::event_key() returns unshifted (lowercase) keysym always
+8/09/98: Tested on NT, compilation errors there fixed
+8/07/98: Fl_Scroll can force scrollbars on at all times (add 4 to type())
+8/07/98: renamed one of the Fl_Menu_Item methods from "popup" to "pulldown"
+8/06/98: you no longer have to call show() on child windows!!!
+8/06/98: added move() to Fl_Browser (Curtis please test!)
+8/06/98: Some fixes to resizable() handling, it does not need to be a child
+8/06/98: & in Fl_Choice menu item is not drawn in the widget itself
+8/05/98: Fl_Menu_Button::type(POPUP) allows box() to work for menu
+8/04/98: fixed Fl_Menu_Button to not call menu item twice
+7/30/98: Fl_Browser scrolls to bottom when add() is done
+7/30/98: fixed some bugs with the horizontal scrollbars in Fl_Browser_
+7/29/98: kludge so it can simulate MSWindows menus (try the menubar demo)
+7/27/98: you can set a menu's boxtype & color!  Try it in fluid
+7/26/98: float/int input fields do not prevent letters from being shortcuts
+7/26/98: fluid reads .xpm and .xbm files with comments inserted at start
+7/25/98: added fl_password() popup utility
+7/25/98: added horizontal scrollbar to Fl_Browser
+7/25/98: fixed fluid crash on startup (Fl::get_system_colors opens display)
+7/18/98: new menu behavior so moving mouse does not wreck keyboard navigation
+7/17/98: added Fl::own_colormap() and Fl::get_system_colors() init functions
+7/16/98: fixed overlay on Reality Engine
+7/14/98: fl_begin_offscreen() clears clip region, fl_end_offscreen restores it
+7/14/98: uses gettimeofday() instead of times() (faster & more portable?)
+7/10/98: fl_color() and gl_color() work in the overlays!
+7/09/98: inverted meaning & default of the FL_ALIGN_WRAP bit (INCOMPATABLE!)
+7/08/98: fixed (brute force) the titlebar & grab during menus on MSWindows
+7/08/98: shortcuts fixed so they work when mouse is not pointing at any window
+7/07/98: fixed FL_NO_LABEL and some other symbols output by fluid
+7/06/98: Fl_Gl_Window overlay was missized if window resize before redraw_overlay
+7/06/98: Fl_Window::resize() changes size immediately, does not wait for X
+7/05/98: Fl::wait(), Fl::check(), and Fl::run() return 0 when no windows
+6/30/98: buttons and toggle/radio menu items write value() to .fl file
+6/29/98: made output of fluid more readable
+6/29/98: fluid writes callbacks inside a class as real (not static) methods
+6/27/98: added classes to fluid
+6/24/98: emulated Fl::set_atclose(), lots of programs use it!
+6/24/98: Added Fl_Pack.  Fl_Scroll still needs some work to use this
+6/23/98: Removed (most of) the unused-variable errors in fluid output
+6/22/98: Renamed Fl_Menu to Fl_Menu_Item (typedef for back compatability)
+6/22/98: Added @|| symbol so you have complete tape deck controls
+6/22/98: MSWindows menus now come out atop the icon dock
+6/22/98: FL_MENU_RADIO draws diamond rather than square
+6/22/98: X fl_polygon changed to match the MSWindows version
+6/19/98: Fixed bug on Solaris (sprintf in fl_font.C)
+6/18/98: Fixed Alt-GR on foreign keyboards under MSWindows
+6/17/98: added Fl_Menu_::global() so shortcuts work everywhere
+6/16/98: Tried to make Fl_Scroll better, children can change their size
+6/15/98: Fl_Window::callback replaces Fl::atclose (which is deleted)
+6/15/98: FL_INT_INPUT & FL_FLOAT_INPUT just draw text red if it is illegal
+6/15/98: Fl_Valuator::format() is a virtual function
+6/14/98: fixed fl_draw_image on 8-bit truecolor visuals
+6/10/98: simplified forms compatability: Fl_Group::end_forms() replaces stuff
+6/09/98: Added "New" to fluid, fixed some bugs with redisplay
+
+fltk-0.99
+
+6/07/98: fluid no longer puts 'if (!w) {...}' around code for window w
+6/07/98: Can compile shared library on Linux (matches Debian release)
+6/05/98: added Fl_Menu_::popup(x,y,w,h) and Fl_Menu_Button::popup()
+6/05/98: greatly speeded up truecolor visuals by not doing XAllocColor
+6/03/98: zero-sized fl_clip() works
+6/02/98: fluid cut file moved from /tmp to $HOME for security reasons
+6/01/98: MSWindows color palette support on 8-bit displays
+5/27/98: fluid can set shortcuts of buttons and menu items
+5/26/98: integer (instead of string) button & menu shortcuts (INCOMPATABLE)
+5/23/98: cut/paste for MSWindows
+5/23/98: detects if OpenGL overlay exists on MSWindows
+5/22/98: fixes for IRIX 6.2 n32 compiler
+5/20/98: added code, codeblock, decl, and declblock to fluid
+5/20/98: you can pick the items off of menus in fluid
+5/19/98: fluid can now create menus & menu items!
+5/19/98: Fl_Bitmap, Fl_Pixmap, Fl_Image now have label(Fl_Menu) method
+5/17/98: Can use hardware overlay planes in Fl_Gl_Window on MSWindows
+5/16/98: Fl_Light_Button uses down_box() to determine light shape
+5/13/98: fixed many annoying bugs on MSWindows
+5/10/98: new Fl::grab(Fl_Widget*) replaces modal(Fl_Widget*)
+5/05/98: Fl_Gl_Window does not use scissor anymore
+5/04/98: changed Fl_Color_Chooser to use floating point rgb values
+5/04/98: added Fl_Browser @-commands to set font, color, size, background
+5/04/98: added Fl_Browser::column_widths() for multi-column display
+5/04/98: renamed Fl_Browser::specialkey() to Fl_Browser::format_char()
+5/04/98: fixed float/int input where they never work after 1st illegal char.
+5/03/98: fixed bitmaps on MSWindows
+4/27/98: renamed Fl_Slider::size() to Fl_Slider::slider_size()
+4/27/98: renamed fl_pixmap_size to fl_measure_pixmap
+4/27/98: added labeltype measure function, tabs & menus use it
+4/26/98: added labeltype/font/size/color to Fl_Menu
+4/26/98: '_' in menus replaced with FL_MENU_DIVIDER bit (!!! INCOMPATABLE !!!)
+4/21/98: swapped OK/cancel positions on popups to match gtk/gnome
+4/20/98: added Fl_Window::non_modal()
+4/19/98: '/' in menus replaced with FL_SUBMENU bit (!!! INCOMPATABLE !!!)
+4/16/98: fluid puts extra_code for windows & groups *after* adding children
+4/15/98: fixed numericsort to work for more than 10 digits.
+4/15/98: merges adjacent mouse-moved events (should have motion history)
+4/15/98: event mask for children windows left on (helps for using fl_xevent)
+4/12/98: added Fl_Input::static_value(x) that avoids doing malloc & copy
+4/12/98: you can insert ^@ (nul) into Fl_Input, Fl_Output, and cut/paste
+4/12/98: secret fl_encoding variable may be set to override iso8859-1
+4/11/98: added FL_ALIGN_NOWRAP & FL_ALIGN_CLIP
+4/10/98: MSWindows supports OpenGL!
+4/10/98: uses transient_for property for modal windows
+4/05/98: added Fl::modal(window) to fix menu problems
+4/05/98: better drawing of dials
+3/22/98: replaced Fl::abort() with: Fl::warning(), Fl::error(), Fl::fatal()
+3/22/98: added Fl::set_fonts() to get all the fonts from server
+3/21/98: really neato new color chooser
+3/17/98: new fl_draw_image with callback for arbitrary image data formats
+3/17/98: mucho improvement in the MSWindows port, it is now usable!
+3/16/98: new fl_show_colormap (single pop-up array of all colors)
+3/13/98: fixed borders under KDE's kwm.
+3/13/98: Uses X regions to update window, new fl_clip functions
+3/08/98: Round buttons now draw much more attractively
+3/05/98: Fl_Tabs draws the tabs much nicer
+3/05/98: Fl_Input now does compose-character sequences
+3/04/98: Fluid: changing objects with panel open saves changes to old objects
+3/03/98: Uses select() instead of poll() even on sgi (fixes Irix 6.3)
+2/26/98: Added Fl::get_key(n), Fl::event_key(n), Fl::event_state(n)
+2/23/98: Added Fl_Tile (maximum of 2 across and 2 down children)
+2/07/98: Esc key (if not used for anything else) will close window
+2/07/98: Adds ":0.0" to -display if missing
+2/06/98: Rearrangement to make a MSWindows port easier
+2/02/98: Does not die on X errors
+2/01/98: Controls for valuators added to fluid
+2/01/98: Added Fl_Value_Input and Fl_Value_Output
+1/29/98: Added Fl_Valuator base class for sliders, dials, etc
+1/29/98: fixed colormap-allocation hang on Solaris
+1/27/98: fixed the red-window problem in fluid on IRIX 6.2
+1/26/98: changed float to double everywhere to shut MSVC++ up
+1/23/98: Fl_Group does begin() in constructor (dangerous?)
+1/23/98: Greatly simplified how to subclass groups and redraw them
+1/22/98: Added Fl_Widget::damage(bits,x,y,w,h) to do clipped redrawing
+1/22/98: New Fl_Bitmap::draw() methods (and Fl_Pixmap, Fl_Image)
+1/22/98: Word wrap in the labels
+1/21/98: Renamed Fl_Object to Fl_Widget, to match common toolkit terminology
+
+fltk-0.98
+
+1/17/98: renamed the library to fltk
+1/14/98: added fl_curve
+1/14/98: fl_arc really works (finally!) no more 16-sided circles
+1/14/98: replaced fl_end() with fl_end_line(), etc
+1/12/98: Does not crash with very large WM_COMMAND strings
+1/12/98: Cleaner menus that work ok w/o overlay or save-behind
+1/12/98: Fluid objects may be named "a.x" or "a->x" or similar
+1/12/98: Fl_Double_Window supported in fluid with a kludge
+
+FL-0.98
+
+1/9/98: Fl_Group now uses array, eliminated next(), prev(), first(), last()
+1/7/98: Removed many uninteresting test programs to make distribution smaller
+1/7/98: Removed Fl_Window::set_atclose(), use Fl::set_atclose() instead
+1/6/98:	Reduction of number of .html files used for documentation
+1/6/98: added event_is_click(), renamed reset_clicks to event_is_click(0)
+12/15/97: Huge improvements to menus: can pop up with any item selected
+	  and Fl_Choice uses this to pop up lists with arrow on item,
+	  underscore shortcuts added to Fl_Menu_Button and Fl_Choice
+	  and Fl_Menu_Bar.
+12/12/97: Fl_Gl_Window::invalidate() added, use this instead of valid(0)
+12/11/97: New navigation keys in the menu code!
+12/11/97: Microsloth-style underscore shortcuts on all buttons
+12/07/97: Fixed Xdbe (it sent backbuffer rather than window toXDBEswap...())
+12/05/97: mandelbrot demo created
+12/05/97: Fl_Window::make_current() for incremental redrawing added
+12/05/97: fl_overlay_rect() and fl_overlay_erase() to xor selection box
+12/02/97: Shortcut keys to scroll browser up/down (finally!)
+
+FL-0.97
+
+11/30/97: Many bugs with overlay + Xdbe windows fixed
+11/30/97: Numeric keypad types numbers even if NumLock off (not portable?)
+11/28/97: Fluid frees unused images
+11/25/97: Added Fl_Object::size_range(...) to control resizing
+11/25/97: Fluid can label objects with xbm, xpm, or gif images!
+11/24/97: FL_DRAG & FL_MOVE set Fl::event_time()
+11/23/97: minimal update for sliders (less blinking of large sliders)
+11/17/97: renamed Fl_Input_::handle to handletext to prevent C++ warnings
+11/17/97: minimal update for Fl_Browser (less blinking)
+11/17/97: ability to set and check edge thickness of box types
+11/16/97: Added Xdbe (double buffer extension) support to Fl_Double_Window
+11/11/97: fixed crash if FL_RELEASE deletes Fl::pushed() object
+11/11/97: ./configure makes a config.h, detects many more things
+11/10/97: can use 32bit visuals with xrgb data layout
+11/10/97: restored code for arbitrary 32 bit visual color masks
+11/10/97: fl_draw_pixmap shares buffer with fl_draw_image
+
+FL-0.96
+
+11/06/97: Uses GNU ./configure script to build
+11/05/97: Made fluid work with Fl_Tabs
+11/03/97: Fl_Browser_ has show_scrollbar() virtual func for subclass
+	  to override to change type of scrollbar or force it on
+11/03/97: Fl_Slider::slider(uchar) attribute to set box type for slider
+11/03/97: no limit on how many points are sent to fl_vertex() 
+11/03/97: added FL_OVAL_BOX, FL_OFLAT_BOX, FL_OSHADOW_BOX, FL_OVAL_FRAME
+10/29/97: made fluid read fd files from Forms and XForms fdesign (sort of)
+10/28/97: fluid works!  I am ready to release it.  Needs directions
+10/28/97: renamed Fl_Text to Fl_Output
+10/28/97: added Fl_Text_Adjuster
+10/28/97: fixed double window crash when fl_gc is not set correctly
+10/22/97: made Fl_Text be a subclass of Fl_Input_
+10/16/97: mucho work on fluid!  almost there...
+10/15/97: added Fl_Fill_Dial
+10/15/97: changed fl_circle to use XDrawArc
+10/14/97: minimal update of Fl_Input, to reduce blinking
+10/14/97: Removed all uses of fl->, replaced with Fl:: "namespace"
+10/14/97: moved setting of colors, fonts, boxtypes, labeltypes to Fl::
+10/14/97: fixed the gray ramp to really go from black to white
+10/10/97: Cleanup of button and button subclasses
+10/9/97: Changed "style" to "font" for clarity
+10/8/97: Added engraved/embossed/shadow label types
+10/6/97: Added when() to many objects
+10/1/97: Fl_Overlay_Window will use hardware overlay if possible
+10/1/97: Fixed shortcuts for Fl_Choice to do redraw
+9/29/97: Much better fl_draw_image for 8-bit visuals
+9/26/97: Fixed gl_color() when drawing into gl overlay
+9/25/97: Fl_Gl_Window simulates overlay if hardware not provided
+9/22/97: Added FL_ACTIVATE/DEACTIVATE/HIDE/SHOW event types
+9/18/97: Click/shift+click on Fl_Adjuster moves it by increments
+9/18/97: cleanup & simplification of window creation and drawing code
+9/18/97: fl_draw_into(xid), Fl_Window::make_xid(vis) added
+9/18/97: Fixed background pixel support to not try so hard
+
+FL-0.95
+
+8/25/97: Forms file chooser is emulated using libFL file chooser
+8/25/97: Uses background_pixel if possible to speed up box drawing
+8/23/97: XForms .86 compatability added, required many changes
+8/22/97: Added fl_draw_pixmap and Fl_Pixmap (simple version only!)
+8/19/97: The BIG FLIP!  Turned coordinate system over so +y is down
+8/08/97: Glut compatability added
+8/06/97: added fl_color(r,g,b) to set rgb color to draw in
+8/05/97: added fl_draw_image for color pictures (!)
+8/03/97: made x.H and put X-specific fl variables in there
+7/27/97: greately improved fl_font_enumerate to return sizes
+7/26/97: Much cleanup, rearrangement of function and header file names
+7/20/97: Added overlay drawing ability to Fl_Gl_Window
+7/17/97: Celebrated Titanic being done!  Well, mostly...
+6/25/97: Make -DUSE_X true all the time, GL fl_draw functions removed
+6/10/97: fluid finally produced code that compiles!  Still a long
+	ways to go...
+6/8/97: Added fl->add_xevent_handler so your program can get at those
+	XExtension events.  Rewrote fl->selection_owner so it uses
+	this, mostly to test it.  Added Fl_Implementation.H header
+	to src to clean up public header files.
+6/5/97: Added Fl_Window::show(argc,argv,i) so that standard switches
+	can be passed to the main window in a window-system
+	independent way.  Removed xclass() property from Fl_Window,
+	as this replaces it.
+6/5/97: Deferred XMapWindow till fl->flush(), to allow above to work
+4/15/97: needdraw() renamed to damage(), for clarity.
+4/15/97: code rearranged so you don't have to link -lGL if you don't use it
+4/15/97: #ifdef MESA will cause Fl_Gl_Window to take advantage of
+	the fact that the back buffer is unchanged by damage.
+4/18/97: Can use poll() instead of select().  To make your machine
+	use this, see Fl_Poll.H and turn on USE_POLL and turn off USE_SELECT.
+
+FL-0.94
+
+3/26/97: Fl_Browser_ (and Fl_Browser) preserves the position(), even
+	if it is below the data.
+3/26/97: Renamed resizebox() to resizable()
+3/25/97: Made all Fl object instance variables be static.
+3/23/97: Added focus(), belowmouse(), pushed(), and selection_owner()
+	tracking to the Fl object.  Since only one object can be this
+	at a time, this gets rid of redundant storage in every object
+	such as the pushed_ field that was on the buttons.  Also
+	greatly simplified Fl_Group.
+3/21/97: Added glXReleaseBuffersMESA if #ifdef MESA
+3/7/97: Renamed some source files to avoid name conflicts on MSWindows.
+3/5/97: Fl_Menu returns item selected, caller now does the callback.
+3/5/97: Renamed Fl_Menubar to Fl_Menu_Bar.
+3/5/97: Improvements to how Fl_Input scrolls.
+2/11/97: Installs the window's colormap when the mouse enters window.
+2/5/97: Cleaned up the close and exit behavior.  The only way to stop
+	the close box from closing a window is to subclass it and
+	change the response to FL_CLOSE.  The callback is done,
+	however, before closing the window.  Added exit() and error()
+	methods to Fl class, which you can "override" by defining
+	your own versions in your source code.
+1/24/97: Restored setting of XSizeHints (many window managers ignore
+	the Motif window information).
+
+FL-0.93
+
+1/23/97: Got it to compile and run (with -DNO_GL) on Dec Alpha Unix!
+	Mostly this meant getting rid of trailing commas on enum lists.
+1/20/97: DDForms-compatable resize behavior, where it scales
+	everything inside the resizebox.  Also fixed resizing of a
+	group inside a window.
+1/12/97: typing a shift key on some Xlib versions no longer produces
+	a character.  Fixed display of characters shown as \xxx.
+1/12/97: Got it to compile and run (with -DNO_GL) on Alpha Linux.
+1/11/97: Fl_Browser now has a topline() attribute that you can get
+	and set, as well as the Fl_Browser_::position() attribute.
+	topline() is in lines, position() is in pixels.
+1/11/97: General code clean up and size reduction.
+1/11/97: Fl_Group::focus(x) fixed to always work
+1/8/97: fl_file_chooser uses the scandir(), much faster!
+1/7/97: Removed setting of XSizeHints
+12/96: More work on fluid
+
+FL-0.92
+
+10/31/96: New fl->wait() and fl->check() handling so that flip
+	book program would work.
+10/20/96: Removed calls to glFlush when not in a glx context.  This
+	bug caused Mesa 2.0 to crash.  Fixing it required extensive
+	rewriting of the Fl_Window base classes and virtual functions.
+10/../96: Lots of work done on writing fluid
+10/09/96: Added the Fl_Input_ base class.
+09/25/96: All constructors of the form Fl_x(x,y,w,h,label=0).
+09/16/96: More changes to Fl_Input, fixed the scrolling behavior,
+	made it not crash if you paste huge amounts of text in.
+09/11/96: Fixed minimal update when you resize a subwindow.
+09/10/96: Constructor no longer does add().
+09/07/96: FL_SHORTCUT is sent mouse window rather than focus window
+09/07/96: Added ^Z=undo, ^X=cut, ^C=copy ^V=paste to Fl_Input, and
+	made double-click select words and triple-click select lines.
+08/23/96: Tries to send maximum size in XSizeHints
+
+FL-0.91
+
+08/21/96: fluid uses Fl_Overlay_Window
+08/20/96: Added Fl_Overlay_Window
+08/19/96: Added Fl_Double_Window to provide double buffering
+08/19/96: Documentation for subclassing windows
+08/15/96: Fixed bugs with overriding resize() on Fl_Window
+08/15/96: Erases menus before unmap, to fix colormap flash on O2
+08/14/96: Replaced  with 
+08/14/96: Added makeinclude.svr4 (tested on a "SINEX-Z" os)
+08/14/96: Added scandir.c from the GNU C library for SVR4
+08/13/96: makefiles have LIBNAME, VERSION, and REVISION switches
+08/13/96: added (completely untested!) makeinclude.linux.so to make
+	a shared library.  I recommend however that if you are making
+	programs for any kind of distribution that you use the static
+	version of the library, rather than relying on users correctly
+	installing the shared one!
+08/13/96: fixed *many* occurances of wrong scoping of for(int x;;)
+08/13/96: patched out warning messages for enumerations from gcc.
+08/13/96: fixed crash for fixed-pitch XFonts (per_char ptr is NULL)
+08/13/96: some fixes to Fl_Chart so output matches Forms.
+08/13/96: Insure radio button not pressed if mouse released outside it
+08/13/96: Clicking in the value box of a Value_Slider does not move slider.
+08/13/96: Added switches so arrows can't navigate between text fields
+08/13/96: Initializes some stuff it should have in Fl_Menu_Button.
+08/13/96: Non-multiline Fl_Inputs do not treat ^J characters as
+	special, for instance ^K always deletes to the end even if
+	there are imbedded newlines.
+08/13/96: Tab inserts a tab in Fl_MultiLine_Input.  Use Ctrl+Tab to navigate
+08/10/96: renamed from libFL to libFl to avoid existing SGI library
+08/10/96: the static Fl_Object method readqueue has been moved to
+	a method on the Fl object.
+08/10/96: the static Fl_Object method draw_box() renamed fl_box() and
+	put in Draw.H
+08/10/96: fl_label_bitmap has been renamed fl_draw and put in Draw.H
+08/10/96: fixed the deactivated menu items to not draw over the right edge.
+08/09/96: fl_clip works in both X and GL windows when USE_X is defined.
+08/09/96: the static Fl_Object methods event_inside and test_shortcut
+	have been moved to methods on the Fl object.
+	The static Fl_Object method shortcut_text has been renamed
+	to a function fl_shortcut_text and put in the Draw.H header.
+08/09/96: many internal changes to Fl_Group and Fl_Window to support
+	minimal update.  expose() is no longer a virtual function and
+	is private to Fl_Window.  Fl_Object::flush() and qredraw()
+	deleted.  New methods: draw_child(), redraw_child(), and
+	done_drawing(), for calling by draw() implementations.
+	See (not yet written) drawing documentation.
+08/05/96: to make it possible to do minimal update, Fl_Group must draw
+	everything outside of the object's bounding box.  So draw_label()
+	changed to only draw FL_INSIDE or FL_CENTER alignements.  New
+	method draw_outside_label() added to be called by Fl_Group
+	to draw the other labels.  This simplified Fl_Slider and
+	Fl_LightButton some, too.
diff --git a/fluid/Fl_Function_Type.cxx b/fluid/Fl_Function_Type.cxx
new file mode 100644
index 000000000..21bdb5b37
--- /dev/null
+++ b/fluid/Fl_Function_Type.cxx
@@ -0,0 +1,669 @@
+/*	Fl_Function_Type_Type.C
+
+	Type describing a C function output by Fluid.
+
+*/
+
+#include 
+#include "Fl_Type.H"
+#include 
+#include 
+#include 
+#include 
+
+////////////////////////////////////////////////////////////////
+// quick check of any C code for legality, returns an error message
+// these currently require comments to parse correctly!
+
+static char buffer[128]; // for error messages
+
+// check a quoted string ending in either " or ' or >:
+const char *_q_check(const char * & c, int type) {
+  for (;;) switch (*c++) {
+  case '\0':
+    sprintf(buffer,"missing %c",type);
+    return buffer;
+  case '\\':
+    if (*c) c++;
+    break;
+  default:
+    if (*(c-1) == type) return 0;
+  }
+}
+
+// check normal code, match braces and parenthesis:
+const char *_c_check(const char * & c, int type) {
+  const char *d;
+  for (;;) switch (*c++) {
+  case 0:
+    if (!type) return 0;
+    sprintf(buffer, "missing %c", type);
+    return buffer;
+  case '{':
+    if (type==')') goto UNEXPECTED;
+    d = _c_check(c,'}'); if (d) return d; break;
+  case '(':
+    d = _c_check(c,')'); if (d) return d; break;
+  case '\"':
+    d = _q_check(c,'\"'); if (d) return d; break;
+  case '\'':
+    d = _q_check(c,'\''); if (d) return d; break;
+  case '}':
+  case ')':
+  case '#':
+  UNEXPECTED:
+    if (type == *(c-1)) return 0;
+    sprintf(buffer, "unexpected %c", *(c-1));
+    return buffer;
+  }
+}
+
+const char *c_check(const char *c, int type) {
+  return _c_check(c,type);
+}
+
+////////////////////////////////////////////////////////////////
+
+class Fl_Function_Type : public Fl_Type {
+  const char* return_type;
+  char public_, constructor, havewidgets;
+public:
+  Fl_Type *make();
+  void write_declare();
+  void write_code1();
+  void write_code2();
+  void open();
+  int ismain() {return name_ == 0;}
+  virtual const char *type_name() {return "Function";}
+  virtual const char *title() {
+    return name() ? name() : "main()";
+  }
+  int is_parent() const {return 1;}
+  int is_code_block() const {return 1;}
+  void write_properties();
+  void read_property(const char *);
+};
+
+Fl_Type *Fl_Function_Type::make() {
+  Fl_Type *p = Fl_Type::current;
+  while (p && !p->is_decl_block()) p = p->parent;
+  Fl_Function_Type *o = new Fl_Function_Type();
+  o->name("make_window()");
+  o->return_type = 0;
+  o->add(p);
+  o->factory = this;
+  o->public_ = 1;
+  return o;
+}
+
+void Fl_Function_Type::write_properties() {
+  Fl_Type::write_properties();
+  if (!public_) write_string("private");
+  if (return_type) {
+    write_string("return_type");
+    write_word(return_type);
+  }
+}
+
+void Fl_Function_Type::read_property(const char *c) {
+  if (!strcmp(c,"private")) {
+    public_ = 0;
+  } else if (!strcmp(c,"return_type")) {
+    storestring(read_word(),return_type);
+  } else {
+    Fl_Type::read_property(c);
+  }
+}
+
+#include "function_panel.H"
+#include 
+
+void Fl_Function_Type::open() {
+  if (!function_panel) make_function_panel();
+  f_return_type_input->static_value(return_type);
+  f_name_input->static_value(name());
+  f_public_button->value(public_);
+  function_panel->show();
+  const char* message = 0;
+  for (;;) { // repeat as long as there are errors
+    if (message) fl_alert(message);
+    for (;;) {
+      Fl_Widget* w = Fl::readqueue();
+      if (w == f_panel_cancel) goto BREAK2;
+      else if (w == f_panel_ok) break;
+      else if (!w) Fl::wait();
+    }
+    const char*c = f_name_input->value();
+    while (isspace(*c)) c++;
+    message = c_check(c); if (message) continue;
+    const char *d = c;
+    for (; *d != '('; d++) if (isspace(*d) || !*d) break;
+    if (*c && *d != '(') {
+      message = "must be name(arguments), try again:"; continue;
+    }
+    c = f_return_type_input->value();
+    message = c_check(c); if (message) continue;
+    name(f_name_input->value());
+    storestring(c, return_type);
+    public_ = f_public_button->value();
+    break;
+  }
+ BREAK2:
+  function_panel->hide();
+}
+
+Fl_Function_Type Fl_Function_type;
+
+void Fl_Function_Type::write_declare() {
+  ::write_declare("#include ");
+}
+
+extern const char* subclassname(Fl_Type*);
+
+void Fl_Function_Type::write_code1() {
+  constructor=0;
+  havewidgets = 0;
+  Fl_Type *child;
+  const char* widget_type = 0;
+  for (child = next; child && child->level > level; child = child->next)
+    if (child->is_widget()) {
+      havewidgets = 1;
+      widget_type = subclassname(child);
+      break;
+    }
+  write_c("\n");
+  if (ismain())
+    write_c("int main(int argc, char **argv) {\n");
+  else {
+    const char* t = return_type;
+    const char* star = "";
+    if (!t) {
+      if (havewidgets) {t = widget_type; star = "*";}
+      else t = "void";
+    }
+    const char* k = class_name();
+    if (k) {
+      write_public(public_);
+      if (name()[0] == '~')
+	constructor = 1;
+      else {
+	size_t n; for (n=0; name()[n] && name()[n]!='('; n++);
+	if (n == strlen(k) && !strncmp(name(), k, n)) constructor = 1;
+      }
+      write_h("  ");
+      if (!constructor) {write_h("%s%s ", t, star); write_c("%s%s ", t,star);}
+      write_h("%s;\n", name());
+      write_c("%s::%s {\n", k, name());
+    } else {
+      if (public_) write_h("%s%s %s;\n", t, star, name());
+      else write_c("static ");
+      write_c("%s%s %s {\n", t, star, name());
+    }
+  }
+  if (havewidgets) write_c("  %s* w;\n", widget_type);
+  indentation += 2;
+}
+
+void Fl_Function_Type::write_code2() {
+  if (ismain()) {
+    if (havewidgets) write_c("  w->show(argc, argv);\n");
+    write_c("  return Fl::run();\n");
+  } else if (havewidgets && !constructor)
+    write_c("  return w;\n");
+  write_c("}\n");
+  indentation = 0;
+}
+
+////////////////////////////////////////////////////////////////
+
+class Fl_Code_Type : public Fl_Type {
+public:
+  Fl_Type *make();
+  void write_declare();
+  void write_code1();
+  void write_code2();
+  void open();
+  virtual const char *type_name() {return "code";}
+  int is_code_block() const {return 0;}
+};
+
+Fl_Type *Fl_Code_Type::make() {
+  Fl_Type *p = Fl_Type::current;
+  while (p && !p->is_code_block()) p = p->parent;
+  if (!p) {
+    fl_message("Please select a function");
+    return 0;
+  }
+  Fl_Code_Type *o = new Fl_Code_Type();
+  o->name("printf(\"Hello, World!\\n\");");
+  o->add(p);
+  o->factory = this;
+  return o;
+}
+
+void Fl_Code_Type::open() {
+  if (!code_panel) make_code_panel();
+  code_input->static_value(name());
+  code_panel->show();
+  const char* message = 0;
+  for (;;) { // repeat as long as there are errors
+    if (message) fl_alert(message);
+    for (;;) {
+      Fl_Widget* w = Fl::readqueue();
+      if (w == code_panel_cancel) goto BREAK2;
+      else if (w == code_panel_ok) break;
+      else if (!w) Fl::wait();
+    }
+    const char*c = code_input->value();
+    message = c_check(c); if (message) continue;
+    name(c);
+    break;
+  }
+ BREAK2:
+  code_panel->hide();
+}
+
+Fl_Code_Type Fl_Code_type;
+
+void Fl_Code_Type::write_declare() {}
+
+void Fl_Code_Type::write_code1() {
+  const char* c = name();
+  if (!c) return;
+  write_c("%s%s\n", indent(), c);
+}
+
+void Fl_Code_Type::write_code2() {}
+
+////////////////////////////////////////////////////////////////
+
+class Fl_CodeBlock_Type : public Fl_Type {
+  const char* after;
+public:
+  Fl_Type *make();
+  void write_declare();
+  void write_code1();
+  void write_code2();
+  void open();
+  virtual const char *type_name() {return "codeblock";}
+  int is_code_block() const {return 1;}
+  int is_parent() const {return 1;}
+  void write_properties();
+  void read_property(const char *);
+};
+
+Fl_Type *Fl_CodeBlock_Type::make() {
+  Fl_Type *p = Fl_Type::current;
+  while (p && !p->is_code_block()) p = p->parent;
+  if (!p) {
+    fl_message("Please select a function");
+    return 0;
+  }
+  Fl_CodeBlock_Type *o = new Fl_CodeBlock_Type();
+  o->name("if (test())");
+  o->after = 0;
+  o->add(p);
+  o->factory = this;
+  return o;
+}
+
+void Fl_CodeBlock_Type::write_properties() {
+  Fl_Type::write_properties();
+  if (after) {
+    write_string("after");
+    write_word(after);
+  }
+}
+
+void Fl_CodeBlock_Type::read_property(const char *c) {
+  if (!strcmp(c,"after")) {
+    storestring(read_word(),after);
+  } else {
+    Fl_Type::read_property(c);
+  }
+}
+
+void Fl_CodeBlock_Type::open() {
+  if (!codeblock_panel) make_codeblock_panel();
+  code_before_input->static_value(name());
+  code_after_input->static_value(after);
+  codeblock_panel->show();
+  const char* message = 0;
+  for (;;) { // repeat as long as there are errors
+    if (message) fl_alert(message);
+    for (;;) {
+      Fl_Widget* w = Fl::readqueue();
+      if (w == codeblock_panel_cancel) goto BREAK2;
+      else if (w == codeblock_panel_ok) break;
+      else if (!w) Fl::wait();
+    }
+    const char*c = code_before_input->value();
+    message = c_check(c); if (message) continue;
+    name(c);
+    c = code_after_input->value();
+    message = c_check(c); if (message) continue;
+    storestring(c, after);
+    break;
+  }
+ BREAK2:
+  codeblock_panel->hide();
+}
+
+Fl_CodeBlock_Type Fl_CodeBlock_type;
+
+void Fl_CodeBlock_Type::write_declare() {}
+
+void Fl_CodeBlock_Type::write_code1() {
+  const char* c = name();
+  write_c("%s%s {\n", indent(), c ? c : "");
+  indentation += 2;
+}
+
+void Fl_CodeBlock_Type::write_code2() {
+  indentation += 2;
+  if (after) write_c("%s} %s\n", indent(), after);
+  else write_c("%s}\n", indent());
+}
+
+////////////////////////////////////////////////////////////////
+
+class Fl_Decl_Type : public Fl_Type {
+  char public_;
+public:
+  Fl_Type *make();
+  void write_declare();
+  void write_code1();
+  void write_code2();
+  void open();
+  virtual const char *type_name() {return "decl";}
+  void write_properties();
+  void read_property(const char *);
+};
+
+Fl_Type *Fl_Decl_Type::make() {
+  Fl_Type *p = Fl_Type::current;
+  while (p && !p->is_decl_block()) p = p->parent;
+  Fl_Decl_Type *o = new Fl_Decl_Type();
+  o->public_ = 0;
+  o->name("int x;");
+  o->add(p);
+  o->factory = this;
+  return o;
+}
+
+void Fl_Decl_Type::write_properties() {
+  Fl_Type::write_properties();
+  if (public_) write_string("public");
+}
+
+void Fl_Decl_Type::read_property(const char *c) {
+  if (!strcmp(c,"public")) {
+    public_ = 1;
+  } else {
+    Fl_Type::read_property(c);
+  }
+}
+
+void Fl_Decl_Type::open() {
+  if (!decl_panel) make_decl_panel();
+  decl_input->static_value(name());
+  decl_public_button->value(public_);
+  decl_panel->show();
+  const char* message = 0;
+  for (;;) { // repeat as long as there are errors
+    if (message) fl_alert(message);
+    for (;;) {
+      Fl_Widget* w = Fl::readqueue();
+      if (w == decl_panel_cancel) goto BREAK2;
+      else if (w == decl_panel_ok) break;
+      else if (!w) Fl::wait();
+    }
+    const char*c = decl_input->value();
+    while (isspace(*c)) c++;
+    message = c_check(c&&c[0]=='#' ? c+1 : c);
+    if (message) continue;
+    name(c);
+    public_ = decl_public_button->value();
+    break;
+  }
+ BREAK2:
+  decl_panel->hide();
+}
+
+Fl_Decl_Type Fl_Decl_type;
+
+void Fl_Decl_Type::write_declare() {}
+
+void Fl_Decl_Type::write_code1() {
+  const char* c = name();
+  if (!c) return;
+  // handle putting #include or extern into decl:
+  if (!isalpha(*c) || !strncmp(c,"extern",6)) {
+    if (public_)
+      write_h("%s\n", c);
+    else
+      write_c("%s\n", c);
+    return;
+  }
+  // lose all trailing semicolons so I can add one:
+  const char* e = c+strlen(c);
+  while (e>c && e[-1]==';') e--;
+  if (class_name()) {
+    write_public(public_);
+    write_h("  %.*s;\n", e-c, c);
+  } else {
+    if (public_) {
+      write_h("extern %.*s;\n", e-c, c);
+      write_c("%.*s;\n", e-c, c);
+    } else {
+      write_c("static %.*s;\n", e-c, c);
+    }
+  }
+}
+
+void Fl_Decl_Type::write_code2() {}
+
+////////////////////////////////////////////////////////////////
+
+class Fl_DeclBlock_Type : public Fl_Type {
+  const char* after;
+public:
+  Fl_Type *make();
+  void write_declare();
+  void write_code1();
+  void write_code2();
+  void open();
+  virtual const char *type_name() {return "declblock";}
+  void write_properties();
+  void read_property(const char *);
+  int is_parent() const {return 1;}
+  int is_decl_block() const {return 1;}
+};
+
+Fl_Type *Fl_DeclBlock_Type::make() {
+  Fl_Type *p = Fl_Type::current;
+  while (p && !p->is_decl_block()) p = p->parent;
+  Fl_DeclBlock_Type *o = new Fl_DeclBlock_Type();
+  o->name("#if 1");
+  o->after = strdup("#endif");
+  o->add(p);
+  o->factory = this;
+  return o;
+}
+
+void Fl_DeclBlock_Type::write_properties() {
+  Fl_Type::write_properties();
+  write_string("after");
+  write_word(after);
+}
+
+void Fl_DeclBlock_Type::read_property(const char *c) {
+  if (!strcmp(c,"after")) {
+    storestring(read_word(),after);
+  } else {
+    Fl_Type::read_property(c);
+  }
+}
+
+void Fl_DeclBlock_Type::open() {
+  if (!declblock_panel) make_declblock_panel();
+  decl_before_input->static_value(name());
+  decl_after_input->static_value(after);
+  declblock_panel->show();
+  const char* message = 0;
+  for (;;) { // repeat as long as there are errors
+    if (message) fl_alert(message);
+    for (;;) {
+      Fl_Widget* w = Fl::readqueue();
+      if (w == declblock_panel_cancel) goto BREAK2;
+      else if (w == declblock_panel_ok) break;
+      else if (!w) Fl::wait();
+    }
+    const char*c = decl_before_input->value();
+    while (isspace(*c)) c++;
+    message = c_check(c&&c[0]=='#' ? c+1 : c);
+    if (message) continue;
+    name(c);
+    c = decl_after_input->value();
+    while (isspace(*c)) c++;
+    message = c_check(c&&c[0]=='#' ? c+1 : c);
+    if (message) continue;
+    storestring(c,after);
+    break;
+  }
+ BREAK2:
+  declblock_panel->hide();
+}
+
+Fl_DeclBlock_Type Fl_DeclBlock_type;
+
+void Fl_DeclBlock_Type::write_declare() {}
+
+void Fl_DeclBlock_Type::write_code1() {
+  const char* c = name();
+  if (c) write_c("%s\n", c);
+}
+
+void Fl_DeclBlock_Type::write_code2() {
+  const char* c = after;
+  if (c) write_c("%s\n", c);
+}
+
+////////////////////////////////////////////////////////////////
+
+class Fl_Class_Type : public Fl_Type {
+  const char* subclass_of;
+  char public_;
+public:
+  // state variables for output:
+  char write_public_state; // true when public: has been printed
+  Fl_Class_Type* parent_class; // save class if nested
+//
+  Fl_Type *make();
+  void write_declare();
+  void write_code1();
+  void write_code2();
+  void open();
+  virtual const char *type_name() {return "class";}
+  int is_parent() const {return 1;}
+  int is_decl_block() const {return 1;}
+  int is_class() const {return 1;}
+  void write_properties();
+  void read_property(const char *);
+};
+
+const char* Fl_Type::class_name() const {
+  Fl_Type* p = parent;
+  while (p) {if (p->is_class()) return p->name(); p = p->parent;}
+  return 0;
+}
+
+Fl_Type *Fl_Class_Type::make() {
+  Fl_Type *p = Fl_Type::current;
+  while (p && !p->is_decl_block()) p = p->parent;
+  Fl_Class_Type *o = new Fl_Class_Type();
+  o->name("UserInterface");
+  o->subclass_of = 0;
+  o->public_ = 1;
+  o->add(p);
+  o->factory = this;
+  return o;
+}
+
+void Fl_Class_Type::write_properties() {
+  Fl_Type::write_properties();
+  if (subclass_of) {
+    write_string(":");
+    write_word(subclass_of);
+  }
+  if (!public_) write_string("private");
+}
+
+void Fl_Class_Type::read_property(const char *c) {
+  if (!strcmp(c,"private")) {
+    public_ = 0;
+  } else if (!strcmp(c,":")) {
+    storestring(read_word(), subclass_of);
+  } else {
+    Fl_Type::read_property(c);
+  }
+}
+
+void Fl_Class_Type::open() {
+  if (!class_panel) make_class_panel();
+  c_name_input->static_value(name());
+  c_subclass_input->static_value(subclass_of);
+  c_public_button->value(public_);
+  class_panel->show();
+  const char* message = 0;
+  for (;;) { // repeat as long as there are errors
+    if (message) fl_alert(message);
+    for (;;) {
+      Fl_Widget* w = Fl::readqueue();
+      if (w == c_panel_cancel) goto BREAK2;
+      else if (w == c_panel_ok) break;
+      else if (!w) Fl::wait();
+    }
+    const char*c = c_name_input->value();
+    while (isspace(*c)) c++;
+    if (!*c) goto OOPS;
+    while (is_id(*c)) c++;
+    while (isspace(*c)) c++;
+    if (*c) {OOPS: message = "class name must be C++ identifier"; continue;}
+    c = c_subclass_input->value();
+    message = c_check(c); if (message) continue;
+    name(c_name_input->value());
+    storestring(c, subclass_of);
+    public_ = c_public_button->value();
+    break;
+  }
+ BREAK2:
+  class_panel->hide();
+}
+
+Fl_Class_Type Fl_Class_type;
+
+void Fl_Class_Type::write_declare() {}
+
+static Fl_Class_Type *current_class;
+extern int varused_test;
+void write_public(int state) {
+  if (!current_class || varused_test) return;
+  if (current_class->write_public_state == state) return;
+  current_class->write_public_state = state;
+  write_h(state ? "public:\n" : "private:\n");
+}
+
+void Fl_Class_Type::write_code1() {
+  parent_class = current_class;
+  current_class = this;
+  write_public_state = 0;
+  write_h("\nclass %s ", name());
+  if (subclass_of) write_h(": %s ", subclass_of);
+  write_h("{\n");
+}
+
+void Fl_Class_Type::write_code2() {
+  write_h("};\n");
+  current_class = parent_class;
+}
diff --git a/fluid/Fl_Group_Type.cxx b/fluid/Fl_Group_Type.cxx
new file mode 100644
index 000000000..0e499339d
--- /dev/null
+++ b/fluid/Fl_Group_Type.cxx
@@ -0,0 +1,245 @@
+// Fl_Group_Type.C
+
+// Object describing an Fl_Group
+// Probably also links to Fl_Window_Type.C
+
+// Also the Fl_Tabs widget, with special stuff to select tab items
+// and insure that only one is visible.
+
+#include 
+#include 
+#include 
+#include "Fl_Widget_Type.H"
+
+class igroup : public Fl_Group {
+public:
+  void resize(int,int,int,int);
+  igroup(int x,int y,int w,int h) : Fl_Group(x,y,w,h) {Fl_Group::current(0);}
+};
+// Override group's resize behavior to do nothing to children:
+void igroup::resize(int X, int Y, int W, int H) {
+  Fl_Widget::resize(X,Y,W,H);
+  redraw();
+}
+
+class Fl_Group_Type : public Fl_Widget_Type {
+public:
+  virtual const char *type_name() {return "Fl_Group";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    igroup *g = new igroup(x,y,w,h); Fl_Group::current(0); return g;}
+  Fl_Widget_Type *_make() {return new Fl_Group_Type();}
+  Fl_Type *make();
+  void write_code1();
+  void write_code2();
+  void add_child(Fl_Type*, Fl_Type*);
+  void move_child(Fl_Type*, Fl_Type*);
+  void remove_child(Fl_Type*);
+  int is_parent() const {return 1;}
+  int is_group() const {return 1;}
+};
+Fl_Group_Type Fl_Group_type;	// the "factory"
+
+Fl_Type *Fl_Group_Type::make() {
+  return Fl_Widget_Type::make();
+}
+
+void fix_group_size(Fl_Type *tt) {
+  if (!tt || !tt->is_group()) return;
+  Fl_Group_Type* t = (Fl_Group_Type*)tt;
+  int X = t->o->x();
+  int Y = t->o->y();
+  int R = X+t->o->w();
+  int B = Y+t->o->h();
+  for (Fl_Type *nn = t->next; nn && nn->level > t->level; nn = nn->next) {
+    if (!nn->is_widget() || nn->is_menu_item()) continue;
+    Fl_Widget_Type* n = (Fl_Widget_Type*)nn;
+    int x = n->o->x();	if (x < X) X = x;
+    int y = n->o->y();	if (y < Y) Y = y;
+    int r = x+n->o->w();if (r > R) R = r;
+    int b = y+n->o->h();if (b > B) B = b;
+  }
+  t->o->resize(X,Y,R-X,B-Y);
+}
+
+extern int force_parent;
+
+void group_cb(Fl_Widget *, void *) {
+  // Find the current widget:
+  Fl_Type *qq = Fl_Type::current;
+  while (qq && (!qq->is_widget() || qq->is_menu_item())) qq = qq->parent;
+  if (!qq || qq->level <= 1) {
+    fl_message("Please select widgets to group");
+    return;
+  }
+  Fl_Widget_Type* q = (Fl_Widget_Type*)qq;
+  force_parent = 1;
+  Fl_Group_Type *n = (Fl_Group_Type*)(Fl_Group_type.make());
+  n->move_before(q);
+  n->o->resize(q->o->x(),q->o->y(),q->o->w(),q->o->h());
+  for (Fl_Type *t = Fl_Type::first; t;) {
+    if (t->level != n->level || t == n || !t->selected) {
+      t = t->next; continue;}
+    Fl_Type *nxt = t->remove();
+    t->add(n);
+    t = nxt;
+  }
+  fix_group_size(n);
+}
+
+void ungroup_cb(Fl_Widget *, void *) {
+  // Find the group:
+  Fl_Type *q = Fl_Type::current;
+  while (q && (!q->is_widget() || q->is_menu_item())) q = q->parent;
+  if (q) q = q->parent;
+  if (!q || q->level <= 1) {
+    fl_message("Please select widgets in a group");
+    return;
+  }
+  Fl_Type* n;
+  for (n = q->next; n && n->level > q->level; n = n->next) {
+    if (n->level == q->level+1 && !n->selected) {
+      fl_message("Please select all widgets in group");
+      return;
+    }
+  }
+  for (n = q->next; n && n->level > q->level;) {
+    Fl_Type *nxt = n->remove();
+    n->insert(q);
+    n = nxt;
+  }
+  delete q;
+}
+
+////////////////////////////////////////////////////////////////
+
+#include 
+
+void Fl_Group_Type::write_code1() {
+  Fl_Widget_Type::write_code1();
+}
+
+void Fl_Group_Type::write_code2() {
+  write_c("%so->end();\n", indent());
+  if (resizable()) write_c("%sFl_Group::current()->resizable(o);\n", indent());
+  Fl_Widget_Type::write_code2();
+}
+
+////////////////////////////////////////////////////////////////
+
+#include 
+
+class itabs : public Fl_Tabs {
+public:
+  void resize(int,int,int,int);
+  itabs(int x,int y,int w,int h) : Fl_Tabs(x,y,w,h) {}
+};
+// Override group's resize behavior to do nothing to children:
+void itabs::resize(int X, int Y, int W, int H) {
+  Fl_Widget::resize(X,Y,W,H);
+  redraw();
+}
+
+static const char tabs_type_name[] = "Fl_Tabs";
+
+class Fl_Tabs_Type : public Fl_Group_Type {
+public:
+  virtual const char *type_name() {return tabs_type_name;}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    itabs *g = new itabs(x,y,w,h); Fl_Group::current(0); return g;}
+  Fl_Widget_Type *_make() {return new Fl_Tabs_Type();}
+  Fl_Type* click_test(int,int);
+  void add_child(Fl_Type*, Fl_Type*);
+  void remove_child(Fl_Type*);
+};
+Fl_Tabs_Type Fl_Tabs_type;	// the "factory"
+
+// This is called when user clicks on a widget in the window.  See
+// if it is a tab title, and adjust visibility and return new selection:
+// If none, return o unchanged:
+
+Fl_Type* Fl_Tabs_Type::click_test(int x, int y) {
+  Fl_Tabs *t = (Fl_Tabs*)o;
+  Fl_Widget *a = t->which(x,y);
+  if (!a) return 0; // didn't click on tab
+  // okay, run the tabs ui until they let go of mouse:
+  t->handle(FL_PUSH);
+  Fl::pushed(t);
+  while (Fl::pushed()==t) Fl::wait();
+  return (Fl_Type*)(t->value()->user_data());
+}
+
+// This is called when o is created.  If it is in the tab group make
+// sure it is visible:
+
+void Fl_Group_Type::add_child(Fl_Type* cc, Fl_Type* before) {
+  Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
+  Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
+  ((Fl_Group*)o)->insert(*(c->o), b);
+  o->redraw();
+}
+
+void Fl_Tabs_Type::add_child(Fl_Type* c, Fl_Type* before) {
+  Fl_Group_Type::add_child(c, before);
+  ((Fl_Tabs*)o)->value(0);
+}
+
+// This is called when o is deleted.  If it is in the tab group make
+// sure it is not visible:
+
+void Fl_Group_Type::remove_child(Fl_Type* cc) {
+  Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
+  ((Fl_Group*)o)->remove(c->o);
+  o->redraw();
+}
+
+void Fl_Tabs_Type::remove_child(Fl_Type* cc) {
+  Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
+  Fl_Tabs *t = (Fl_Tabs*)o;
+  if (t->value() == c->o) t->value(0);
+  Fl_Group_Type::remove_child(c);
+}
+
+// move, don't change selected value:
+
+void Fl_Group_Type::move_child(Fl_Type* cc, Fl_Type* before) {
+  Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
+  Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
+  ((Fl_Group*)o)->remove(c->o);
+  ((Fl_Group*)o)->insert(*(c->o), b);
+  o->redraw();
+}
+
+////////////////////////////////////////////////////////////////
+// some other group subclasses that fluid does not treat specially:
+
+#include 
+
+static const char scroll_type_name[] = "Fl_Scroll";
+
+static Fl_Menu_Item scroll_type_menu[] = {
+  {"BOTH", 0, 0, 0/*(void*)Fl_Scroll::BOTH*/},
+  {"HORIZONTAL", 0, 0, (void*)Fl_Scroll::HORIZONTAL},
+  {"VERTICAL", 0, 0, (void*)Fl_Scroll::VERTICAL},
+  {"HORIZONTAL_ALWAYS", 0, 0, (void*)Fl_Scroll::HORIZONTAL_ALWAYS},
+  {"VERTICAL_ALWAYS", 0, 0, (void*)Fl_Scroll::VERTICAL_ALWAYS},
+  {"BOTH_ALWAYS", 0, 0, (void*)Fl_Scroll::BOTH_ALWAYS},
+  {0}};
+
+class Fl_Scroll_Type : public Fl_Group_Type {
+  Fl_Menu_Item *subtypes() {return scroll_type_menu;}
+public:
+  virtual const char *type_name() {return scroll_type_name;}
+  Fl_Widget_Type *_make() {return new Fl_Scroll_Type();}
+};
+Fl_Scroll_Type Fl_Scroll_type;	// the "factory"
+
+////////////////////////////////////////////////////////////////
+
+static const char tile_type_name[] = "Fl_Tile";
+
+class Fl_Tile_Type : public Fl_Group_Type {
+public:
+  virtual const char *type_name() {return tile_type_name;}
+  Fl_Widget_Type *_make() {return new Fl_Tile_Type();}
+};
+Fl_Tile_Type Fl_Tile_type;	// the "factory"
diff --git a/fluid/Fl_Menu_Type.cxx b/fluid/Fl_Menu_Type.cxx
new file mode 100644
index 000000000..02318602c
--- /dev/null
+++ b/fluid/Fl_Menu_Type.cxx
@@ -0,0 +1,487 @@
+// Fl_Menu_Type.C
+
+// Menu items are kludged by making a phony Fl_Box widget so the normal
+// widget panel can be used to control them.
+
+// This file also contains code to make Fl_Menu_Button, Fl_Menu_Bar,
+// etc widgets.
+
+#include 
+#include "Fl_Widget_Type.H"
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static Fl_Menu_Item menu_item_type_menu[] = {
+  {"Normal",0,0,(void*)0},
+  {"Toggle",0,0,(void*)FL_MENU_BOX},
+  {"Radio",0,0,(void*)FL_MENU_RADIO},
+  {0}};
+
+class Fl_Menu_Item_Type : public Fl_Widget_Type {
+public:
+  Fl_Menu_Item* subtypes() {return menu_item_type_menu;}
+  const char* type_name() {return "menuitem";}
+  Fl_Type* make();
+  int is_menu_item() const {return 1;}
+  int is_button() const {return 1;} // this gets shortcut to work
+  Fl_Widget* widget(int,int,int,int) {return 0;}
+  Fl_Widget_Type* _make() {return 0;}
+  void write_declare();
+  const char* menu_name(int& i);
+  int flags();
+  void write_static();
+  void write_item();
+  void write_code1();
+  void write_code2();
+};
+
+class Fl_Submenu_Type : public Fl_Menu_Item_Type {
+public:
+  Fl_Menu_Item* subtypes() {return 0;}
+  const char* type_name() {return "submenu";}
+  int is_parent() const {return 1;}
+  int is_button() const {return 0;} // disable shortcut
+  Fl_Type* make();
+  // changes to submenu must propagate up so build_menu is called
+  // on the parent Fl_Menu_Type:
+  void add_child(Fl_Type*a, Fl_Type*b) {parent->add_child(a,b);}
+  void move_child(Fl_Type*a, Fl_Type*b) {parent->move_child(a,b);}
+  void remove_child(Fl_Type*a) {parent->remove_child(a);}
+};
+
+extern int reading_file;
+extern int force_parent;
+
+static char submenuflag;
+
+Fl_Type *Fl_Menu_Item_Type::make() {
+  // Find the current menu item:
+  Fl_Type* q = Fl_Type::current;
+  Fl_Type* p = q;
+  if (p) {
+    if (force_parent && q->is_menu_item() || !q->is_parent()) p = p->parent;
+  }
+  force_parent = 0;
+  if (!p || !(p->is_menu_button() || p->is_menu_item() && p->is_parent())) {
+    fl_message("Please select a menu to add to");
+    return 0;
+  }
+  if (!o) {
+    o = new Fl_Button(0,0,100,20); // create template widget
+  }
+
+  Fl_Menu_Item_Type* t = submenuflag ? new Fl_Submenu_Type() : new Fl_Menu_Item_Type();
+  t->o = new Fl_Button(0,0,100,20);
+  t->factory = this;
+  t->add(p);
+  if (!reading_file) t->label(submenuflag ? "submenu" : "item");
+  return t;
+}
+
+Fl_Type *Fl_Submenu_Type::make() {
+  submenuflag = 1;
+  Fl_Type* t = Fl_Menu_Item_Type::make();
+  submenuflag = 0;
+  return t;
+}
+
+Fl_Menu_Item_Type Fl_Menu_Item_type;
+Fl_Submenu_Type Fl_Submenu_type;
+
+////////////////////////////////////////////////////////////////
+// Writing the C code:
+
+#include 
+
+// test functions in Fl_Widget_Type.C:
+int is_name(const char *c);
+const char *array_name(Fl_Widget_Type *o);
+int isdeclare(const char *c);
+
+void Fl_Menu_Item_Type::write_declare() {
+  if (callback() && is_name(callback()))
+    ::write_declare("extern void %s(Fl_Menu_*, %s);", callback(),
+		    user_data_type() ? user_data_type() : "void*");
+  for (int n=0; n < NUM_EXTRA_CODE; n++) {
+    if (extra_code(n) && isdeclare(extra_code(n)))
+      ::write_declare("%s", extra_code(n));
+  }
+}
+
+const char* Fl_Menu_Item_Type::menu_name(int& i) {
+  i = 0;
+  Fl_Type* t = prev;
+  while (t && t->is_menu_item()) {
+    // be sure to count the {0} that ends a submenu:
+    if (t->level > t->next->level ||
+	// detect empty submenu:
+	t->level==t->next->level &&t->is_parent())
+      i++;
+    t = t->prev; i++;
+  }
+  return unique_id(t, "menu", t->name(), t->label());
+}
+
+#include "Fluid_Image.H"
+
+void Fl_Menu_Item_Type::write_static() {
+  if (callback() && !is_name(callback())) {
+    // see if 'o' or 'v' used, to prevent unused argument warnings:
+    int use_o = 0;
+    int use_v = 0;
+    const char *d;
+    for (d = callback(); *d;) {
+      if (*d == 'o' && !is_id(d[1])) use_o = 1;
+      if (*d == 'v' && !is_id(d[1])) use_v = 1;
+      do d++; while (is_id(*d));
+      while (*d && !is_id(*d)) d++;
+    }
+    const char* cn = callback_name();
+    const char* k = class_name();
+    if (k) {
+      write_c("\ninline void %s::%s_i(Fl_Menu_*", k, cn);
+    } else {
+      write_c("\nstatic void %s(Fl_Menu_*", cn);
+    }
+    if (use_o) write_c(" o");
+    const char* ut = user_data_type() ? user_data_type() : "void*";
+    write_c(", %s", ut);
+    if (use_v) write_c(" v");
+    write_c(") {\n  %s", callback());
+    if (*(d-1) != ';') write_c(";");
+    write_c("\n}\n");
+    if (k) {
+      write_c("void %s::%s(Fl_Menu_* o, %s v) {\n", k, cn, ut);
+      write_c("  ((%s*)(o->", k);
+      Fl_Type* t = parent; while (t->is_menu_item()) t = t->parent;
+      for (t = t->parent; t->is_widget(); t = t->parent) write_c("parent()->");
+      write_c("user_data()))->%s_i(o,v);\n}\n", cn);
+    }
+  }
+  if (image) {
+    if (image->written != write_number) {
+      image->write_static();
+      image->written = write_number;
+    }
+  }
+  if (next && next->is_menu_item()) return;
+  // okay, when we hit last item in the menu we have to write the
+  // entire array out:
+  int level;
+  const char* k = class_name();
+  if (k) {
+    write_c("\nFl_Menu_Item %s::%s[] = {\n", k, menu_name(level));
+  } else
+    write_c("\nFl_Menu_Item %s[] = {\n", menu_name(level));
+  Fl_Type* t = prev; while (t && t->is_menu_item()) t = t->prev;
+  level = t->level+1;
+  for (Fl_Type* q = t->next; q && q->is_menu_item(); q = q->next) {
+    ((Fl_Menu_Item_Type*)q)->write_item();
+    if (q->is_parent()) level++;
+    int l1 =
+      (q->next && q->next->is_menu_item()) ? q->next->level : t->next->level;
+    while (level > l1) {write_c(" {0},\n"); level--;}
+    level = l1;
+  }
+  write_c(" {0}\n};\n");
+}
+
+int Fl_Menu_Item_Type::flags() {
+  int i = o->type();
+  if (((Fl_Button*)o)->value()) i |= FL_MENU_VALUE;
+  if (!o->active()) i |= FL_MENU_INACTIVE;
+  if (!o->visible()) i |= FL_MENU_INVISIBLE;
+  if (is_parent()) i |= FL_SUBMENU;
+  if (hotspot()) i |= FL_MENU_DIVIDER;
+  return i;
+}
+
+void Fl_Menu_Item_Type::write_item() {
+  write_c(" {");
+  if (image) write_c("0");
+  else if (label()) write_cstring(label());
+  else write_c("\"\"");
+  if (((Fl_Button*)o)->shortcut())
+    write_c(", 0x%x, ", ((Fl_Button*)o)->shortcut());
+  else
+    write_c(", 0, ");
+  if (callback()) {
+    const char* k = class_name();
+    if (k) {
+      write_c(" (Fl_Callback*)%s::%s,", k, callback_name());
+    } else {
+      write_c(" (Fl_Callback*)%s,", callback_name());
+    }
+  } else
+    write_c(" 0,");
+  if (user_data())
+    write_c(" (void*)(%s),", user_data());
+  else
+    write_c(" 0,");
+  write_c(" %d, %d, %d, %d, %d", flags(),
+	  o->labeltype(), o->labelfont(), o->labelsize(), o->labelcolor());
+  write_c("},\n");
+}
+
+void Fl_Menu_Item_Type::write_code1() {
+  if (!prev->is_menu_item()) {
+    // for first menu item, declare the array
+    int i; const char* n = menu_name(i);
+    if (class_name())
+      write_h("  static Fl_Menu_Item %s[];\n", n);
+    else
+      write_h("extern Fl_Menu_Item %s[];\n", n);
+  }
+
+  const char *c = array_name(this);
+  if (c) {
+    int i; const char* n = menu_name(i);
+    write_h("#define %s (%s+%d)\n", c, n, i);
+  }
+
+  if (callback()) {
+    if (!is_name(callback()) && class_name()) {
+      const char* cn = callback_name();
+      const char* ut = user_data_type() ? user_data_type() : "void*";
+      write_public(0);
+      write_h("  inline void %s_i(Fl_Menu_*, %s);\n", cn, ut);
+      write_h("  static void %s(Fl_Menu_*, %s);\n", cn, ut);
+    }
+  }
+
+  int init = 0;
+  if (image) {
+    int i; const char* n = menu_name(i);
+    write_c(" {Fl_Menu_Item* o = &%s[%d];\n", n, i);
+    init = 1;
+    image->write_code();
+  }
+  for (int n=0; n < NUM_EXTRA_CODE; n++)
+    if (extra_code(n) && !isdeclare(extra_code(n))) {
+      if (!init) {
+	init = 1;
+	int i; const char* n = menu_name(i);
+	write_c("%s{ Fl_Menu_Item* o = &%s[%d];\n", indent(), n, i);
+      }
+      write_c("%s  %s\n", indent(), extra_code(n));
+    }
+  if (init) write_c("%s}\n",indent());
+}
+
+void Fl_Menu_Item_Type::write_code2() {}
+
+////////////////////////////////////////////////////////////////
+// This is the base class for widgets that contain a menu (ie
+// subclasses of Fl_Menu_.
+// This is a parent widget and menu items can be added as
+// children.  An actual array of Fl_Menu_Items is kept parallel
+// with the child objects and updated as they change.
+
+class Fl_Menu_Type : public Fl_Widget_Type {
+  int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+    Fl_Menu_ *o = (Fl_Menu_*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+    switch (w) {
+    case 4:
+    case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break;
+    case 1: o->textfont(f); break;
+    case 2: o->textsize(s); break;
+    case 3: o->textcolor(c); break;
+    }
+    return 1;
+  }
+public:
+  int is_menu_button() const {return 1;}
+  int is_parent() const {return 1;}
+  int menusize;
+  void build_menu();
+  Fl_Menu_Type() : Fl_Widget_Type() {menusize = 0;}
+  ~Fl_Menu_Type() {
+    if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Menu_*)o)->menu());
+  }
+  void add_child(Fl_Type*, Fl_Type*) {build_menu();}
+  void move_child(Fl_Type*, Fl_Type*) {build_menu();}
+  void remove_child(Fl_Type*) {build_menu();}
+  Fl_Type* click_test(int x, int y);
+  void write_code2();
+};
+
+void Fl_Menu_Type::build_menu() {
+  Fl_Menu_* w = (Fl_Menu_*)o;
+  // count how many Fl_Menu_Item structures needed:
+  int n = 0;
+  Fl_Type* q;
+  for (q = next; q && q->level > level; q = q->next) {
+    if (q->is_parent()) n++; // space for null at end of submenu
+    n++;
+  }
+  if (!n) {
+    if (menusize) delete[] (Fl_Menu_Item*)(w->menu());
+    w->menu(0);
+    menusize = 0;
+  } else {
+    n++; // space for null at end of menu
+    if (menusizemenu());
+      menusize = n+10;
+      w->menu(new Fl_Menu_Item[menusize]);
+    }
+    // fill them all in:
+    Fl_Menu_Item* m = (Fl_Menu_Item*)(w->menu());
+    int lvl = level+1;
+    for (q = next; q && q->level > level; q = q->next) {
+      Fl_Menu_Item_Type* i = (Fl_Menu_Item_Type*)q;
+      m->label(i->o->label());
+      m->shortcut(((Fl_Button*)(i->o))->shortcut());
+      m->callback(0,(void*)i);
+      m->flags = i->flags();
+      m->labeltype(i->o->labeltype());
+      m->labelfont(i->o->labelfont());
+      m->labelsize(i->o->labelsize());
+      m->labelcolor(i->o->labelcolor());
+      m++;
+      if (q->is_parent()) lvl++;
+      int l1 =
+	(q->next && q->next->is_menu_item()) ? q->next->level : level;
+      while (lvl > l1) {m->label(0); m++; lvl--;}
+      lvl = l1;
+    }
+  }
+  o->redraw();
+}
+
+Fl_Type* Fl_Menu_Type::click_test(int, int) {
+  if (selected) return 0; // let user move the widget
+  Fl_Menu_* w = (Fl_Menu_*)o;
+  if (!menusize) return 0;
+  const Fl_Menu_Item* save = w->mvalue();
+  w->value((Fl_Menu_Item*)0);
+  Fl::pushed(w);
+  w->handle(FL_PUSH);
+  const Fl_Menu_Item* m = w->mvalue();
+  if (m) {
+    // restore the settings of toggles & radio items:
+    if (m->flags & (FL_MENU_RADIO | FL_MENU_TOGGLE)) build_menu();
+    return (Fl_Type*)(m->user_data());
+  }
+  w->value(save);
+  return this;
+}
+
+void Fl_Menu_Type::write_code2() {
+  if (next && next->is_menu_item())
+    write_c("%so->menu(%s);\n", indent(),
+	    unique_id(this, "menu", name(), label()));
+  Fl_Widget_Type::write_code2();
+}
+
+////////////////////////////////////////////////////////////////
+
+#include 
+static Fl_Menu_Item button_type_menu[] = {
+  {"normal",0,0,(void*)0},
+  {"popup1",0,0,(void*)Fl_Menu_Button::POPUP1},
+  {"popup2",0,0,(void*)Fl_Menu_Button::POPUP2},
+  {"popup3",0,0,(void*)Fl_Menu_Button::POPUP3},
+  {"popup12",0,0,(void*)Fl_Menu_Button::POPUP12},
+  {"popup23",0,0,(void*)Fl_Menu_Button::POPUP23},
+  {"popup13",0,0,(void*)Fl_Menu_Button::POPUP13},
+  {"popup123",0,0,(void*)Fl_Menu_Button::POPUP123},
+  {0}};
+class Fl_Menu_Button_Type : public Fl_Menu_Type {
+  Fl_Menu_Item *subtypes() {return button_type_menu;}
+public:
+  virtual const char *type_name() {return "Fl_Menu_Button";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Menu_Button(x,y,w,h,"menu");}
+  Fl_Widget_Type *_make() {return new Fl_Menu_Button_Type();}
+};
+Fl_Menu_Button_Type Fl_Menu_Button_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+
+static Fl_Menu_Item dummymenu[] = {{"CHOICE"},{0}};
+
+class Fl_Choice_Type : public Fl_Menu_Type {
+public:
+  virtual const char *type_name() {return "Fl_Choice";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    Fl_Choice *o = new Fl_Choice(x,y,w,h,"choice:");
+    o->menu(dummymenu);
+    return o;
+  }
+  Fl_Widget_Type *_make() {return new Fl_Choice_Type();}
+};
+Fl_Choice_Type Fl_Choice_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+class Fl_Menu_Bar_Type : public Fl_Menu_Type {
+public:
+  virtual const char *type_name() {return "Fl_Menu_Bar";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Menu_Bar(x,y,w,h);}
+  Fl_Widget_Type *_make() {return new Fl_Menu_Bar_Type();}
+};
+Fl_Menu_Bar_Type Fl_Menu_Bar_type;
+
+////////////////////////////////////////////////////////////////
+// Shortcut entry item in panel:
+
+#include 
+#include "Shortcut_Button.H"
+#include 
+
+void Shortcut_Button::draw() {
+  if (value()) draw_box(FL_THIN_DOWN_BOX, (Fl_Color)9);
+  else draw_box(FL_THIN_UP_BOX, FL_WHITE);
+  fl_font(FL_HELVETICA,14); fl_color(FL_BLACK);
+  fl_draw(fl_shortcut_label(svalue),x()+6,y(),w(),h(),FL_ALIGN_LEFT);
+}
+
+int Shortcut_Button::handle(int e) {
+  when(0); type(FL_TOGGLE_BUTTON);
+  if (e == FL_KEYBOARD) {
+    if (!value()) return 0;
+    int v = Fl::event_text()[0];
+    if (v > 32 && v < 0x7f || v > 0xa0 && v <= 0xff) {
+      v = v | Fl::event_state()&(FL_META|FL_ALT|FL_CTRL);
+    } else {
+      v = Fl::event_state()&(FL_META|FL_ALT|FL_CTRL|FL_SHIFT) | Fl::event_key();
+      if (v == FL_BackSpace && svalue) v = 0;
+    }
+    if (v != svalue) {svalue = v; set_changed(); redraw();}
+    return 1;
+  } else if (e == FL_UNFOCUS) {
+    int c = changed(); value(0); if (c) set_changed();
+    return 1;
+  } else if (e == FL_FOCUS) {
+    return value();
+  } else {
+    int r = Fl_Button::handle(e);
+    if (e == FL_RELEASE && value() && Fl::focus() != this) take_focus();
+    return r;
+  }
+}
+  
+void shortcut_in_cb(Shortcut_Button* i, void* v) {
+  if (v == LOAD) {
+    if (!current_widget->is_button()) {i->hide(); return;}
+    i->show();
+    i->svalue = ((Fl_Button*)(current_widget->o))->shortcut();
+    i->redraw();
+  } else {
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_button()) {
+	Fl_Button* b = (Fl_Button*)(((Fl_Widget_Type*)o)->o);
+	b->shortcut(i->svalue);
+	if (o->is_menu_item()) ((Fl_Widget_Type*)o)->redraw();
+      }
+  }
+}
diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx
new file mode 100644
index 000000000..f57a970d4
--- /dev/null
+++ b/fluid/Fl_Type.cxx
@@ -0,0 +1,617 @@
+/*	Fl_Type.C
+
+	Each object described by Fluid is one of these objects.  They
+	are all stored in a double-linked list.
+
+	They "type" of the object is covered by the virtual functions.
+	There will probably be a lot of these virtual functions.
+
+	The type browser is also a list of these objects, but they
+	are "factory" instances, not "real" ones.  These objects exist
+	only so the "make" method can be called on them.  They are
+	not in the linked list and are not written to files or
+	copied or otherwise examined.
+
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "Fl_Type.H"
+
+////////////////////////////////////////////////////////////////
+
+class Widget_Browser : public Fl_Browser_ {
+  friend class Fl_Type;
+
+  // required routines for Fl_Browser_ subclass:
+  void *item_first() const ;
+  void *item_next(void *) const ;
+  void *item_prev(void *) const ;
+  int item_selected(void *) const ;
+  void item_select(void *,int);
+  int item_width(void *) const ;
+  int item_height(void *) const ;
+  void item_draw(void *,int,int,int,int) const ;
+  int incr_height() const ;
+
+public:	
+
+  int handle(int);
+  void callback();
+  Widget_Browser(int,int,int,int,const char * =0);
+};
+
+static Widget_Browser *widget_browser;
+Fl_Widget *make_widget_browser(int x,int y,int w,int h) {
+  return (widget_browser = new Widget_Browser(x,y,w,h));
+}
+
+void select(Fl_Type *o, int v) {
+  widget_browser->select(o,v,1);
+  //  Fl_Type::current = o;
+}
+
+void select_only(Fl_Type *o) {
+  widget_browser->select_only(o,1);
+}
+
+void deselect() {
+  widget_browser->deselect();
+  //Fl_Type::current = 0; // this breaks the paste & merge functions
+}
+
+Fl_Type *Fl_Type::first;
+Fl_Type *Fl_Type::last;
+
+static void Widget_Browser_callback(Fl_Widget *o,void *) {
+  ((Widget_Browser *)o)->callback();
+}
+
+Widget_Browser::Widget_Browser(int x,int y,int w,int h,const char*l)
+: Fl_Browser_(x,y,w,h,l) {
+  type(FL_MULTI_BROWSER);
+  Fl_Widget::callback(Widget_Browser_callback);
+  when(FL_WHEN_RELEASE);
+}
+
+void *Widget_Browser::item_first() const {return Fl_Type::first;}
+
+void *Widget_Browser::item_next(void *l) const {return ((Fl_Type*)l)->next;}
+
+void *Widget_Browser::item_prev(void *l) const {return ((Fl_Type*)l)->prev;}
+
+int Widget_Browser::item_selected(void *l) const {return ((Fl_Type*)l)->new_selected;}
+
+void Widget_Browser::item_select(void *l,int v) {((Fl_Type*)l)->new_selected = v;}
+
+int Widget_Browser::item_height(void *l) const {
+  return ((Fl_Type *)l)->visible ? textsize()+2 : 0;
+}
+
+int Widget_Browser::incr_height() const {return textsize()+2;}
+
+static Fl_Type* pushedtitle;
+
+// Generate a descriptive text for this item, to put in browser & window titles
+const char* Fl_Type::title() {
+  const char* c = name(); if (c) return c;
+  return type_name();
+}
+
+extern const char* subclassname(Fl_Type*);
+
+void Widget_Browser::item_draw(void *v, int x, int y, int, int) const {
+  Fl_Type *l = (Fl_Type *)v;
+  x += 3 + l->level * 10;
+  fl_color(FL_BLACK);
+  if (l->is_parent()) {
+    if (!l->next || l->next->level <= l->level) {
+      if (l->open_!=(l==pushedtitle)) {
+	fl_loop(x,y+7,x+5,y+12,x+10,y+7);
+      } else {
+	fl_loop(x+2,y+2,x+7,y+7,x+2,y+12);
+      }
+    } else {
+      if (l->open_!=(l==pushedtitle)) {
+	fl_polygon(x,y+7,x+5,y+12,x+10,y+7);
+      } else {
+	fl_polygon(x+2,y+2,x+7,y+7,x+2,y+12);
+      }
+    }
+    x += 10;
+  }
+  if (l->is_widget() || l->is_class()) {
+    const char* c = subclassname(l);
+    if (!strncmp(c,"Fl_",3)) c += 3;
+    fl_font(textfont(), textsize());
+    fl_draw(c, x, y+13);
+    x += int(fl_width(c)+fl_width('n'));
+    c = l->name();
+    if (c) {
+      fl_font(textfont()|FL_BOLD, textsize());
+      fl_draw(c, x, y+13);
+    } else if ((c=l->label())) {
+      char buf[50]; char* p = buf;
+      *p++ = '"';
+      for (int i = 20; i--;) {
+	if (! (*c & -32)) break;
+	*p++ = *c++;
+      }
+      if (*c) {strcpy(p,"..."); p+=3;}
+      *p++ = '"';
+      *p = 0;
+      fl_draw(buf, x, y+13);
+    }
+  } else {
+    const char* c = l->title();
+    char buf[60]; char* p = buf;
+    for (int i = 55; i--;) {
+      if (! (*c & -32)) break;
+      *p++ = *c++;
+    }
+    if (*c) {strcpy(p,"..."); p+=3;}
+    *p = 0;
+    fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize());
+    fl_draw(buf, x, y+13);
+  }
+}
+
+int Widget_Browser::item_width(void *v) const {
+  Fl_Type *l = (Fl_Type *)v;
+
+  if (!l->visible) return 0;
+
+  int w = 3 + l->level*10;
+  if (l->is_parent()) w += 10;
+
+  if (l->is_widget() || l->is_class()) {
+    const char* c = l->type_name();
+    if (!strncmp(c,"Fl_",3)) c += 3;
+    fl_font(textfont(), textsize());
+    w += int(fl_width(c) + fl_width('n'));
+    c = l->name();
+    if (c) {
+      fl_font(textfont()|FL_BOLD, textsize());
+      w += int(fl_width(c));
+    } else if ((c=l->label())) {
+      char buf[50]; char* p = buf;
+      *p++ = '"';
+      for (int i = 20; i--;) {
+	if (! (*c & -32)) break;
+	*p++ = *c++;
+      }
+      if (*c) {strcpy(p,"..."); p+=3;}
+      *p++ = '"';
+      *p = 0;
+      w += int(fl_width(buf));
+    }
+  } else {
+    const char* c = l->title();
+    char buf[60]; char* p = buf;
+    for (int i = 55; i--;) {
+      if (! (*c & -32)) break;
+      *p++ = *c++;
+    }
+    if (*c) {strcpy(p,"..."); p+=3;}
+    *p = 0;
+    fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize());
+    w += int(fl_width(buf));
+  }
+
+  return w;
+}
+
+void redraw_browser() {
+  widget_browser->redraw();
+}
+
+void Widget_Browser::callback() {
+  selection_changed((Fl_Type*)selection());
+}
+
+int Widget_Browser::handle(int e) {
+  static Fl_Type *title;
+  Fl_Type *l;
+  int X,Y,W,H; bbox(X,Y,W,H);
+  switch (e) {
+  case FL_PUSH:
+    if (!Fl::event_inside(X,Y,W,H)) break;
+    l = (Fl_Type*)find_item(Fl::event_y());
+    if (l) {
+      X += 10*l->level;
+      if (l->is_parent() && Fl::event_x()>X && Fl::event_x()level;
+      if (l->is_parent() && Fl::event_x()>X && Fl::event_x()new_selected && (Fl::event_clicks() || Fl::event_state(FL_CTRL)))
+	l->open();
+      break;
+    }
+    l = pushedtitle;
+    title = pushedtitle = 0;
+    if (l) {
+      if (l->open_) {
+	l->open_ = 0;
+	for (Fl_Type*k = l->next; k&&k->level>l->level; k = k->next)
+	  k->visible = 0;
+      } else {
+	l->open_ = 1;
+	for (Fl_Type*k=l->next; k&&k->level>l->level;) {
+	  k->visible = 1;
+	  if (k->is_parent() && !k->open_) {
+	    Fl_Type *j;
+	    for (j = k->next; j && j->level>k->level; j = j->next);
+	    k = j;
+	  } else
+	    k = k->next;
+	}
+      }
+      redraw();
+    }
+    return 1;
+  }
+  return Fl_Browser_::handle(e);
+}
+
+Fl_Type::Fl_Type() {
+  factory = 0;
+  parent = 0;
+  next = prev = 0;
+  selected = new_selected = 0;
+  visible = 0;
+  name_ = 0;
+  label_ = 0;
+  user_data_ = 0;
+  user_data_type_ = 0;
+  callback_ = 0;
+  rtti = 0;
+  level = 0;
+}
+
+static void fixvisible(Fl_Type *p) {
+  Fl_Type *t = p;
+  for (;;) {
+    if (t->parent) t->visible = t->parent->visible && t->parent->open_;
+    else t->visible = 1;
+    t = t->next;
+    if (!t || t->level <= p->level) break;
+  }
+}
+
+// turn a click at x,y on this into the actual picked object:
+Fl_Type* Fl_Type::click_test(int,int) {return 0;}
+void Fl_Type::add_child(Fl_Type*, Fl_Type*) {}
+void Fl_Type::move_child(Fl_Type*, Fl_Type*) {}
+void Fl_Type::remove_child(Fl_Type*) {}
+
+// add a list of widgets as a new child of p:
+void Fl_Type::add(Fl_Type *p) {
+  parent = p;
+  Fl_Type *end = this;
+  while (end->next) end = end->next;
+  Fl_Type *q;
+  int newlevel;
+  if (p) {
+    for (q = p->next; q && q->level > p->level; q = q->next);
+    newlevel = p->level+1;
+  } else {
+    q = 0;
+    newlevel = 0;
+  }
+  for (Fl_Type *t = this->next; t; t = t->next) t->level += (newlevel-level);
+  level = newlevel;
+  if (q) {
+    prev = q->prev;
+    prev->next = this;
+    q->prev = end;
+    end->next = q;
+  } else if (first) {
+    prev = last;
+    prev->next = this;
+    end->next = 0;
+    last = end;
+  } else {
+    first = this;
+    last = end;
+    prev = end->next = 0;
+  }
+  if (p) p->add_child(this,0);
+  open_ = 1;
+  fixvisible(this);
+  modflag = 1;
+  widget_browser->redraw();
+}
+
+// add to a parent before another widget:
+void Fl_Type::insert(Fl_Type *g) {
+  Fl_Type *end = this;
+  while (end->next) end = end->next;
+  parent = g->parent;
+  int newlevel = g->level;
+  visible = g->visible;
+  for (Fl_Type *t = this->next; t; t = t->next) t->level += newlevel-level;
+  level = newlevel;
+  prev = g->prev;
+  if (prev) prev->next = this; else first = this;
+  end->next = g;
+  g->prev = end;
+  fixvisible(this);
+  if (parent) parent->add_child(this, g);
+  widget_browser->redraw();
+}
+
+// delete from parent:
+Fl_Type *Fl_Type::remove() {
+  Fl_Type *end = this;
+  for (;;) {
+    if (!end->next || end->next->level <= level) break;
+    end = end->next;
+  }
+  if (prev) prev->next = end->next;
+  else first = end->next;
+  if (end->next) end->next->prev = prev;
+  else last = prev;
+  Fl_Type *r = end->next;
+  prev = end->next = 0;
+  if (parent) parent->remove_child(this);
+  parent = 0;
+  widget_browser->redraw();
+  selection_changed(0);
+  return r;
+}
+
+// update a string member:
+int storestring(const char *n, const char * & p, int nostrip) {
+  if (n == p) return 0;
+  int length = 0;
+  if (n) { // see if blank, strip leading & trailing blanks
+    if (!nostrip) while (isspace(*n)) n++;
+    const char *e = n + strlen(n);
+    if (!nostrip) while (e > n && isspace(*(e-1))) e--;
+    length = e-n;
+    if (!length) n = 0;
+  }    
+  if (n == p) return 0;
+  if (n && p && !strncmp(n,p,length) && !p[length]) return 0;
+  if (p) free((void *)p);
+  if (!n || !*n) {
+    p = 0;
+  } else {
+    char *q = (char *)malloc(length+1);
+    strncpy(q,n,length);
+    q[length] = 0;
+    p = q;
+  }
+  modflag = 1;
+  return 1;
+}
+
+void Fl_Type::name(const char *n) {
+  if (storestring(n,name_)) {
+    if (visible) widget_browser->redraw();
+  }
+}
+
+void Fl_Type::label(const char *n) {
+  if (storestring(n,label_,1)) {
+    setlabel(label_);
+    if (visible && !name_) widget_browser->redraw();
+  }
+}
+
+void Fl_Type::callback(const char *n) {
+  storestring(n,callback_);
+}
+
+void Fl_Type::user_data(const char *n) {
+  storestring(n,user_data_);
+}
+
+void Fl_Type::user_data_type(const char *n) {
+  storestring(n,user_data_type_);
+}
+
+void Fl_Type::open() {
+  printf("Open of '%s' is not yet implemented\n",type_name());
+}
+
+void Fl_Type::setlabel(const char *) {}
+
+Fl_Type::~Fl_Type() {
+  if (parent) parent->remove_child(this);
+  // warning: destructor only works for widgets that have been add()ed.
+  if (widget_browser) widget_browser->deleting(this);
+  if (prev) prev->next = next; else first = next;
+  if (next) next->prev = prev; else last = prev;
+  if (current == this) current = 0;
+  modflag = 1;
+}
+
+int Fl_Type::is_parent() const {return 0;}
+int Fl_Type::is_widget() const {return 0;}
+int Fl_Type::is_valuator() const {return 0;}
+int Fl_Type::is_button() const {return 0;}
+int Fl_Type::is_menu_item() const {return 0;}
+int Fl_Type::is_menu_button() const {return 0;}
+int Fl_Type::is_group() const {return 0;}
+int Fl_Type::is_window() const {return 0;}
+int Fl_Type::is_code_block() const {return 0;}
+int Fl_Type::is_decl_block() const {return 0;}
+int Fl_Type::is_class() const {return 0;}
+
+////////////////////////////////////////////////////////////////
+
+Fl_Type *in_this_only; // set if menu popped-up in window
+
+void select_all_cb(Fl_Widget *,void *) {
+  Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0;
+  if (in_this_only) {
+    Fl_Type *t = p;
+    for (; t && t != in_this_only; t = t->parent);
+    if (t != in_this_only) p = in_this_only;
+  }
+  for (;;) {
+    if (p) {
+      int foundany = 0;
+      for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) {
+	if (!t->new_selected) {widget_browser->select(t,1,0); foundany = 1;}
+      }
+      if (foundany) break;
+      p = p->parent;
+    } else {
+      for (Fl_Type *t = Fl_Type::first; t; t = t->next)
+	widget_browser->select(t,1,0);
+      break;
+    }
+  }
+  selection_changed(p);
+}
+
+static void delete_children(Fl_Type *p) {
+  Fl_Type *f;
+  for (f = p; f && f->next && f->next->level > p->level; f = f->next);
+  for (; f != p; ) {
+    Fl_Type *g = f->prev;
+    delete f;
+    f = g;
+  }
+}
+
+void delete_all(int selected_only) {
+  for (Fl_Type *f = Fl_Type::first; f;) {
+    if (f->selected || !selected_only) {
+      delete_children(f);
+      Fl_Type *g = f->next;
+      delete f;
+      f = g;
+    } else f = f->next;
+  }
+  selection_changed(0);
+}
+
+// move f (and it's children) into list before g:
+// returns pointer to whatever is after f & children
+void Fl_Type::move_before(Fl_Type* g) {
+  if (level != g->level) printf("move_before levels don't match! %d %d\n",
+				level, g->level);
+  Fl_Type* n;
+  for (n = next; n && n->level > level; n = n->next);
+  if (n == g) return;
+  Fl_Type *l = n ? n->prev : Fl_Type::last;
+  prev->next = n;
+  if (n) n->prev = prev; else Fl_Type::last = prev;
+  prev = g->prev;
+  l->next = g;
+  if (prev) prev->next = this; else Fl_Type::first = this;
+  g->prev = l;
+  if (parent) parent->move_child(this,g);
+  widget_browser->redraw();
+}
+
+// move selected widgets in their parent's list:
+void earlier_cb(Fl_Widget*,void*) {
+  Fl_Type *f;
+  for (f = Fl_Type::first; f; f=f->next) if (f->selected) {
+    Fl_Type *g;
+    for (g = f->prev; g && g->level > f->level; g = g->prev);
+    if (g && g->level == f->level) f->move_before(g);
+  }
+}
+
+void later_cb(Fl_Widget*,void*) {
+  Fl_Type *f;
+  for (f = Fl_Type::last; f; f=f->prev) if (f->selected) {
+    Fl_Type *g;
+    for (g = f->next; g && g->level > f->level; g = g->next);
+    if (g && g->level == f->level && !g->selected) g->move_before(f);
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+// write a widget and all it's children:
+void Fl_Type::write() {
+    write_indent(level);
+    write_word(type_name());
+    write_word(name());
+    write_open(level);
+    write_properties();
+    write_close(level);
+    if (!is_parent()) return;
+    // now do children:
+    write_open(level);
+    Fl_Type *child;
+    for (child = next; child && child->level > level; child = child->next)
+	if (child->level == level+1) child->write();
+    write_close(level);
+}
+
+void Fl_Type::write_properties() {
+  // repeat this for each attribute:
+  if (label()) {
+    write_indent(level+1);
+    write_word("label");
+    write_word(label());
+  }
+  if (user_data()) {
+    write_indent(level+1);
+    write_word("user_data");
+    write_word(user_data());
+    if (user_data_type()) {
+      write_word("user_data_type");
+      write_word(user_data_type());
+    }
+  }
+  if (callback()) {
+    write_indent(level+1);
+    write_word("callback");
+    write_word(callback());
+  }
+  if (is_parent() && open_) write_word("open");
+  if (selected) write_word("selected");
+}
+
+void Fl_Type::read_property(const char *c) {
+  if (!strcmp(c,"label"))
+    label(read_word());
+  else if (!strcmp(c,"user_data"))
+    user_data(read_word());
+  else if (!strcmp(c,"user_data_type"))
+    user_data_type(read_word());
+  else if (!strcmp(c,"callback"))
+    callback(read_word());
+  else if (!strcmp(c,"open"))
+    open_ = 1;
+  else if (!strcmp(c,"selected"))
+    select(this,1);
+  else
+    read_error("Unknown property \"%s\"", c);
+}
+
+int Fl_Type::read_fdesign(const char*, const char*) {return 0;}
diff --git a/fluid/Fl_Type.h b/fluid/Fl_Type.h
new file mode 100644
index 000000000..737423a1d
--- /dev/null
+++ b/fluid/Fl_Type.h
@@ -0,0 +1,142 @@
+// Fl_Type.H
+
+// Each object described by Fluid is one of these objects.  They
+// are all stored in a double-linked list.
+
+// There is also a single "factory" instance of each type of this.
+// The method "make()" is called on this factory to create a new
+// instance of this object.  It could also have a "copy()" function,
+// but it was easier to implement this by using the file read/write
+// that is needed to save the setup anyways.
+
+#include 
+#include 
+
+class Fl_Type {
+
+  friend class Widget_Browser;
+  friend Fl_Widget *make_type_browser(int,int,int,int,const char *l=0);
+  friend class Fl_Window_Type;
+  virtual void setlabel(const char *); // virtual part of label(char*)
+
+protected:
+
+  Fl_Type();
+
+  const char *name_;
+  const char *label_;
+  const char *callback_;
+  const char *user_data_;
+  const char *user_data_type_;
+
+public:	// things that should not be public:
+
+  Fl_Type *parent; // parent, which is previous in list
+  char new_selected; // browser highlight
+  char selected; // copied here by selection_changed()
+  char open_;	// state of triangle in browser
+  char visible; // true if all parents are open
+  char rtti;	// hack because I have no rtti, this is 0 for base class
+  int level;	// number of parents over this
+  static Fl_Type *first, *last; // linked list of all objects
+  Fl_Type *next, *prev;	// linked list of all objects
+
+  Fl_Type *factory;
+  const char *callback_name();
+
+public:
+
+  virtual ~Fl_Type();
+  virtual Fl_Type *make() = 0;
+
+  void add(Fl_Type *parent); // add as new child
+  void insert(Fl_Type *n); // insert into list before n
+  Fl_Type* remove();	// remove from list
+  void move_before(Fl_Type*); // move before a sibling
+
+  virtual const char *title(); // string for browser
+  virtual const char *type_name() = 0; // type for code output
+
+  const char *name() const {return name_;}
+  void name(const char *);
+  const char *label() const {return label_;}
+  void label(const char *);
+  const char *callback() const {return callback_;}
+  void callback(const char *);
+  const char *user_data() const {return user_data_;}
+  void user_data(const char *);
+  const char *user_data_type() const {return user_data_type_;}
+  void user_data_type(const char *);
+
+  virtual Fl_Type* click_test(int,int);
+  virtual void add_child(Fl_Type*, Fl_Type* beforethis);
+  virtual void move_child(Fl_Type*, Fl_Type* beforethis);
+  virtual void remove_child(Fl_Type*);
+
+  static Fl_Type *current;  // most recently picked object
+  virtual void open();	// what happens when you double-click
+
+  // read and write data to a saved file:
+  void write();
+  virtual void write_properties();
+  virtual void read_property(const char *);
+  virtual int read_fdesign(const char*, const char*);
+
+  // write code, these are called in order:
+  virtual void write_declare(); // write #include and #define to .h file
+  virtual void write_static(); // write static stuff to .c file
+  virtual void write_code1(); // code and .h before children
+  virtual void write_code2(); // code and .h after children
+
+  // fake rtti:
+  virtual int is_parent() const;
+  virtual int is_widget() const;
+  virtual int is_button() const;
+  virtual int is_valuator() const;
+  virtual int is_menu_item() const;
+  virtual int is_menu_button() const;
+  virtual int is_group() const;
+  virtual int is_window() const;
+  virtual int is_code_block() const;
+  virtual int is_decl_block() const;
+  virtual int is_class() const;
+
+  const char* class_name() const;
+};
+
+// object list operations:
+Fl_Widget *make_widget_browser(int x,int y,int w,int h);
+extern int modflag;
+void delete_all(int selected_only=0);
+void selection_changed(Fl_Type* new_current);
+
+// file operations:
+void write_word(const char *);
+void write_string(const char *,...);
+int write_file(const char *, int selected_only = 0);
+int write_code(const char *cfile, const char *hfile);
+
+int write_declare(const char *, ...);
+int is_id(char);
+const char* unique_id(void* o, const char*, const char*, const char*);
+void write_c(const char*, ...);
+void write_h(const char*, ...);
+void write_cstring(const char *);
+void write_cstring(const char *,int length);
+void write_indent(int n);
+void write_open(int);
+void write_close(int n);
+extern int write_number;
+void write_public(int state); // writes pubic:/private: as needed
+extern int indentation;
+extern const char* indent();
+
+int read_file(const char *, int merge);
+const char *read_word(int wantbrace = 0);
+void read_error(const char *format, ...);
+
+// check legality of c code (sort of) and return error:
+const char *c_check(const char *c, int type = 0);
+
+// replace a string pointer with new value, strips leading/trailing blanks:
+int storestring(const char *n, const char * & p, int nostrip=0);
diff --git a/fluid/Fl_Widget_Type.cxx b/fluid/Fl_Widget_Type.cxx
new file mode 100644
index 000000000..96c22acea
--- /dev/null
+++ b/fluid/Fl_Widget_Type.cxx
@@ -0,0 +1,1676 @@
+// Fl_Widget_Type.C
+
+#include 
+#include 
+#include "Fl_Widget_Type.H"
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+// Make an Fl_Widget_Type subclass instance.
+// It figures out the automatic size and parent of the new widget,
+// creates the Fl_Widget (by calling the virtual function _make),
+// adds it to the Fl_Widget hierarchy, creates a new Fl_Type
+// instance, sets the widget pointers, and makes all the display
+// update correctly...
+
+extern int reading_file;
+int force_parent;
+extern int gridx;
+extern int gridy;
+
+int Fl_Widget_Type::is_widget() const {return 1;}
+
+const char* subclassname(Fl_Type* l) {
+  if (l->is_widget()) {
+    Fl_Widget_Type* p = (Fl_Widget_Type*)l;
+    const char* c = p->subclass();
+    if (c) return c;
+    if (p->o->type() == FL_WINDOW+1) return "Fl_Double_Window";
+  }
+  return l->type_name();
+}
+
+Fl_Type *Fl_Widget_Type::make() {
+  // Find the current widget, or widget to copy:
+  Fl_Type *qq = Fl_Type::current;
+  while (qq && (!qq->is_widget() || qq->is_menu_item())) qq = qq->parent;
+  if (!qq) {
+    fl_message("Please select a widget");
+    return 0;
+  }
+  Fl_Widget_Type* q = (Fl_Widget_Type*)qq;
+  // find the parent widget:
+  Fl_Widget_Type* p = q;
+  if ((force_parent || !p->is_group()) && p->parent->is_widget())
+    p = (Fl_Widget_Type*)(p->parent);
+  force_parent = 0;
+
+  // Figure out a border between widget and window:
+  int B = p->o->w()/2; if (p->o->h()/2 < B) B = p->o->h()/2; if (B>25) B = 25;
+
+  int ULX,ULY; // parent's origin in window
+  if (!p->is_window()) { // if it is a group, add corner
+    ULX = p->o->x(); ULY = p->o->y();
+  } else {
+    ULX = ULY = 0;
+  }
+
+  // Figure out a position and size for the widget
+  int X,Y,W,H;
+  if (is_group()) {	// fill the parent with the widget
+    X = ULX+B;
+    W = p->o->w()-B;
+    Y = ULY+B;
+    H = p->o->h()-B;
+  } else if (q != p) {	// copy position and size of current widget
+    W = q->o->w();
+    H = q->o->h();
+    X = q->o->x()+W;
+    Y = q->o->y();
+    if (X+W > ULX+p->o->w()) {
+      X = q->o->x();
+      Y = q->o->y()+H;
+      if (Y+H > ULY+p->o->h()) Y = ULY+B;
+    }
+  } else {	// just make it small and square...
+    X = ULX+B;
+    Y = ULY+B;
+    W = H = B;
+  }
+
+  // satisfy the grid requirements (otherwise it edits really strangely):
+  if (gridx>1) {
+    X = (X/gridx)*gridx;
+    W = ((W-1)/gridx+1)*gridx;
+  }
+  if (gridy>1) {
+    Y = (Y/gridy)*gridy;
+    H = ((H-1)/gridy+1)*gridy;
+  }
+
+  // Construct the Fl_Type:
+  Fl_Widget_Type *t = _make();
+  if (!o) o = widget(0,0,100,100); // create template widget
+  t->factory = this;
+  // Construct the Fl_Widget:
+  t->o = widget(X,Y,W,H);
+  if (reading_file) t->o->label(0);
+  else if (t->o->label()) t->label(t->o->label()); // allow editing
+  t->o->user_data((void*)t);
+  // Put it in the parent:
+  //  ((Fl_Group *)(p->o))->add(t->o); (done by Fl_Type::add())
+  // add to browser:
+  t->add(p);
+  t->redraw();
+  return t;
+}
+
+#include "Fluid_Image.H"
+
+void Fl_Widget_Type::setimage(Fluid_Image *i) {
+  if (i == image) return;
+  if (image) image->decrement();
+  if (i) i->increment();
+  image = i;
+  if (i) i->label(o);
+  else o->labeltype(FL_NORMAL_LABEL);
+  redraw();
+}
+
+static char dont_touch_image;
+void Fl_Widget_Type::setlabel(const char *n) {
+  if (image) {
+    if (dont_touch_image) return;
+    Fluid_Image *i = Fluid_Image::find(n);
+    setimage(i);
+    if (i) return;
+  }
+  o->label(n);
+  redraw();
+}
+
+Fl_Widget_Type::Fl_Widget_Type() {
+  for (int n=0; nhide();
+    if (o->parent()) ((Fl_Group*)o->parent())->remove(*o);
+    delete o;
+  }
+}
+
+void Fl_Widget_Type::extra_code(int m,const char *n) {
+  storestring(n,extra_code_[m]);
+}
+
+extern void redraw_browser();
+void Fl_Widget_Type::subclass(const char *n) {
+  if (storestring(n,subclass_) && visible)
+    redraw_browser();
+}
+
+void Fl_Widget_Type::redraw() {
+  Fl_Type *t = this;
+  if (is_menu_item()) {
+    // find the menu button that parents this menu:
+    do t = t->parent; while (t && t->is_menu_item());
+    // kludge to cause build_menu to be called again:
+    t->add_child(0,0);
+  } else {
+    while (t->parent && t->parent->is_widget()) t = t->parent;
+    ((Fl_Widget_Type*)t)->o->redraw();
+  }
+}
+
+// the recursive part sorts all children, returns pointer to next:
+Fl_Type *sort(Fl_Type *parent) {
+  Fl_Type *f,*n=0;
+  for (f = parent ? parent->next : Fl_Type::first; ; f = n) {
+    if (!f || parent && f->level <= parent->level) return f;
+    n = sort(f);
+    if (!f->selected || (!f->is_widget() || f->is_menu_item())) continue;
+    Fl_Widget* fw = ((Fl_Widget_Type*)f)->o;
+    Fl_Type *g; // we will insert before this
+    for (g = parent->next; g != f; g = g->next) {
+      if (!g->selected || g->level > f->level) continue;
+      Fl_Widget* gw = ((Fl_Widget_Type*)g)->o;
+      if (gw->y() > fw->y()) break;
+      if (gw->y() == fw->y() && gw->x() > fw->x()) break;
+    }
+    if (g != f) f->move_before(g);
+  }
+}
+
+////////////////////////////////////////////////////////////////
+// The control panels!
+
+#include "widget_panel.H"
+#include 
+
+// All the callbacks use the argument to indicate whether to load or store.
+// This avoids the need for pointers to all the widgets, and keeps the
+// code localized in the callbacks.
+// A value of LOAD means to load.  The hope is that this will not collide
+// with any actual useful values for the argument.  I also use this to
+// initialized parts of the widget that are nyi by fluid.
+
+Fl_Widget_Type *current_widget; // one of the selected ones
+static int numselected; // number selected
+static int haderror;
+
+void name_cb(Fl_Input* o, void *v) {
+  if (v == LOAD) {
+    if (numselected != 1) {
+      static char buf[16];
+      sprintf(buf,"(%d widgets)",numselected);
+      ((Fl_Window*)(o->parent()))->label(buf);
+      o->hide();
+    } else {
+      o->static_value(current_widget->name());
+      o->show();
+      ((Fl_Window*)(o->parent()))->label(current_widget->title());
+    }
+  } else {
+    if (numselected == 1) {
+      current_widget->name(o->value());
+      // I don't update window title, as it probably is being closed
+      // and wm2 (a window manager) barfs if you retitle and then
+      // hide a window:
+      // ((Fl_Window*)(o->parent()))->label(current_widget->title());
+    }
+  }
+}
+
+void name_public_cb(Fl_Light_Button* i, void* v) {
+  if (v == LOAD) {
+    i->value(current_widget->public_);
+  } else {
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget())
+	((Fl_Widget_Type*)o)->public_ = i->value();
+  }
+}    
+
+static char* oldlabel;
+static unsigned oldlabellen;
+static Fl_Input *label_input;
+
+void label_cb(Fl_Input* i, void *v) {
+  if (v == LOAD) {
+    label_input = i;
+    i->static_value(current_widget->label());
+    if (strlen(i->value()) >= oldlabellen) {
+      oldlabellen = strlen(i->value())+128;
+      oldlabel = (char*)realloc(oldlabel,oldlabellen);
+    }
+    strcpy(oldlabel,i->value());
+    if (current_widget->image) i->deactivate();
+    else i->activate();
+  } else {
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) o->label(i->value());
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+// turn number to string or string to number for saving to file:
+// does not work for hierarchial menus!
+
+const char *item_name(Fl_Menu_Item* m, int i) {
+  if (m) {
+    while (m->label()) {
+      if (m->argument() == i) return m->label();
+      m++;
+    }
+  }
+  static char buffer[20];
+  sprintf(buffer, "%d", i);
+  return buffer;
+}
+int item_number(Fl_Menu_Item* m, const char* i) {
+  if (m && i) {
+    if (i[0]=='F' && i[1]=='L' && i[2]=='_') i += 3;
+    while (m->label()) {
+      if (!strcmp(m->label(), i)) return int(m->argument());
+      m++;
+    }
+  }
+  return atoi(i);
+}
+
+#define ZERO_ENTRY 1000
+
+Fl_Menu_Item boxmenu[] = {
+{"NO_BOX",0,0,(void *)ZERO_ENTRY},
+{"boxes",0,0,0,FL_SUBMENU},
+{"UP_BOX",0,0,(void *)FL_UP_BOX},
+{"DOWN_BOX",0,0,(void *)FL_DOWN_BOX},
+{"FLAT_BOX",0,0,(void *)FL_FLAT_BOX},
+{"BORDER_BOX",0,0,(void *)FL_BORDER_BOX},
+{"THIN_UP_BOX",0,0,(void *)FL_THIN_UP_BOX},
+{"THIN_DOWN_BOX",0,0,(void *)FL_THIN_DOWN_BOX},
+{"ENGRAVED_BOX",0,0,(void *)FL_ENGRAVED_BOX},
+{"EMBOSSED_BOX",0,0,(void *)FL_EMBOSSED_BOX},
+{"ROUND_UP_BOX",0,0,(void *)FL_ROUND_UP_BOX},
+{"ROUND_DOWN_BOX",0,0,(void *)FL_ROUND_DOWN_BOX},
+{"DIAMOND_UP_BOX",0,0,(void *)FL_DIAMOND_UP_BOX},
+{"DIAMOND_DOWN_BOX",0,0,(void *)FL_DIAMOND_DOWN_BOX},
+{"SHADOW_BOX",0,0,(void *)FL_SHADOW_BOX},
+{"ROUNDED_BOX",0,0,(void *)FL_ROUNDED_BOX},
+{"RSHADOW_BOX",0,0,(void *)FL_RSHADOW_BOX},
+{"RFLAT_BOX",0,0,(void *)FL_RFLAT_BOX},
+{"OVAL_BOX",0,0,(void *)FL_OVAL_BOX},
+{"OSHADOW_BOX",0,0,(void *)FL_OSHADOW_BOX},
+{"OFLAT_BOX",0,0,(void *)FL_OFLAT_BOX},
+{0},
+{"frames",0,0,0,FL_SUBMENU},
+{"UP_FRAME",0,0,(void *)FL_UP_FRAME},
+{"DOWN_FRAME",0,0,(void *)FL_DOWN_FRAME},
+{"THIN_UP_FRAME",0,0,(void *)FL_THIN_UP_FRAME},
+{"THIN_DOWN_FRAME",0,0,(void *)FL_THIN_DOWN_FRAME},
+{"ENGRAVED_FRAME",0,0,(void *)FL_ENGRAVED_FRAME},
+{"EMBOSSED_FRAME",0,0,(void *)FL_EMBOSSED_FRAME},
+{"BORDER_FRAME",0,0,(void *)FL_BORDER_FRAME},
+{"SHADOW_FRAME",0,0,(void *)FL_SHADOW_FRAME},
+{"ROUNDED_FRAME",0,0,(void *)FL_ROUNDED_FRAME},
+{"OVAL_FRAME",0,0,(void *)FL_OVAL_FRAME},
+{0},
+{0}};
+
+const char *boxname(int i) {
+  if (!i) i = ZERO_ENTRY;
+  for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++)
+    if (boxmenu[j].argument() == i) return boxmenu[j].label();
+  return 0;
+}
+
+int boxnumber(const char *i) {
+  if (i[0]=='F' && i[1]=='L' && i[2]=='_') i += 3;
+  for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++)
+    if (boxmenu[j].label() && !strcmp(boxmenu[j].label(), i)) {
+      return int(boxmenu[j].argument());
+    }
+  return 0;
+}
+
+void box_cb(Fl_Choice* i, void *v) {
+  if (v == LOAD) {
+    if (current_widget->is_menu_item()) {i->hide(); return;} else i->show();
+    int n = current_widget->o->box(); if (!n) n = ZERO_ENTRY;
+    for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++)
+      if (boxmenu[j].argument() == n) {i->value(j); break;}
+  } else {
+    int m = i->value();
+    int n = int(boxmenu[m].argument());
+    if (!n) return; // should not happen
+    if (n == ZERO_ENTRY) n = 0;
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+        q->o->box((Fl_Boxtype)n);
+        q->redraw();
+      }
+  }
+}
+
+void down_box_cb(Fl_Choice* i, void *v) {
+  if (v == LOAD) {
+    int n;
+    if (current_widget->is_button() && !current_widget->is_menu_item())
+      n = ((Fl_Button*)(current_widget->o))->down_box();
+    else if (current_widget->is_menu_button())
+      n = ((Fl_Menu_*)(current_widget->o))->down_box();
+    else {
+      i->hide(); return;
+    }
+    i->show();
+    if (!n) n = ZERO_ENTRY;
+    for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++)
+      if (boxmenu[j].argument() == n) {i->value(j); break;}
+  } else {
+    int m = i->value();
+    int n = int(boxmenu[m].argument());
+    if (!n) return; // should not happen
+    if (n == ZERO_ENTRY) n = 0;
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected) {
+      if (o->is_button() && !o->is_menu_item()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+        ((Fl_Button*)(q->o))->down_box((Fl_Boxtype)n);
+        if (((Fl_Button*)(q->o))->value()) q->redraw();
+      } else if (o->is_menu_button()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+        ((Fl_Menu_*)(q->o))->down_box((Fl_Boxtype)n);
+      }
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+Fl_Menu_Item whenmenu[] = {
+  {"never",0,0,(void*)ZERO_ENTRY},
+  {"Release",0,0,(void*)FL_WHEN_RELEASE},
+  {"Changed",0,0,(void*)FL_WHEN_CHANGED},
+  {"Enter key",0,0,(void*)FL_WHEN_ENTER_KEY},
+  //{"Release or Enter",0,0,(void*)(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE)},
+  {0}};
+
+void when_cb(Fl_Choice* i, void *v) {
+  if (v == LOAD) {
+    if (current_widget->is_menu_item()) {i->hide(); return;} else i->show();
+    int n = current_widget->o->when() & (~FL_WHEN_NOT_CHANGED);
+    if (!n) n = ZERO_ENTRY;
+    for (int j = 0; j < int(sizeof(whenmenu)/sizeof(*whenmenu)); j++)
+      if (whenmenu[j].argument() == n) {i->value(j); break;}
+  } else {
+    int m = i->value();
+    int n = int(whenmenu[m].argument());
+    if (!n) return; // should not happen
+    if (n == ZERO_ENTRY) n = 0;
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	q->o->when(n|(q->o->when()&FL_WHEN_NOT_CHANGED));
+      }
+  }
+}
+
+void when_button_cb(Fl_Light_Button* i, void *v) {
+  if (v == LOAD) {
+    if (current_widget->is_menu_item()) {i->hide(); return;} else i->show();
+    i->value(current_widget->o->when()&FL_WHEN_NOT_CHANGED);
+  } else {
+    int n = i->value() ? FL_WHEN_NOT_CHANGED : 0;
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	q->o->when(n|(q->o->when()&~FL_WHEN_NOT_CHANGED));
+      }
+  }
+}
+
+uchar Fl_Widget_Type::resizable() const {
+  if (is_window()) return ((Fl_Window*)o)->resizable() != 0;
+  Fl_Group* p = (Fl_Group*)o->parent();
+  if (p) return p->resizable() == o;
+  else return 0;
+}
+
+void Fl_Widget_Type::resizable(uchar v) {
+  if (v) {
+    if (resizable()) return;
+    if (is_window()) ((Fl_Window*)o)->resizable(o);
+    else {
+      Fl_Group* p = (Fl_Group*)o->parent();
+      if (p) p->resizable(o);
+    }
+  } else {
+    if (!resizable()) return;
+    if (is_window()) {
+      ((Fl_Window*)o)->resizable(0);
+    } else {
+      Fl_Group* p = (Fl_Group*)o->parent();
+      if (p) p->resizable(0);
+    }
+  }
+}
+
+void resizable_cb(Fl_Light_Button* i,void* v) {
+  if (v == LOAD) {
+    if (current_widget->is_menu_item()) {i->hide(); return;}
+    if (numselected > 1) {i->hide(); return;}
+    i->show();
+    i->value(current_widget->resizable());
+  } else {
+    current_widget->resizable(i->value());
+  }
+}
+
+void hotspot_cb(Fl_Light_Button* i,void* v) {
+  if (v == LOAD) {
+    if (numselected > 1) {i->hide(); return;}
+    if (current_widget->is_menu_item()) i->label("divider");
+    else i->label("hotspot");
+    i->show();
+    i->value(current_widget->hotspot());
+  } else {
+    current_widget->hotspot(i->value());
+    if (current_widget->is_menu_item()) {current_widget->redraw(); return;}
+    if (i->value()) {
+      Fl_Type *p = current_widget->parent;
+      if (!p || !p->is_widget()) return;
+      while (!p->is_window()) p = p->parent;
+      for (Fl_Type *o = p->next; o && o->level > p->level; o = o->next) {
+	if (o->is_widget() && o != current_widget)
+	  ((Fl_Widget_Type*)o)->hotspot(0);
+      }
+    }
+  }
+}
+
+void visible_cb(Fl_Light_Button* i, void* v) {
+  if (v == LOAD) {
+    i->value(current_widget->o->visible());
+  } else {
+    int n = i->value();
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	n ? q->o->show() : q->o->hide();
+	q->redraw();
+      }
+  }
+}
+
+void active_cb(Fl_Light_Button* i, void* v) {
+  if (v == LOAD) {
+    i->value(current_widget->o->active());
+  } else {
+    int n = i->value();
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	n ? q->o->activate() : q->o->deactivate();
+	q->redraw();
+      }
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+Fl_Menu_Item fontmenu[] = {
+{"Helvetica"},
+{"Helvetica bold"},
+{"Helvetica italic"},
+{"Helvetica bold italic"},
+{"Courier"},
+{"Courier bold"},
+{"Courier italic"},
+{"Courier bold italic"},
+{"Times"},
+{"Times bold"},
+{"Times italic"},
+{"Times bold italic"},
+{"Symbol"},
+{"Terminal"},
+{"Terminal Bold"},
+{"Zapf Dingbats"},
+{0}};
+
+void labelfont_cb(Fl_Choice* i, void *v) {
+  if (v == LOAD) {
+    int n = current_widget->o->labelfont();
+    if (n > 15) n = 0;
+    i->value(n);
+  } else {
+    int n = i->value();
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	q->o->labelfont(n);
+	q->redraw();
+      }
+  }
+}
+
+void labelsize_cb(Fl_Value_Input* i, void *v) {
+  int n;
+  if (v == LOAD) {
+    n = current_widget->o->labelsize();
+  } else {
+    n = int(i->value());
+    if (n <= 0) n = FL_NORMAL_SIZE;
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	q->o->labelsize(n);
+	q->redraw();
+      }
+  }
+  i->value(n);
+}
+
+extern const char *ui_find_image_name;
+void image_cb(Fl_Widget *a, void *) {
+  Fluid_Image *i = ui_find_image(current_widget->label());
+  if (!ui_find_image_name) return; // user hit "Cancel"
+  // if i is zero then user picked a non-existent file.  So that the
+  // directory they chose is preserved, we change to a normal text label.
+  for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+    if (o->selected && o->is_widget()) {
+    Fl_Widget_Type* p = (Fl_Widget_Type*)o;
+    dont_touch_image = 1;
+    p->setimage(i);
+    p->label(ui_find_image_name);
+    dont_touch_image = 0;
+  }
+  label_cb(label_input,LOAD);
+  a->when(FL_WHEN_RELEASE|FL_WHEN_NOT_CHANGED);
+}
+
+Fl_Menu_Item labeltypemenu[] = {
+  {"Image...",0,image_cb,(void*)(-1)},
+  {"NORMAL_LABEL",0,0,(void*)0},
+  {"SYMBOL_LABEL",0,0,(void*)FL_SYMBOL_LABEL},
+  {"SHADOW_LABEL",0,0,(void*)FL_SHADOW_LABEL},
+  {"ENGRAVED_LABEL",0,0,(void*)FL_ENGRAVED_LABEL},
+  {"EMBOSSED_LABEL",0,0,(void*)FL_EMBOSSED_LABEL},
+  {"NO_LABEL",0,0,(void*)(FL_NO_LABEL)},
+{0}};
+
+void labeltype_cb(Fl_Choice* i, void *v) {
+  if (v == LOAD) {
+    int n;
+    if (current_widget->image) {
+      n = -1;
+      i->when(FL_WHEN_RELEASE|FL_WHEN_NOT_CHANGED);
+    } else {
+      n = current_widget->o->labeltype();
+      i->when(FL_WHEN_RELEASE);
+    }
+    for (int j = 0; j < int(sizeof(labeltypemenu)/sizeof(*labeltypemenu)); j++)
+      if (labeltypemenu[j].argument() == n) {i->value(j); break;}
+  } else {
+    int m = i->value();
+    int n = int(labeltypemenu[m].argument());
+    if (n<0) return; // should not happen
+    if (current_widget->image) label_input->activate();
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+      Fl_Widget_Type* p = (Fl_Widget_Type*)o;
+      if (p->image) {
+	p->setimage(0);
+	p->o->label(p->label());
+      }
+      p->o->labeltype((Fl_Labeltype)n);
+      p->redraw();
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+void color_cb(Fl_Button* i, void *v) {
+  Fl_Color c = current_widget->o->color();
+  if (v == LOAD) {
+    if (current_widget->is_menu_item()) {i->hide(); return;} else i->show();
+  } else {
+    Fl_Color d = fl_show_colormap(c);
+    if (d == c) return;
+    c = d;
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	q->o->color(c); q->o->redraw();
+    }
+  }
+  i->color(c); i->labelcolor(contrast(FL_BLACK,c)); i->redraw();
+}
+
+void color2_cb(Fl_Button* i, void *v) {
+  Fl_Color c = current_widget->o->selection_color();
+  if (v == LOAD) {
+    if (current_widget->is_menu_item()) {i->hide(); return;} else i->show();
+  } else {
+    Fl_Color d = fl_show_colormap(c);
+    if (d == c) return;
+    c = d;
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	q->o->selection_color(c); q->o->redraw();
+    }
+  }
+  i->color(c); i->labelcolor(contrast(FL_BLACK,c)); i->redraw();
+}
+
+void labelcolor_cb(Fl_Button* i, void *v) {
+  Fl_Color c = current_widget->o->labelcolor();
+  if (v != LOAD) {
+    Fl_Color d = fl_show_colormap(c);
+    if (d == c) return;
+    c = d;
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	q->o->labelcolor(c); q->redraw();
+    }
+  }
+  i->color(c); i->labelcolor(contrast(FL_BLACK,c)); i->redraw();
+}
+
+static Fl_Button* relative(Fl_Widget* o, int i) {
+  Fl_Group* g = (Fl_Group*)(o->parent());
+  return (Fl_Button*)(g->child(g->find(*o)+i));
+}
+
+void align_cb(Fl_Button* i, void *v) {
+  int b = int(long(i->user_data()));
+  if (v == LOAD) {
+    if (current_widget->is_menu_item()) {i->hide(); return;} else i->show();
+    i->value(current_widget->o->align() & b);
+  } else {
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+      int x = q->o->align();
+      int y;
+      if (i->value()) {
+	y = x | b;
+	if (b == FL_ALIGN_LEFT || b == FL_ALIGN_TOP) {
+	  Fl_Button *b1 = relative(i,+1);
+	  b1->clear();
+	  y = y & ~(b1->argument());
+	}
+	if (b == FL_ALIGN_RIGHT || b == FL_ALIGN_BOTTOM) {
+	  Fl_Button *b1 = relative(i,-1);
+	  b1->clear();
+	  y = y & ~(b1->argument());
+	}
+      } else {
+	y = x & ~b;
+      }
+      if (x != y) {q->o->align(y); q->redraw();}
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+void callback_cb(Fl_Input* i, void *v) {
+  if (v == LOAD) {
+    i->static_value(current_widget->callback());
+  } else {
+    const char *c = i->value();
+    const char *d = c_check(c);
+    if (d) {fl_show_message("Error in callback:",d,0); haderror = 1; return;}
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected) {
+      o->callback(c);
+    }
+  }
+}
+
+void user_data_cb(Fl_Input *i, void *v) {
+  if (v == LOAD) {
+    i->static_value(current_widget->user_data());
+  } else {
+    const char *c = i->value();
+    const char *d = c_check(c);
+    if (d) {fl_show_message("Error in user_data:",d,0); haderror = 1; return;}
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected) {
+      o->user_data(c);
+    }
+  }
+}
+
+void user_data_type_cb(Fl_Input *i, void *v) {
+  static const char *dflt = "void*";
+  if (v == LOAD) {
+    const char *c = current_widget->user_data_type();
+    if (!c) c = dflt;
+    i->static_value(c);
+  } else {
+    const char *c = i->value();
+    if (!*c) i->value(dflt);
+    else if (!strcmp(c,dflt)) c = 0;
+    const char *d = c_check(c);
+    if (!d) {
+      if (c && *c && c[strlen(c)-1] != '*' && strcmp(c,"long"))
+	d = "must be pointer or long";
+    }
+    if (d) {fl_show_message("Error in type:",d,0); haderror = 1; return;}
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected) {
+      o->user_data_type(c);
+    }
+  }
+}
+
+// "v_attributes" let user type in random code for attribute settings:
+
+void v_input_cb(Fl_Input* i, void* v) {
+  int n = int(long(i->user_data()));
+  if (v == LOAD) {
+    i->static_value(current_widget->extra_code(n));
+  } else {
+    const char *c = i->value();
+    const char *d = c_check(c&&c[0]=='#' ? c+1 : c);
+    if (d) {fl_show_message("Error in",i->label(),d); haderror = 1; return;}
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type *t = (Fl_Widget_Type*)o;
+	t->extra_code(n,c);
+      }
+  }
+}
+
+void subclass_cb(Fl_Input* i, void* v) {
+  if (v == LOAD) {
+    if (current_widget->is_menu_item()) {i->hide(); return;} else i->show();
+    i->static_value(current_widget->subclass());
+  } else {
+    const char *c = i->value();
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type *t = (Fl_Widget_Type*)o;
+	t->subclass(c);
+      }
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+// textstuff: set textfont, textsize, textcolor attributes:
+
+// default widget returns 0 to indicate not-implemented:
+int Fl_Widget_Type::textstuff(int, Fl_Font&, int&, Fl_Color&) {return 0;}
+
+void textfont_cb(Fl_Choice* i, void* v) {
+  Fl_Font n; int s; Fl_Color c;
+  if (v == LOAD) {
+    if (!current_widget->textstuff(0,n,s,c)) {i->hide(); return;}
+    i->show();
+    if (n > 15) n = FL_HELVETICA;
+    i->value(n);
+  } else {
+    n = (Fl_Font)i->value();
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	q->textstuff(1,n,s,c);
+	q->o->redraw();
+      }
+  }
+}
+
+void textsize_cb(Fl_Value_Input* i, void* v) {
+  Fl_Font n; int s; Fl_Color c;
+  if (v == LOAD) {
+    if (!current_widget->textstuff(0,n,s,c)) {i->hide(); return;}
+    i->show();
+  } else {
+    s = int(i->value());
+    if (s <= 0) s = FL_NORMAL_SIZE;
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	q->textstuff(2,n,s,c);
+	q->o->redraw();
+      }
+  }
+  i->value(s);
+}
+
+void textcolor_cb(Fl_Button* i, void* v) {
+  Fl_Font n; int s; Fl_Color c;
+  if (v == LOAD) {
+    if (!current_widget->textstuff(0,n,s,c)) {i->hide(); return;}
+    i->show();
+  } else {
+    c = i->labelcolor();
+    Fl_Color d = fl_show_colormap(c);
+    if (d == c) return;
+    c = d;
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	q->textstuff(3,n,s,c); q->o->redraw();
+      }
+  }
+  i->color(c); i->labelcolor(contrast(FL_BLACK,c)); i->redraw();
+}
+
+////////////////////////////////////////////////////////////////
+// Kludges to the panel for subclasses:
+
+void slider_size_cb(Fl_Value_Input* i, void* v) {
+  if (v == LOAD) {
+    if (current_widget->is_valuator()!=2) {i->hide(); return;}
+    i->show();
+    i->value(((Fl_Slider*)(current_widget->o))->slider_size());
+  } else {
+    double n = i->value();
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	if (q->is_valuator()==2) {
+	  ((Fl_Slider*)(q->o))->slider_size(n);
+	  q->o->redraw();
+	}
+      }
+  }
+}
+
+void min_cb(Fl_Value_Input* i, void* v) {
+  if (v == LOAD) {
+    if (!current_widget->is_valuator()) {i->hide(); return;}
+    i->show();
+    i->value(((Fl_Valuator*)(current_widget->o))->minimum());
+  } else {
+    double n = i->value();
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	if (q->is_valuator()) {
+	  ((Fl_Valuator*)(q->o))->minimum(n);
+	  q->o->redraw();
+	}
+      }
+  }
+}
+
+void max_cb(Fl_Value_Input* i, void* v) {
+  if (v == LOAD) {
+    if (!current_widget->is_valuator()) {i->hide(); return;}
+    i->show();
+    i->value(((Fl_Valuator*)(current_widget->o))->maximum());
+  } else {
+    double n = i->value();
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	if (q->is_valuator()) {
+	  ((Fl_Valuator*)(q->o))->maximum(n);
+	q->o->redraw();
+	}
+      }
+  }
+}
+
+void step_cb(Fl_Value_Input* i, void* v) {
+  if (v == LOAD) {
+    if (!current_widget->is_valuator()) {i->hide(); return;}
+    i->show();
+    i->value(((Fl_Valuator*)(current_widget->o))->step());
+  } else {
+    double n = i->value();
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	if (q->is_valuator()) {
+	  ((Fl_Valuator*)(q->o))->step(n);
+	  q->o->redraw();
+	}
+      }
+  }
+}
+
+void value_cb(Fl_Value_Input* i, void* v) {
+  if (v == LOAD) {
+    if (current_widget->is_valuator()) {
+      i->show();
+      i->value(((Fl_Valuator*)(current_widget->o))->value());
+    } else if (current_widget->is_button()) {
+      i->show();
+      i->value(((Fl_Button*)(current_widget->o))->value());
+    } else 
+      i->hide();
+  } else {
+    double n = i->value();
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	if (q->is_valuator()) {
+	  ((Fl_Valuator*)(q->o))->value(n);
+	} else if (q->is_button()) {
+	  ((Fl_Button*)(q->o))->value(n != 0);
+	  if (q->is_menu_item()) q->redraw();
+	}
+      }
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+// subtypes:
+
+Fl_Menu_Item *Fl_Widget_Type::subtypes() {return 0;}
+
+void subtype_cb(Fl_Choice* i, void* v) {
+  if (v == LOAD) {
+    Fl_Menu_Item* m = current_widget->subtypes();
+    if (!m) {i->hide(); return;}
+    i->menu(m);
+    int j;
+    for (j = 0;; j++) {
+      if (!m[j].text) {j = 0; break;}
+      if (m[j].argument() == current_widget->o->type()) break;
+    }
+    i->value(j);
+    i->show();
+    i->redraw();
+  } else {
+    int n = int(i->mvalue()->argument());
+    Fl_Menu_Item* m = current_widget->subtypes();
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* q = (Fl_Widget_Type*)o;
+	if (q->subtypes()==m) {
+	  q->o->type(n);
+	  q->redraw();
+	}
+      }
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+static Fl_Window *the_panel;
+
+void propagate_load(Fl_Group* g, void* v) {
+  if (v == LOAD) {
+    Fl_Widget*const* a = g->array();
+    for (int i=g->children(); i--;) {
+      Fl_Widget* o = *a++;
+      o->do_callback(o,LOAD);
+    }
+  }
+}
+
+void set_cb(Fl_Button*, void*) {
+  haderror = 0;
+  Fl_Widget*const* a = the_panel->array();
+  for (int i=the_panel->children(); i--;) {
+    Fl_Widget* o = *a++;
+    if (o->changed()) {
+      o->do_callback();
+      if (haderror) return;
+      o->clear_changed();
+    }
+  }
+}
+
+void ok_cb(Fl_Return_Button* o, void* v) {
+  set_cb(o,v);
+  if (!haderror) the_panel->hide();
+}
+
+void revert_cb(Fl_Button*, void*) {
+  // We have to revert all dynamically changing fields:
+  // but for now only the first label works...
+  if (numselected == 1) current_widget->label(oldlabel);
+  propagate_load(the_panel, LOAD);
+}
+
+void cancel_cb(Fl_Button* o, void* v) {
+  revert_cb(o,v);
+  the_panel->hide();
+}
+
+void toggle_overlays(Fl_Widget *,void *); // in Fl_Window_Type.C
+void overlay_cb(Fl_Button*o,void *v) {
+  toggle_overlays(o,v);
+}
+
+// update the panel according to current widget set:
+static void load_panel() {
+  if (!the_panel) return;
+
+  // find all the Fl_Widget subclasses currently selected:
+  numselected = 0;
+  current_widget = 0;
+  if (Fl_Type::current) {
+    if (Fl_Type::current->is_widget())
+      current_widget=(Fl_Widget_Type*)Fl_Type::current;
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
+      if (o->is_widget() && o->selected) {
+	numselected++;
+	if (!current_widget) current_widget = (Fl_Widget_Type*)o;
+      }
+    }
+  }
+  if (numselected)
+    propagate_load(the_panel, LOAD);
+  else
+    the_panel->hide();
+}
+
+// This is called when user double-clicks an item, open or update the panel:
+void Fl_Widget_Type::open() {
+  if (!the_panel) the_panel = make_widget_panel();
+  load_panel();
+  if (numselected) the_panel->show();
+}
+
+Fl_Type *Fl_Type::current;
+
+extern void redraw_overlays();
+extern void redraw_browser();
+
+// Called when ui changes what objects are selected:
+// p is selected object, null for all deletions (we must throw away
+// old panel in that case, as the object may no longer exist)
+void selection_changed(Fl_Type *p) {
+  // store all changes to the current selected objects:
+  if (p && the_panel && the_panel->visible()) {
+    set_cb(0,0);
+    // if there was an error, we try to leave the selected set unchanged:
+    if (haderror) {
+      Fl_Type *q = 0;
+      for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
+	o->new_selected = o->selected;
+	if (!q && o->selected) q = o;
+      }
+      if (!p || !p->selected) p = q;
+      Fl_Type::current = p;
+      redraw_browser();
+      return;
+    }
+  }
+  // update the selected flags to new set:
+  Fl_Type *q = 0;
+  for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
+    o->selected = o->new_selected;
+    if (!q && o->selected) q = o;
+  }
+  if (!p || !p->selected) p = q;
+  Fl_Type::current = p;
+  redraw_overlays();
+  // load the panel with the new settings:
+  load_panel();
+}
+
+////////////////////////////////////////////////////////////////
+// Writing the C code:
+
+#include 
+
+// test to see if user named a function, or typed in code:
+int is_name(const char *c) {
+  for (; *c; c++) if (ispunct(*c) && *c!='_') return 0;
+  return 1;
+}
+
+// Test to see if name() is an array entry.  If so, and this is the
+// highest number, return name[num+1].  Return null if not the highest
+// number or a field or function.  Return name() if not an array entry.
+const char *array_name(Fl_Widget_Type *o) {
+  const char *c = o->name();
+  if (!c) return 0;
+  const char *d;
+  for (d = c; *d != '['; d++) {
+    if (!*d) return c;
+    if (ispunct(*d) && *d!='_') return 0;
+  }
+  int num = atoi(d+1);
+  int sawthis = 0;
+  for (Fl_Type *t = Fl_Type::first; t; t = t->next) {
+    if (t == o) {sawthis=1; continue;}
+    const char *e = t->name();
+    if (!e) continue;
+    if (strncmp(c,e,d-c)) continue;
+    int n1 = atoi(e+(d-c)+1);
+    if (n1 > num || n1==num && sawthis) return 0;
+  }
+  static char buffer[128];
+  strncpy(buffer,c,d-c+1);
+  sprintf(buffer+(d-c+1),"%d]",num+1);
+  return buffer;
+}
+
+// Test to see if extra code is a declaration:
+int isdeclare(const char *c) {
+  while (isspace(*c)) c++;
+  if (*c == '#') return 1;
+  if (!strncmp(c,"extern",6)) return 1;
+  return 0;
+}
+
+void Fl_Widget_Type::write_declare() {
+  const char *t = subclassname(this);
+  if (!subclass()) ::write_declare("#include ", t);
+  if (callback() && is_name(callback()))
+    ::write_declare("extern void %s(%s*, %s);", callback(), t,
+		    user_data_type() ? user_data_type() : "void*");
+  for (int n=0; n < NUM_EXTRA_CODE; n++) {
+    if (extra_code(n) && isdeclare(extra_code(n)))
+      ::write_declare("%s", extra_code(n));
+  }
+}
+
+void Fl_Widget_Type::write_static() {
+  const char* t = subclassname(this);
+  const char* c = array_name(this);
+  const char* k = class_name();
+  if (c && !k) {
+    write_c("\n");
+    if (!public_) write_c("static ");
+    else write_h("extern %s *%s;\n", t, c);
+    write_c("%s *%s;\n", t, c);
+  }
+  if (callback() && !is_name(callback())) {
+    // see if 'o' or 'v' used, to prevent unused argument warnings:
+    int use_o = 0;
+    int use_v = 0;
+    const char *d;
+    for (d = callback(); *d;) {
+      if (*d == 'o' && !is_id(d[1])) use_o = 1;
+      if (*d == 'v' && !is_id(d[1])) use_v = 1;
+      do d++; while (is_id(*d));
+      while (*d && !is_id(*d)) d++;
+    }
+    const char* cn = callback_name();
+    if (k) {
+      write_c("\ninline void %s::%s_i(%s*", k, cn, t);
+    } else {
+      write_c("\nstatic void %s(%s*", cn, t);
+    }
+    if (use_o) write_c(" o");
+    const char* ut = user_data_type() ? user_data_type() : "void*";
+    write_c(", %s", ut);
+    if (use_v) write_c(" v");
+    write_c(") {\n  %s", callback());
+    if (*(d-1) != ';') write_c(";");
+    write_c("\n}\n");
+    if (k) {
+      write_c("void %s::%s(%s* o, %s v) {\n", k, cn, t, ut);
+      write_c("  ((%s*)(o->", k);
+      for (Fl_Type* p = parent; p->is_widget(); p = p->parent)
+	write_c("parent()->");
+      write_c("user_data()))->%s_i(o,v);\n}\n", cn);
+    }
+  }
+  if (image) {
+    if (image->written != write_number) {
+      image->write_static();
+      image->written = write_number;
+    }
+  }
+}
+
+const char *Fl_Type::callback_name() {
+  if (is_name(callback())) return callback();
+  return unique_id(this, "cb", name(), label());
+}
+
+extern int varused_test, varused;
+  
+void Fl_Widget_Type::write_code1() {
+  const char* t = subclassname(this);
+  const char *c = array_name(this);
+  if (c) {
+    if (class_name()) {
+      write_public(public_);
+      write_h("  %s *%s;\n", t, c);
+    } else if (!public_)
+      write_h("extern %s *%s;\n", t, c);
+  }
+  if (class_name() && callback() && !is_name(callback())) {
+    const char* cn = callback_name();
+    const char* ut = user_data_type() ? user_data_type() : "void*";
+    write_public(0);
+    write_h("  inline void %s_i(%s*, %s);\n", cn, t, ut);
+    write_h("  static void %s(%s*, %s);\n", cn, t, ut);
+  }
+  // figure out if local varaible will be used (prevent compiler warnings):
+  if (is_parent())
+    varused = 1;
+  else {
+    varused_test = 1; varused = 0;
+    write_widget_code();
+    varused_test = 0;
+    for (int n=0; n < NUM_EXTRA_CODE; n++)
+      if (extra_code(n) && !isdeclare(extra_code(n))) varused = 1;
+  }
+  write_c(indent());
+  if (varused) write_c("{ %s* o = ", t);
+  if (name()) write_c("%s = ", name());
+  if (is_window()) {
+    write_c("w = new %s(%d, %d", t, o->w(), o->h());
+    // prevent type() code from being emitted:
+    ((Fl_Widget_Type*)factory)->o->type(o->type());
+  } else {
+    write_c("new %s(%d, %d, %d, %d", t, o->x(), o->y(), o->w(), o->h());
+  }
+  if (!image && label() && *label()) {
+    write_c(", ");
+    write_cstring(label());
+  }
+  write_c(");\n");
+  indentation += 2;
+  if (varused) write_widget_code();
+}
+
+// this is split from write_code1() for Fl_Window_Type:
+void Fl_Widget_Type::write_widget_code() {
+  Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o;
+  if (o->type() != tplate->type())
+    write_c("%so->type(%d);\n", indent(), o->type());
+  if (o->box() != tplate->box())
+    write_c("%so->box(FL_%s);\n", indent(), boxname(o->box()));
+  if (is_button()) {
+    Fl_Button* b = (Fl_Button*)o;
+    if (b->down_box()) write_c("%so->down_box(FL_%s);\n", indent(),
+			       boxname(b->down_box()));
+    if (b->value()) write_c("%so->value(1);\n", indent());
+    if (b->shortcut())
+      write_c("%so->shortcut(0x%x);\n", indent(), b->shortcut());
+  }
+  if (is_menu_button()) {
+    Fl_Menu_* b = (Fl_Menu_*)o;
+    if (b->down_box()) write_c("%so->down_box(FL_%s);\n", indent(),
+			       boxname(b->down_box()));
+  }
+  if (o->color() != tplate->color())
+    write_c("%so->color(%d);\n", indent(), o->color());
+  if (o->selection_color() != tplate->selection_color())
+    write_c("%so->selection_color(%d);\n", indent(), o->selection_color());
+  if (image)
+    image->write_code();
+  else if (o->labeltype() != tplate->labeltype())
+    write_c("%so->labeltype(FL_%s);\n", indent(),
+	    item_name(labeltypemenu, o->labeltype()));
+  if (o->labelfont() != tplate->labelfont())
+    write_c("%so->labelfont(%d);\n", indent(), o->labelfont());
+  if (o->labelsize() != tplate->labelsize())
+    write_c("%so->labelsize(%d);\n", indent(), o->labelsize());
+  if (o->labelcolor() != tplate->labelcolor())
+    write_c("%so->labelcolor(%d);\n", indent(), o->labelcolor());
+  if (is_valuator()) {
+    Fl_Valuator* v = (Fl_Valuator*)o;
+    Fl_Valuator* f = (Fl_Valuator*)(tplate);
+    if (v->minimum()!=f->minimum())
+      write_c("%so->minimum(%g);\n", indent(), v->minimum());
+    if (v->maximum()!=f->maximum())
+      write_c("%so->maximum(%g);\n", indent(), v->maximum());
+    if (v->step()!=f->step())
+      write_c("%so->step(%g);\n", indent(), v->step());
+    if (v->value())
+      write_c("%so->value(%g);\n", indent(), v->value());
+    if (is_valuator()==2) {
+      double x = ((Fl_Slider*)v)->slider_size();
+      double y = ((Fl_Slider*)f)->slider_size();
+      if (x != y) write_c("%so->slider_size(%g);\n", indent(), x);
+    }
+  }
+  {Fl_Font ff; int fs; Fl_Color fc; if (textstuff(4,ff,fs,fc)) {
+    Fl_Font f; int s; Fl_Color c; textstuff(0,f,s,c);
+    if (f != ff) write_c("%so->textfont(%d);\n", indent(), f);
+    if (s != fs) write_c("%so->textsize(%d);\n", indent(), s);
+    if (c != fc) write_c("%so->textcolor(%d);\n",indent(), c);
+  }}
+  const char* ud = user_data();
+  if (class_name() && !parent->is_widget()) ud = "this";
+  if (callback()) {
+    write_c("%so->callback((Fl_Callback*)%s", indent(), callback_name());
+    if (ud)
+      write_c(", (void*)(%s));\n", ud);
+    else
+      write_c(");\n");
+  } else if (ud) {
+    write_c("%so->user_data((void*)(%s));\n", indent(), ud);
+  }
+  if (o->align() != tplate->align())
+    write_c("%so->align(%d);\n", indent(), o->align());
+  if (o->when() != tplate->when())
+    write_c("%so->when(%d);\n", indent(), o->when());
+  if (!o->visible() && o->parent())
+    write_c("%so->hide();\n", indent());
+  if (!o->active())
+    write_c("%so->deactivate();\n", indent());
+  if (!is_group() && resizable())
+    write_c("%sFl_Group::current()->resizable(o);\n",indent());
+  if (hotspot())
+    write_c("%sw->hotspot(o);\n", indent());
+}
+
+void Fl_Widget_Type::write_code2() {
+  indentation -= 2;
+  if (!is_parent() && !varused) return;
+  for (int n=0; n < NUM_EXTRA_CODE; n++)
+    if (extra_code(n) && !isdeclare(extra_code(n)))
+      write_c("%s  %s\n", indent(), extra_code(n));
+  write_c("%s}\n", indent());
+}
+
+////////////////////////////////////////////////////////////////
+
+void Fl_Widget_Type::write_properties() {
+  Fl_Type::write_properties();
+  write_indent(level+1);
+  if (!public_) write_string("private");
+  write_string("xywh {%d %d %d %d}", o->x(), o->y(), o->w(), o->h());
+  Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o;
+  if (o->type() != tplate->type()) {
+    write_string("type");
+    write_word(item_name(subtypes(), o->type()));
+  }
+  if (o->box() != tplate->box()) {
+    write_string("box"); write_word(boxname(o->box()));}
+  if (is_button()) {
+    Fl_Button* b = (Fl_Button*)o;
+    if (b->down_box()) {
+      write_string("down_box"); write_word(boxname(b->down_box()));}
+    if (b->shortcut()) write_string("shortcut 0x%x", b->shortcut());
+    if (b->value()) write_string("value 1");
+  }
+  if (is_menu_button()) {
+    Fl_Menu_* b = (Fl_Menu_*)o;
+    if (b->down_box()) {
+      write_string("down_box"); write_word(boxname(b->down_box()));}
+  }
+  if (o->color()!=tplate->color())
+    write_string("color %d", o->color());
+  if (o->selection_color()!=tplate->selection_color())
+    write_string("selection_color %d", o->selection_color());
+  if (image)
+    write_string("labeltype image");
+  else if (o->labeltype()!=tplate->labeltype()) {
+    write_string("labeltype");
+    write_word(item_name(labeltypemenu, o->labeltype()));
+  }
+  if (o->labelfont()!=tplate->labelfont())
+    write_string("labelfont %d", o->labelfont());
+  if (o->labelsize()!=tplate->labelsize())
+    write_string("labelsize %d", o->labelsize());
+  if (o->labelcolor()!=tplate->labelcolor())
+    write_string("labelcolor %d", o->labelcolor());
+  if (o->align()!=tplate->align())
+    write_string("align %d", o->align());
+  if (o->when() != tplate->when())
+    write_string("when %d", o->when());
+  if (is_valuator()) {
+    Fl_Valuator* v = (Fl_Valuator*)o;
+    Fl_Valuator* f = (Fl_Valuator*)(tplate);
+    if (v->minimum()!=f->minimum()) write_string("minimum %g",v->minimum());
+    if (v->maximum()!=f->maximum()) write_string("maximum %g",v->maximum());
+    if (v->step()!=f->step()) write_string("step %g",v->step());
+    if (v->value()!=0.0) write_string("value %g",v->value());
+    if (is_valuator()==2) {
+      double x = ((Fl_Slider*)v)->slider_size();
+      double y = ((Fl_Slider*)f)->slider_size();
+      if (x != y) write_string("slider_size %g", x);
+    }
+  }
+  {Fl_Font ff; int fs; Fl_Color fc; if (textstuff(4,ff,fs,fc)) {
+    Fl_Font f; int s; Fl_Color c; textstuff(0,f,s,c);
+    if (f != ff) write_string("textfont %d", f);
+    if (s != fs) write_string("textsize %d", s);
+    if (c != fc) write_string("textcolor %d", c);
+  }}
+  if (!o->visible()) write_string("hide");
+  if (!o->active()) write_string("deactivate");
+  if (resizable()) write_string("resizable");
+  if (hotspot()) write_string(is_menu_item() ? "divider" : "hotspot");
+  for (int n=0; n < NUM_EXTRA_CODE; n++) if (extra_code(n)) {
+    write_indent(level+1);
+    write_string("code%d",n);
+    write_word(extra_code(n));
+  }
+  if (subclass()) {
+    write_indent(level+1);
+    write_string("class");
+    write_word(subclass());
+  }
+}
+
+int pasteoffset;
+
+void Fl_Widget_Type::read_property(const char *c) {
+  int x,y,w,h; Fl_Font f; int s; Fl_Color cc;
+  if (!strcmp(c,"private")) {
+    public_ = 0;
+  } else if (!strcmp(c,"xywh")) {
+    if (sscanf(read_word(),"%d %d %d %d",&x,&y,&w,&h) == 4) {
+      x += pasteoffset;
+      y += pasteoffset;
+      o->resize(x,y,w,h);
+    }
+  } else if (!strcmp(c,"type")) {
+    o->type(item_number(subtypes(), read_word()));
+  } else if (!strcmp(c,"box")) {
+    const char* value = read_word();
+    if ((x = boxnumber(value))) {
+      if (x == ZERO_ENTRY) x = 0;
+      o->box((Fl_Boxtype)x);
+    } else if (sscanf(value,"%d",&x) == 1) o->box((Fl_Boxtype)x);
+  } else if (is_button() && !strcmp(c,"down_box")) {
+    const char* value = read_word();
+    if ((x = boxnumber(value))) {
+      if (x == ZERO_ENTRY) x = 0;
+      ((Fl_Button*)o)->down_box((Fl_Boxtype)x);
+    }
+  } else if (is_menu_button() && !strcmp(c,"down_box")) {
+    const char* value = read_word();
+    if ((x = boxnumber(value))) {
+      if (x == ZERO_ENTRY) x = 0;
+      ((Fl_Menu_*)o)->down_box((Fl_Boxtype)x);
+    }
+  } else if (is_button() && !strcmp(c,"value")) {
+    const char* value = read_word();
+    ((Fl_Button*)o)->value(atoi(value));
+  } else if (!strcmp(c,"color")) {
+    int n = sscanf(read_word(),"%d %d",&x,&y);
+    if (n == 2) { // back compatability...
+      if (x != 47) o->color(x);
+      o->selection_color(y);
+    } else {
+      o->color(x);
+    }
+  } else if (!strcmp(c,"selection_color")) {
+    if (sscanf(read_word(),"%d",&x)) o->selection_color(x);
+  } else if (!strcmp(c,"labeltype")) {
+    c = read_word();
+    if (!strcmp(c,"image")) {
+      Fluid_Image *i = Fluid_Image::find(label());
+      if (!i) read_error("Image file '%s' not found", label());
+      else setimage(i);
+    } else {
+      o->labeltype((Fl_Labeltype)item_number(labeltypemenu,c));
+    }
+  } else if (!strcmp(c,"labelfont")) {
+    if (sscanf(read_word(),"%d",&x) == 1) o->labelfont(x);
+  } else if (!strcmp(c,"labelsize")) {
+    if (sscanf(read_word(),"%d",&x) == 1) o->labelsize(x);
+  } else if (!strcmp(c,"labelcolor")) {
+    if (sscanf(read_word(),"%d",&x) == 1) o->labelcolor(x);
+  } else if (!strcmp(c,"align")) {
+    if (sscanf(read_word(),"%d",&x) == 1) o->align(x);
+  } else if (!strcmp(c,"when")) {
+    if (sscanf(read_word(),"%d",&x) == 1) o->when(x);
+  } else if (!strcmp(c,"minimum") && is_valuator()) {
+    ((Fl_Valuator*)o)->minimum(strtod(read_word(),0));
+  } else if (!strcmp(c,"maximum") && is_valuator()) {
+    ((Fl_Valuator*)o)->maximum(strtod(read_word(),0));
+  } else if (!strcmp(c,"step") && is_valuator()) {
+    ((Fl_Valuator*)o)->step(strtod(read_word(),0));
+  } else if (!strcmp(c,"value") && is_valuator()) {
+    ((Fl_Valuator*)o)->value(strtod(read_word(),0));
+  } else if ((!strcmp(c,"slider_size")||!strcmp(c,"size"))&&is_valuator()==2) {
+    ((Fl_Slider*)o)->slider_size(strtod(read_word(),0));
+  } else if (!strcmp(c,"textfont")) {
+    if (sscanf(read_word(),"%d",&x) == 1) {f=(Fl_Font)x; textstuff(1,f,s,cc);}
+  } else if (!strcmp(c,"textsize")) {
+    if (sscanf(read_word(),"%d",&x) == 1) {s=x; textstuff(2,f,s,cc);}
+  } else if (!strcmp(c,"textcolor")) {
+    if (sscanf(read_word(),"%d",&x) == 1) {cc=(Fl_Color)x;textstuff(3,f,s,cc);}
+  } else if (!strcmp(c,"hide")) {
+    o->hide();
+  } else if (!strcmp(c,"deactivate")) {
+    o->deactivate();
+  } else if (!strcmp(c,"resizable")) {
+    resizable(1);
+  } else if (!strcmp(c,"hotspot") || !strcmp(c, "divider")) {
+    hotspot(1);
+  } else if (!strcmp(c,"class")) {
+    subclass(read_word());
+  } else if (is_button() && !strcmp(c,"shortcut")) {
+    ((Fl_Button*)o)->shortcut(strtol(read_word(),0,0));
+  } else {
+    if (!strncmp(c,"code",4)) {
+      int n = atoi(c+4);
+      if (n >= 0 && n <= NUM_EXTRA_CODE) {
+	extra_code(n,read_word());
+	return;
+      }
+    }
+    Fl_Type::read_property(c);
+  }
+}
+
+Fl_Menu_Item boxmenu1[] = {
+  // these extra ones are for looking up fdesign saved strings:
+  {"NO_FRAME",		0,0,(void *)FL_NO_BOX},
+  {"ROUNDED3D_UPBOX",	0,0,(void *)_FL_ROUND_UP_BOX},
+  {"ROUNDED3D_DOWNBOX",	0,0,(void *)_FL_ROUND_DOWN_BOX},
+  {"OVAL3D_UPBOX",	0,0,(void *)_FL_ROUND_UP_BOX},
+  {"OVAL3D_DOWNBOX",	0,0,(void *)_FL_ROUND_DOWN_BOX},
+  {"0",			0,0,(void *)ZERO_ENTRY},
+  {"1",			0,0,(void *)FL_UP_BOX},
+  {"2",			0,0,(void *)FL_DOWN_BOX},
+  {"3",			0,0,(void *)FL_FLAT_BOX},
+  {"4",			0,0,(void *)FL_BORDER_BOX},
+  {"5",			0,0,(void *)FL_SHADOW_BOX},
+  {"6",			0,0,(void *)FL_FRAME_BOX},
+  {"7",			0,0,(void *)FL_ROUNDED_BOX},
+  {"8",			0,0,(void *)FL_RFLAT_BOX},
+  {"9",			0,0,(void *)FL_RSHADOW_BOX},
+  {"10",		0,0,(void *)FL_UP_FRAME},
+  {"11",		0,0,(void *)FL_DOWN_FRAME},
+{0}};
+
+extern int fdesign_flip;
+int lookup_symbol(const char *, int &, int numberok = 0);
+
+int Fl_Widget_Type::read_fdesign(const char* name, const char* value) {
+  int v;
+  if (!strcmp(name,"box")) {
+    float x,y,w,h;
+    if (sscanf(value,"%f %f %f %f",&x,&y,&w,&h) == 4) {
+      if (fdesign_flip) {
+	Fl_Type *p;
+	for (p = parent; p && !p->is_window(); p = p->parent);
+	if (p && p->is_widget()) y = ((Fl_Widget_Type*)p)->o->h()-(y+h);
+      }	  
+      x += pasteoffset;
+      y += pasteoffset;
+      o->resize(int(x),int(y),int(w),int(h));
+    }
+  } else if (!strcmp(name,"label")) {
+    label(value);
+    if (value[0] == '@') o->labeltype(FL_SYMBOL_LABEL);
+  } else if (!strcmp(name,"name")) {
+    this->name(value);
+  } else if (!strcmp(name,"callback")) {
+    callback(value); user_data_type("long");
+  } else if (!strcmp(name,"argument")) {
+    user_data(value);
+  } else if (!strcmp(name,"shortcut")) {
+    if (value[0]) {
+      char buf[128]; sprintf(buf,"o->shortcut(\"%s\");",value);
+      extra_code(0,buf);
+    }
+  } else if (!strcmp(name,"style")) {
+    if (!strncmp(value,"FL_NORMAL",9)) return 1;
+    if (!lookup_symbol(value,v,1)) return 0;
+    o->labelfont(v); o->labeltype((Fl_Labeltype)(v>>8));
+  } else if (!strcmp(name,"size")) {
+    if (!lookup_symbol(value,v,1)) return 0;
+    o->labelsize(v);
+  } else if (!strcmp(name,"type")) {
+    if (!strncmp(value,"NORMAL",6)) return 1;
+    if (lookup_symbol(value,v,1)) {o->type(v); return 1;}
+    if (!strcmp(value+strlen(value)-5,"FRAME")) goto TRY_BOXTYPE;
+    if (!strcmp(value+strlen(value)-3,"BOX")) goto TRY_BOXTYPE;
+    return 0;
+  } else if (!strcmp(name,"lcol")) {
+    if (!lookup_symbol(value,v,1)) return 0;
+    o->labelcolor(v);
+  } else if (!strcmp(name,"return")) {
+    if (!lookup_symbol(value,v,0)) return 0;
+    o->when(v|FL_WHEN_RELEASE);
+  } else if (!strcmp(name,"alignment")) {
+    if (!lookup_symbol(value,v)) {
+      // convert old numeric values:
+      int v1 = atoi(value); if (v1 <= 0 && strcmp(value,"0")) return 0;
+      v = 0;
+      if (v1 >= 5) {v = FL_ALIGN_INSIDE; v1 -= 5;}
+      switch (v1) {
+      case 0: v += FL_ALIGN_TOP; break;
+      case 1: v += FL_ALIGN_BOTTOM; break;
+      case 2: v += FL_ALIGN_LEFT; break;
+      case 3: v += FL_ALIGN_RIGHT; break;
+      case 4: v += FL_ALIGN_CENTER; break;
+      default: return 0;
+      }
+    }
+    o->align(v);
+  } else if (!strcmp(name,"resizebox")) {
+    resizable(1);
+  } else if (!strcmp(name,"colors")) {
+    char* p = (char*)value;
+    while (*p != ' ') {if (!*p) return 0; p++;}
+    *p = 0;
+    int v1;
+    if (!lookup_symbol(value,v,1) || !lookup_symbol(p+1,v1,1)) {
+      *p=' '; return 0;}
+    o->color(v,v1);
+  } else if (!strcmp(name,"resize")) {
+    return !strcmp(value,"FL_RESIZE_ALL");
+  } else if (!strcmp(name,"gravity")) {
+    return !strcmp(value,"FL_NoGravity FL_NoGravity");
+  } else if (!strcmp(name,"boxtype")) {
+  TRY_BOXTYPE:
+    int x = boxnumber(value);
+    if (!x) {x = item_number(boxmenu1, value); if (x < 0) return 0;}
+    if (x == ZERO_ENTRY) {
+      x = 0;
+      if (o->box() != ((Fl_Widget_Type*)factory)->o->box()) return 1; // kludge for frame
+    }
+    o->box((Fl_Boxtype)x);
+  } else {
+    return 0;
+  }
+  return 1;
+}
diff --git a/fluid/Fl_Widget_Type.h b/fluid/Fl_Widget_Type.h
new file mode 100644
index 000000000..c911054fa
--- /dev/null
+++ b/fluid/Fl_Widget_Type.h
@@ -0,0 +1,67 @@
+// Fl_Widget_Type.H
+
+// Type for creating all subclasses of Fl_Widget
+// This should have the widget pointer in it, but it is still in the
+// Fl_Type base class.
+
+#include "Fl_Type.H"
+
+struct Fl_Menu_Item;
+class Fluid_Image;
+
+#define NUM_EXTRA_CODE 4
+
+class Fl_Widget_Type : public Fl_Type {
+  virtual Fl_Widget *widget(int,int,int,int) = 0;
+  virtual Fl_Widget_Type *_make() = 0; // virtual constructor
+  virtual void setlabel(const char *);
+
+  const char *extra_code_[NUM_EXTRA_CODE];
+  const char *subclass_;
+  uchar hotspot_;
+
+protected:
+
+  void write_declare();
+  void write_static();
+  void write_code1();
+  void write_widget_code();
+  void write_code2();
+
+public:
+
+  const char *xclass; // junk string, used for shortcut
+  Fl_Widget *o;
+  int public_;
+
+  Fluid_Image *image;
+  void setimage(Fluid_Image *);
+
+  Fl_Widget_Type();
+  Fl_Type *make();
+  void open();
+
+  const char *extra_code(int n) const {return extra_code_[n];}
+  void extra_code(int n,const char *);
+  const char *subclass() const {return subclass_;}
+  void subclass(const char *);
+  uchar hotspot() const {return hotspot_;}
+  void hotspot(uchar v) {hotspot_ = v;}
+  uchar resizable() const;
+  void resizable(uchar v);
+
+  virtual int textstuff(int what, Fl_Font &, int &, Fl_Color &);
+  virtual Fl_Menu_Item *subtypes();
+
+  virtual int is_widget() const;
+
+  virtual void write_properties();
+  virtual void read_property(const char *);
+  virtual int read_fdesign(const char*, const char*);
+
+  ~Fl_Widget_Type();
+  void redraw();
+};
+
+void* const LOAD = (void *)9831;
+extern Fl_Widget_Type *current_widget; // one of the selected ones
diff --git a/fluid/Fl_Window_Type.cxx b/fluid/Fl_Window_Type.cxx
new file mode 100644
index 000000000..044c8233f
--- /dev/null
+++ b/fluid/Fl_Window_Type.cxx
@@ -0,0 +1,666 @@
+/*	Fl_Window_Type.C
+
+	The widget describing an Fl_Window.  This is also all the code
+	for interacting with the overlay, which allows the user to
+	select, move, and resize the children widgets.
+
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "Fl_Widget_Type.H"
+#include 
+#include 
+#include "alignment_panel.H"
+#include 
+
+int gridx = 5;
+int gridy = 5;
+int snap = 3;
+
+void alignment_cb(Fl_Input *i, long v) {
+  int n = atoi(i->value());
+  if (n < 0) n = 0;
+  switch (v) {
+  case 1: gridx = n; break;
+  case 2: gridy = n; break;
+  case 3: snap  = n; break;
+  }
+}
+
+extern const char* header_file_name;
+extern const char* code_file_name;
+
+void show_alignment_cb(Fl_Widget *, void *) {
+  make_alignment_window();
+  header_file_input->value(header_file_name);
+  code_file_input->value(code_file_name);
+  char buf[128];
+  sprintf(buf,"%d",gridx); horizontal_input->value(buf);
+  sprintf(buf,"%d",gridy); vertical_input->value(buf);
+  sprintf(buf,"%d",snap); snap_input->value(buf);
+  alignment_window->show();
+}
+
+void header_input_cb(Fl_Input* i, void*) {
+  header_file_name = i->value();
+}
+void code_input_cb(Fl_Input* i, void*) {
+  code_file_name = i->value();
+  printf("code file name set to %s\n", code_file_name);
+}
+
+////////////////////////////////////////////////////////////////
+
+static Fl_Menu_Item window_type_menu[] = {
+  {"Single",0,0,(void*)FL_WINDOW},
+  {"Double",0,0,(void*)(FL_WINDOW+1)},
+  {0}};
+class Fl_Window_Type : public Fl_Widget_Type {
+  Fl_Menu_Item* subtypes() {return window_type_menu;}
+
+  friend class Overlay_Window;
+  int mx,my;		// mouse position during dragging
+  int x1,y1;		// initial position of selection box
+  int bx,by,br,bt;	// bounding box of selection
+  int dx,dy;
+  int drag;		// which parts of bbox are being moved
+  int numselected;	// number of children selected
+  enum {LEFT=1,RIGHT=2,BOTTOM=4,TOP=8,DRAG=16,BOX=32};
+  void draw_overlay();
+  void newdx();
+  void newposition(Fl_Widget_Type *,int &x,int &y,int &w,int &h);
+  int handle(int);
+  virtual void setlabel(const char *);
+  void write_code1();
+  void write_code2();
+  Fl_Widget_Type *_make() {return 0;} // we don't call this
+  Fl_Widget *widget(int,int,int,int) {return 0;}
+  int recalc;		// set by fix_overlay()
+
+public:
+
+  uchar modal, non_modal;
+
+  Fl_Type *make();
+  virtual const char *type_name() {return "Fl_Window";}
+
+  void open();
+
+  void fix_overlay();	// update the bounding box, etc
+
+  virtual void write_properties();
+  virtual void read_property(const char *);
+  virtual int read_fdesign(const char*, const char*);
+
+  void add_child(Fl_Type*, Fl_Type*);
+  void move_child(Fl_Type*, Fl_Type*);
+  void remove_child(Fl_Type*);
+
+  int is_parent() const {return 1;}
+  int is_group() const {return 1;}
+  int is_window() const {return 1;}
+};
+
+static int overlays_invisible;
+
+// The following Fl_Widget is used to simulate the windows.  It has
+// an overlay for the fluid ui, and special-cases the FL_NO_BOX.
+
+class Overlay_Window : public Fl_Overlay_Window {
+  void draw();
+  void draw_overlay();
+public:
+  Fl_Window_Type *window;
+  int handle(int);
+  Overlay_Window(int w,int h) : Fl_Overlay_Window(w,h) {Fl_Group::current(0);}
+  void resize(int,int,int,int);
+};
+void Overlay_Window::draw() {
+  const int CHECKSIZE = 8;
+  // see if box is clear or a frame or rounded:
+  if ((damage()&128) &&
+      (!box() || (box()>=4&&!(box()&2)) || box()>=_FL_ROUNDED_BOX)) {
+    // if so, draw checkerboard so user can see what areas are clear:
+    for (int y = 0; y < h(); y += CHECKSIZE) 
+      for (int x = 0; x < w(); x += CHECKSIZE) {
+	fl_color(((y/(2*CHECKSIZE))&1) != ((x/(2*CHECKSIZE))&1) ?
+		 FL_WHITE : FL_BLACK);
+	fl_rectf(x,y,CHECKSIZE,CHECKSIZE);
+      }
+  }
+  Fl_Overlay_Window::draw();
+}
+
+void Overlay_Window::draw_overlay() {
+  window->draw_overlay();
+}
+int Overlay_Window::handle(int e) {
+  return window->handle(e);
+}
+
+Fl_Type *Fl_Window_Type::make() {
+  Fl_Type *p = Fl_Type::current;
+  while (p && !p->is_code_block()) p = p->parent;
+  if (!p) {
+    fl_message("Please select a function");
+    return 0;
+  }
+  Fl_Window_Type *o = new Fl_Window_Type();
+  if (!this->o) {// template widget
+    this->o = new Fl_Window(100,100);
+    Fl_Group::current(0);
+  }
+  o->factory = this;
+  o->drag = 0;
+  o->numselected = 0;
+  Overlay_Window *w = new Overlay_Window(100,100);
+  w->window = o;
+  o->o = w;
+  o->add(p);
+  o->modal = 0;
+  o->non_modal = 0;
+  return o;
+}
+
+void Fl_Window_Type::add_child(Fl_Type* cc, Fl_Type* before) {
+  Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
+  Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
+  ((Fl_Window*)o)->insert(*(c->o), b);
+  o->redraw();
+}
+
+void Fl_Window_Type::remove_child(Fl_Type* cc) {
+  Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
+  ((Fl_Window*)o)->remove(c->o);
+  o->redraw();
+}
+
+void Fl_Window_Type::move_child(Fl_Type* cc, Fl_Type* before) {
+  Fl_Widget_Type* c = (Fl_Widget_Type*)cc;
+  ((Fl_Window*)o)->remove(c->o);
+  Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0;
+  ((Fl_Window*)o)->insert(*(c->o), b);
+  o->redraw();
+}
+
+////////////////////////////////////////////////////////////////
+
+// Double-click on window widget shows the window, or if already shown,
+// it shows the control panel.
+void Fl_Window_Type::open() {
+  Overlay_Window *w = (Overlay_Window *)o;
+  if (w->shown()) {
+    w->show();
+    Fl_Widget_Type::open();
+  } else {
+    Fl_Widget *p = w->resizable();
+    if (!p) w->resizable(w);
+    w->show();
+    w->resizable(p);
+  }
+}
+
+// control panel items:
+#include "widget_panel.H"
+
+void modal_cb(Fl_Light_Button* i, void* v) {
+  if (v == LOAD) {
+    if (!current_widget->is_window()) {i->hide(); return;}
+    i->show();
+    i->value(((Fl_Window_Type *)current_widget)->modal);
+  } else {
+    ((Fl_Window_Type *)current_widget)->modal = i->value();
+  }
+}
+
+void non_modal_cb(Fl_Light_Button* i, void* v) {
+  if (v == LOAD) {
+    if (!current_widget->is_window()) {i->hide(); return;}
+    i->show();
+    i->value(((Fl_Window_Type *)current_widget)->non_modal);
+  } else {
+    ((Fl_Window_Type *)current_widget)->non_modal = i->value();
+  }
+}
+
+void border_cb(Fl_Light_Button* i, void* v) {
+  if (v == LOAD) {
+    if (!current_widget->is_window()) {i->hide(); return;}
+    i->show();
+    i->value(((Fl_Window*)(current_widget->o))->border());
+  } else {
+    ((Fl_Window*)(current_widget->o))->border(i->value());
+  }
+}
+
+void xclass_cb(Fl_Input* i, void* v) {
+  if (v == LOAD) {
+    if (!current_widget->is_window()) {i->hide(); return;}
+    i->show();
+    i->value(((Fl_Widget_Type *)current_widget)->xclass);
+  } else {
+    for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+      if (o->selected && o->is_widget()) {
+	Fl_Widget_Type* w = (Fl_Widget_Type*)o;
+	if (w->is_window() || w->is_button())
+	  storestring(i->value(),w->xclass);
+	if (w->is_window()) ((Fl_Window*)(w->o))->xclass(w->xclass);
+	else if (w->is_menu_item()) w->redraw();
+      }
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+void Fl_Window_Type::setlabel(const char *n) {
+  if (o) ((Fl_Window *)o)->label(n);
+}
+
+// make() is called on this widget when user picks window off New menu:
+Fl_Window_Type Fl_Window_type;
+
+// Resize from window manager, try to resize it back to a legal size.
+// This is not proper X behavior, but works on 4DWM and fvwm
+void Overlay_Window::resize(int X,int Y,int W,int H) {
+  if (!visible() || W==w() && H==h()) {
+    Fl_Overlay_Window::resize(X,Y,W,H);
+    return;
+  }
+  int nw = gridx&&W!=w() ? ((W+gridx/2)/gridx)*gridx : W;
+  int nh = gridy&&H!=h() ? ((H+gridy/2)/gridy)*gridy : H;
+  Fl_Widget* t = resizable(); resizable(0);
+  Fl_Overlay_Window::resize(X,Y,W,H);
+  resizable(t);
+  // make sure new window size surrounds the widgets:
+  int b = 0;
+  int r = 0;
+  for (Fl_Type *o=window->next; o && o->level>window->level; o=o->next)
+    if (o->is_widget() && !o->is_menu_item()) {
+      Fl_Widget* w = ((Fl_Widget_Type*)o)->o;
+      if (w->x()+w->w() > r) r = w->x()+w->w();
+      if (w->y()+w->h() > b) b = w->y()+w->h();
+    }
+  if (nh < b) nh = b;
+  if (nw < r) nw = r;
+  // If changed, tell the window manager.  Skip really big windows
+  // that might be bigger than screen:
+  if (nw != W && nw < Fl::w()-100 || nh != H && nh < Fl::h()-100) size(nw,nh);
+}
+
+// calculate actual move by moving mouse position (mx,my) to
+// nearest multiple of gridsize, and snap to original position
+void Fl_Window_Type::newdx() {
+  int dx, dy;
+  if (Fl::event_state(FL_ALT)) {
+    dx = mx-x1;
+    dy = my-y1;
+  } else {
+    int dx0 = mx-x1;
+    int ix = (drag&RIGHT) ? br : bx;
+    dx = gridx ? ((ix+dx0+gridx/2)/gridx)*gridx - ix : dx0;
+    if (dx0 > snap) {
+      if (dx < 0) dx = 0;
+    } else if (dx0 < -snap) {
+      if (dx > 0) dx = 0;
+    } else 
+      dx = 0;
+    int dy0 = my-y1;
+    int iy = (drag&BOTTOM) ? by : bt;
+    dy = gridy ? ((iy+dy0+gridy/2)/gridy)*gridy - iy : dy0;
+    if (dy0 > snap) {
+      if (dy < 0) dy = 0;
+    } else if (dy0 < -snap) {
+      if (dy > 0) dy = 0;
+    } else 
+      dy = 0;
+  }
+  if (this->dx != dx || this->dy != dy) {
+    this->dx = dx; this->dy = dy;
+    ((Overlay_Window *)(this->o))->redraw_overlay();
+  }
+}
+
+// Move a widget according to dx and dy calculated above
+void Fl_Window_Type::newposition(Fl_Widget_Type *o,int &X,int &Y,int &R,int &T) {
+  X = o->o->x();
+  Y = o->o->y();
+  R = X+o->o->w();
+  T = Y+o->o->h();
+  if (!drag) return;
+  if (drag&DRAG) {
+    X += dx;
+    Y += dy;
+    R += dx;
+    T += dy;
+  } else {
+    if (drag&LEFT) if (X==bx) X += dx; else if (Xbr+dx) R = br+dx;
+    if (drag&TOP) if (T==bt) T += dy; else if (T>bt+dx) T = bt+dx;
+  }
+  if (Rw(); by = o->h(); br = 0; bt = 0;
+    numselected = 0;
+    for (Fl_Type *q=next; q && q->level>level; q=q->next)
+      if (q->selected && q->is_widget() && !q->is_menu_item()) {
+	numselected++;
+	Fl_Widget_Type* o = (Fl_Widget_Type*)q;
+	if (o->o->x() < bx) bx = o->o->x();
+	if (o->o->y() < by) by = o->o->y();
+	if (o->o->x()+o->o->w() > br) br = o->o->x()+o->o->w();
+	if (o->o->y()+o->o->h() > bt) bt = o->o->y()+o->o->h();
+      }
+    recalc = 0;
+  }
+  fl_color(FL_RED);
+  if (drag==BOX && (x1 != mx || y1 != my)) {
+    int x = x1; int r = mx; if (x > r) {x = mx; r = x1;}
+    int y = y1; int b = my; if (y > b) {y = my; b = y1;}
+    fl_rect(x,y,r-x,b-y);
+  }
+  if (overlays_invisible) return;
+  if (selected) fl_rect(0,0,o->w(),o->h());
+  if (!numselected) return;
+  int bx,by,br,bt;
+  bx = o->w(); by = o->h(); br = 0; bt = 0;
+  for (Fl_Type *q=next; q && q->level>level; q = q->next)
+    if (q->selected && q->is_widget() && !q->is_menu_item()) {
+      Fl_Widget_Type* o = (Fl_Widget_Type*)q;
+      int x,y,r,t;
+      newposition(o,x,y,r,t);
+      fl_rect(x,y,r-x,t-y);
+      if (x < bx) bx = x;
+      if (y < by) by = y;
+      if (r > br) br = r;
+      if (t > bt) bt = t;
+    }
+  if (selected) return;
+  if (numselected>1) fl_rect(bx,by,br-bx,bt-by);
+  fl_rectf(bx,by,5,5);
+  fl_rectf(br-5,by,5,5);
+  fl_rectf(br-5,bt-5,5,5);
+  fl_rectf(bx,bt-5,5,5);
+}
+
+// Calculate new bounding box of selected widgets:
+void Fl_Window_Type::fix_overlay() {
+  overlays_invisible = 0;
+  recalc = 1;
+  ((Overlay_Window *)(this->o))->redraw_overlay();
+}
+
+// do that for every window (when selected set changes):
+void redraw_overlays() {
+  for (Fl_Type *o=Fl_Type::first; o; o=o->next)
+    if (o->is_window()) ((Fl_Window_Type*)o)->fix_overlay();
+}
+
+void toggle_overlays(Fl_Widget *,void *) {
+  overlays_invisible = !overlays_invisible;
+  for (Fl_Type *o=Fl_Type::first; o; o=o->next)
+    if (o->is_window()) {
+      Fl_Widget_Type* w = (Fl_Widget_Type*)o;
+      ((Overlay_Window*)(w->o))->redraw_overlay();
+    }
+}
+
+extern void select(Fl_Type *,int);
+extern void select_only(Fl_Type *);
+extern void deselect();
+extern Fl_Type* in_this_only;
+extern void fix_group_size(Fl_Type *t);
+
+extern Fl_Menu_Item Main_Menu[];
+extern Fl_Menu_Item New_Menu[];
+
+int Fl_Window_Type::handle(int event) {
+  static Fl_Type* selection;
+  switch (event) {
+  case FL_PUSH:
+    x1 = mx = Fl::event_x();
+    y1 = my = Fl::event_y();
+    drag = 0;
+    // test for popup menu:
+    if (Fl::event_button() >= 3) {
+      in_this_only = this; // modifies how some menu items work.
+      static const Fl_Menu_Item* prev;
+      const Fl_Menu_Item* m = New_Menu->popup(mx,my,"New",prev);
+      if (m && m->callback()) {prev = m; m->do_callback(this->o);}
+      in_this_only = 0;
+      return 1;
+    }
+    // find the innermost item clicked on:
+    selection = this;
+    {for (Fl_Type* i=next; i && i->level>level; i=i->next)
+      if (i->is_widget() && !i->is_menu_item()) {
+      Fl_Widget_Type* o = (Fl_Widget_Type*)i;
+      for (Fl_Widget *o1 = o->o; o1; o1 = o1->parent())
+	if (!o1->visible()) goto CONTINUE2;
+      if (Fl::event_inside(o->o)) selection = o;
+    CONTINUE2:;
+    }}
+    // do object-specific selection of other objects:
+    {Fl_Type* t = selection->click_test(mx, my);
+    if (t) {
+      //if (t == selection) return 1; // indicates mouse eaten w/o change
+      if (Fl::event_state(FL_SHIFT)) {
+	Fl::event_is_click(0);
+	select(t, !t->selected);
+      } else {
+	deselect();
+	select(t, 1);
+	if (t->is_menu_item()) t->open();
+      }
+      selection = t;
+      return 1;
+    }}
+    // see if user grabs edges of selected region:
+    if (numselected && !overlays_invisible && !(Fl::event_state(FL_SHIFT)) &&
+	mx<=br+snap && mx>=bx-snap && my<=bt+snap && my>=by-snap) {
+      int snap1 = snap>5 ? snap : 5;
+      int w1 = (br-bx)/4; if (w1 > snap1) w1 = snap1;
+      if (mx>=br-w1) drag |= RIGHT;
+      else if (mx snap1) w1 = snap1;
+      if (my<=by+w1) drag |= BOTTOM;
+      else if (my>bt-w1) drag |= TOP;
+      if (!drag) drag = DRAG;
+    } else {
+      drag = BOX; // start a new selection region
+    }
+    return 1;
+  case FL_DRAG:
+    if (!drag) return 0;
+    mx = Fl::event_x();
+    my = Fl::event_y();
+    newdx();
+    return 1;
+  case FL_RELEASE:
+    if (!drag) return 0;
+    mx = Fl::event_x();
+    my = Fl::event_y();
+    newdx();
+    if (drag != BOX && (dx || dy || !Fl::event_is_click())) {
+      if (dx || dy) {
+	Fl_Type *i;
+	for (i=next; i && i->level>level;) {
+	  if (i->selected && i->is_widget() && !i->is_menu_item()) {
+	    Fl_Widget_Type* o = (Fl_Widget_Type*)i;
+	    int x,y,r,t;
+	    newposition(o,x,y,r,t);
+	    o->o->resize(x,y,r-x,t-y);
+	    // move all the children, whether selected or not:
+	    Fl_Type* p;
+	    for (p = o->next; p && p->level>o->level; p = p->next)
+	      if (p->is_widget() && !p->is_menu_item()) {
+		Fl_Widget_Type* o = (Fl_Widget_Type*)p;
+		int x,y,r,t;
+		newposition(o,x,y,r,t);
+		o->o->resize(x,y,r-x,t-y);
+	      }
+	    i = p;
+	  } else {
+	    i = i->next;
+	  }
+	}
+	for (i=next; i && i->level>level; i=i->next) fix_group_size(i);
+	this->o->redraw();
+	fix_overlay();
+	modflag = 1;
+      }
+    } else if ((Fl::event_clicks() || Fl::event_state(FL_CTRL))) {
+      Fl_Widget_Type::open();
+    } else {
+      if (mxlevel>level; i=i->next)
+	if (i->is_widget() && !i->is_menu_item()) {
+	Fl_Widget_Type* o = (Fl_Widget_Type*)i;
+	for (Fl_Widget *o1 = o->o; o1; o1 = o1->parent())
+	  if (!o1->visible()) goto CONTINUE;
+	if (Fl::event_inside(o->o)) selection = o;
+	if (o->o->x()>=x1 && o->o->y()>y1 &&
+	    o->o->x()+o->o->w()o->y()+o->o->h()selected : 1);
+	}
+      CONTINUE:;
+      }
+      // if nothing in box, select what was clicked on:
+      if (!n) {
+	select(selection, toggle ? !selection->selected : 1);
+      }
+    }
+    drag = 0;
+    return 1;
+
+  case FL_KEYBOARD: {
+    if (Fl::event_key() == FL_Escape) {((Fl_Window*)o)->hide(); return 1;}
+    // find current child:
+    Fl_Type *i = Fl_Type::current;
+    while (i && (!i->is_widget() || i->is_menu_item())) i = i->parent;
+    if (!i) return 0;
+    Fl_Type *p = i->parent;
+    while (p && p != this) p = p->parent;
+    if (!p || !p->is_widget()) {i=next; if (!i || i->level <= level) return 0;}
+    p = i;
+    // try to navigate to another child:
+    for (;;) {
+      switch (Fl::event_key()) {
+      case FL_Tab:
+	if (Fl::event_state(FL_SHIFT)) goto LEFT;
+      case FL_Right:
+      case FL_Down:
+	i = i->next; break;
+      case FL_Left:
+      case FL_Up:
+      LEFT:
+	i = i->prev; break;
+      default:
+	return 0;
+      }
+      if (!i || i->level <= level) {i = p; break;}
+      if (!i->is_widget() || i->is_menu_item()) continue;
+      switch (Fl::event_key()) {
+      case FL_Up:
+      case FL_Down: if (p->is_widget() && !p->is_menu_item()) {
+	Fl_Widget* w = ((Fl_Widget_Type*)i)->o;
+	Fl_Widget* pw = ((Fl_Widget_Type*)p)->o;
+	if (w->x() >= pw->x()+pw->w() ||
+	    w->x()+w->w() <= pw->x()) continue;
+      }}
+      break;
+    }
+    // select it:
+    deselect(); select(i,1);
+    } return 1;
+
+  case FL_SHORTCUT: {
+    in_this_only = this; // modifies how some menu items work.
+    const Fl_Menu_Item* m = Main_Menu->test_shortcut();
+    if (m && m->callback()) m->do_callback(this->o);
+    in_this_only = 0;
+    return (m != 0);
+  }
+  default:
+    return 0;
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+#include 
+#include 
+
+void Fl_Window_Type::write_code1() {
+  Fl_Widget_Type::write_code1();
+}
+
+void Fl_Window_Type::write_code2() {
+  if (modal) write_c("%so->set_modal();\n", indent());
+  else if (non_modal) write_c("%so->set_non_modal();\n", indent());
+  if (!((Fl_Window*)o)->border()) write_c("%so->clear_border();\n", indent());
+  write_c("%so->end();\n", indent());
+  if (((Fl_Window*)o)->resizable() == o)
+    write_c("%so->resizable(o);\n", indent());
+  Fl_Widget_Type::write_code2();
+}
+
+void Fl_Window_Type::write_properties() {
+  Fl_Widget_Type::write_properties();
+  if (modal) write_string("modal");
+  else if (non_modal) write_string("non_modal");
+  if (!((Fl_Window*)o)->border()) write_string("noborder");
+  if (xclass) {write_string("xclass"); write_word(xclass);}
+  if (o->visible()) write_string("visible");
+}
+
+void Fl_Window_Type::read_property(const char *c) {
+  if (!strcmp(c,"modal")) {
+    modal = 1;
+  } else if (!strcmp(c,"non_modal")) {
+    non_modal = 1;
+  } else if (!strcmp(c, "visible")) {
+    if (Fl::first_window()) open(); // only if we are using user interface
+  } else if (!strcmp(c,"noborder")) {
+    ((Fl_Window*)o)->border(0);
+  } else if (!strcmp(c,"xclass")) {
+    storestring(read_word(),xclass);
+    ((Fl_Window*)o)->xclass(xclass);
+  } else {
+    Fl_Widget_Type::read_property(c);
+  }
+}
+
+int Fl_Window_Type::read_fdesign(const char* name, const char* value) {
+  int x;
+  o->box(FL_NO_BOX); // because fdesign always puts an Fl_Box next
+  if (!strcmp(name,"Width")) {
+    if (sscanf(value,"%d",&x) == 1) o->size(x,o->h());
+  } else if (!strcmp(name,"Height")) {
+    if (sscanf(value,"%d",&x) == 1) o->size(o->w(),x);
+  } else if (!strcmp(name,"NumberofWidgets")) {
+    return 1; // we can figure out count from file
+  } else if (!strcmp(name,"border")) {
+    if (sscanf(value,"%d",&x) == 1) ((Fl_Window*)o)->border(x);
+  } else if (!strcmp(name,"title")) {
+    label(value);
+  } else {
+    return Fl_Widget_Type::read_fdesign(name,value);
+  }
+  return 1;
+}
diff --git a/fluid/Fluid_Image.cxx b/fluid/Fluid_Image.cxx
new file mode 100644
index 000000000..e01022502
--- /dev/null
+++ b/fluid/Fluid_Image.cxx
@@ -0,0 +1,384 @@
+// Fluid_Image.C
+
+// For pixmap labels.
+
+#include 
+#include 
+#include "Fl_Type.H"
+#include "Fluid_Image.H"
+#include 
+#include 
+#include 
+#include 
+#include 
+#include  // needed for DEC's Alpha cxx ?
+#include 
+
+extern void goto_source_dir(); // in fluid.C
+extern void leave_source_dir(); // in fluid.C
+
+////////////////////////////////////////////////////////////////
+#include 
+
+class pixmap_image : public Fluid_Image {
+protected:
+  Fl_Pixmap *p;
+  int *linelength;
+public:
+  pixmap_image(const char *name, FILE *);
+  ~pixmap_image();
+  virtual void label(Fl_Widget *); // set the label of this widget
+  virtual void write_static();
+  virtual void write_code();
+  static int test_file(char *buffer);
+};
+
+int pixmap_image::test_file(char *buffer) {
+  return (strstr(buffer,"/* XPM") != 0);
+}
+
+void pixmap_image::label(Fl_Widget *o) {
+  if (p) p->label(o);
+}
+
+static int pixmap_header_written;
+
+void pixmap_image::write_static() {
+  if (!p) return;
+  write_c("\n");
+  if (pixmap_header_written != write_number) {
+    write_c("#include \n");
+    pixmap_header_written = write_number;
+  }
+  write_c("static char *%s[] = {\n",
+	  unique_id(this, "image", filename_name(name()), 0));
+  int l;
+  for (l = 0; p->data[l]; l++) {
+    if (l) write_c(",\n");
+    write_cstring(p->data[l],linelength[l]);
+  }
+  write_c("\n};\n");
+  write_c("static Fl_Pixmap %s(%s);\n",
+	  unique_id(this, "pixmap", filename_name(name()), 0),
+	  unique_id(this, "image", filename_name(name()), 0));
+}
+
+void pixmap_image::write_code() {
+  if (!p) return;
+  write_c("%s%s.label(o);\n", indent(),
+	  unique_id(this, "pixmap", filename_name(name()), 0));
+}
+
+static int hexdigit(int x) {
+  if (isdigit(x)) return x-'0';
+  if (isupper(x)) return x-'A'+10;
+  if (islower(x)) return x-'a'+10;
+  return 20;
+}
+
+#define MAXSIZE 1024
+
+pixmap_image::pixmap_image(const char *name, FILE *f) : Fluid_Image(name) {
+  if (!f) return; // for subclasses
+  // read all the c-strings out of the file:
+  char *data[MAXSIZE+1];
+  int length[MAXSIZE+1];
+  char buffer[MAXSIZE+20];
+  int i = 0;
+  while (i < MAXSIZE && fgets(buffer,MAXSIZE+20,f)) {
+    if (buffer[0] != '\"') continue;
+    char *p = buffer;
+    char *q = buffer+1;
+    while (*q != '\"') {
+      if (*q == '\\') switch (*++q) {
+      case '\n':
+	fgets(q,(buffer+MAXSIZE+20)-q,f); break;
+      case 0:
+	break;
+      case 'x': {
+	q++;
+	int n = 0;
+	for (int x = 0; x < 3; x++) {
+	  int d = hexdigit(*q);
+	  if (d > 15) break;
+	  n = (n<<4)+d;
+	  q++;
+	}
+	*p++ = n;
+      } break;
+      default: {
+	int c = *q++;
+	if (c>='0' && c<='7') {
+	  c -= '0';
+	  for (int x=0; x<2; x++) {
+	    int d = hexdigit(*q);
+	    if (d>7) break;
+	    c = (c<<3)+d;
+	    q++;
+	  }
+	}
+	*p++ = c;
+      } break;
+      } else {
+	*p++ = *q++;
+      }
+    }
+    *p++ = 0;
+    data[i] = new char[p-buffer];
+    memcpy(data[i],buffer,p-buffer);
+    length[i] = p-buffer-1;
+    i++;
+  }
+  data[i++] = 0; // put a null at the end
+
+  char** real_data = new char*[i];
+  linelength = new int[i];
+  while (i--) {real_data[i] = data[i]; linelength[i] = length[i];}
+  p = new Fl_Pixmap(real_data);
+}
+
+pixmap_image::~pixmap_image() {
+  if (p && p->data) {
+    char** real_data = (char**)(p->data);
+    for (int i = 0; real_data[i]; i++) delete[] real_data[i];
+    delete[] real_data;
+  }
+  delete[] linelength;
+  delete p;
+}
+
+////////////////////////////////////////////////////////////////
+
+class gif_image : public pixmap_image {
+public:
+  gif_image(const char *name, FILE *);
+  ~gif_image();
+  static int test_file(char *buffer);
+};
+
+int gif_image::test_file(char *buffer) {
+  return !strncmp(buffer,"GIF",3);
+}
+
+// function in gif.C:
+int gif2xpm(
+    const char *infname,// filename for error messages
+    FILE *GifFile,	// file to read
+    char*** datap,	// return xpm data here
+    int** lengthp,	// return line lengths here
+    int inumber		// which image in movie (0 = first)
+);
+
+gif_image::gif_image(const char *name, FILE *f) : pixmap_image(name,0) {
+  char** datap;
+  if (gif2xpm(name,f,&datap,&linelength,0)) {
+    p = new Fl_Pixmap(datap);
+  } else
+    p = 0;
+}
+
+gif_image::~gif_image() {
+  if (p && p->data) {
+    char** real_data = (char**)(p->data);
+    for (int i = 0; i < 3; i++) delete[] real_data[i];
+    delete[] real_data;
+    p->data = 0;
+  }
+}
+
+////////////////////////////////////////////////////////////////
+#include 
+
+class bitmap_image : public Fluid_Image {
+  Fl_Bitmap *p;
+public:
+  ~bitmap_image();
+  bitmap_image(const char *name, FILE *);
+  virtual void label(Fl_Widget *); // set the label of this widget
+  virtual void write_static();
+  virtual void write_code();
+  static int test_file(char *buffer);
+};
+
+// bad test, always do this last!
+int bitmap_image::test_file(char *buffer) {
+  return (strstr(buffer,"#define ") != 0);
+}
+
+void bitmap_image::label(Fl_Widget *o) {
+  if (p) p->label(o); else o->labeltype(FL_NORMAL_LABEL);
+}
+
+static int bitmap_header_written;
+
+void bitmap_image::write_static() {
+  if (!p) return;
+  write_c("\n");
+  if (bitmap_header_written != write_number) {
+    write_c("#include \n");
+    bitmap_header_written = write_number;
+  }
+  write_c("static char %s[] = {  \n",
+	  unique_id(this, "bits", filename_name(name()), 0));
+  int n = ((p->w+7)/8)*p->h;
+  for (int i = 0; i < n; i++) {
+    if (i) write_c(", ");
+    write_c("%d",p->array[i]);
+  }
+  write_c("\n};\n");
+  write_c("static Fl_Bitmap %s(%s, %d, %d);\n",
+	  unique_id(this, "bitmap", filename_name(name()), 0),
+	  unique_id(this, "bits", filename_name(name()), 0),
+	  p->w, p->h);
+}
+
+void bitmap_image::write_code() {
+  if (!p) return;
+  write_c("%s%s.label(o);\n", indent(),
+	  unique_id(this, "bitmap", filename_name(name()), 0));
+}
+
+bitmap_image::bitmap_image(const char *name, FILE *f) : Fluid_Image(name) {
+  p = 0; // if any problems with parse we exit with this zero
+  char buffer[1024];
+  char junk[1024];
+  int wh[2]; // width and height
+  int i;
+  for (i = 0; i<2; i++) {
+    for (;;) {
+      if (!fgets(buffer,1024,f)) return;
+      int r = sscanf(buffer,"#define %s %d",junk,&wh[i]);
+      if (r >= 2) break;
+    }
+  }
+  // skip to data array:
+  for (;;) {
+    if (!fgets(buffer,1024,f)) return;
+    if (!strncmp(buffer,"static ",7)) break;
+  }
+  int n = ((wh[0]+7)/8)*wh[1];
+  uchar *data = new uchar[n];
+  // read the data:
+  i = 0;
+  for (;i0) data[i++] = t;
+      while (*a && *a++ != ',');
+    }
+  }
+  p = new Fl_Bitmap(data,wh[0],wh[1]);
+}
+
+bitmap_image::~bitmap_image() {
+  if (p) {
+    delete[] (uchar*)(p->array);
+    delete p;
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+static Fluid_Image** images; // sorted list
+static int numimages;
+static int tablesize;
+
+Fluid_Image* Fluid_Image::find(const char *name) {
+  if (!name || !*name) return 0;
+
+  // first search to see if it exists already:
+  int a = 0;
+  int b = numimages;
+  while (a < b) {
+    int c = (a+b)/2;
+    int i = strcmp(name,images[c]->name_);
+    if (i < 0) b = c;
+    else if (i > 0) a = c+1;
+    else return images[c];
+  }
+
+  // no, so now see if the file exists:
+
+  goto_source_dir();
+  FILE *f = fopen(name,"rb");
+  if (!f) {
+    read_error("%s : %s",name,strerror(errno));
+    leave_source_dir();
+    return 0;
+  }
+
+  Fluid_Image *ret;
+
+  // now see if we can identify the type, by reading in some data
+  // and asking all the types we know about:
+
+  char buffer[1025];
+  fread(buffer, 1, 1024, f);
+  rewind(f);
+  buffer[1024] = 0; // null-terminate so strstr() works
+
+  if (pixmap_image::test_file(buffer)) {
+    ret = new pixmap_image(name,f);
+  } else if (gif_image::test_file(buffer)) {
+    ret = new gif_image(name,f);
+  } else if (bitmap_image::test_file(buffer)) {
+    ret = new bitmap_image(name,f);
+  } else {
+    ret = 0;
+    read_error("%s : unrecognized image format", name);
+  }
+  fclose(f);
+  leave_source_dir();
+  if (!ret) return 0;
+
+  // make a new entry in the table:
+  numimages++;
+  if (numimages > tablesize) {
+    tablesize = tablesize ? 2*tablesize : 16;
+    images = (Fluid_Image**)realloc(images, tablesize*sizeof(Fluid_Image*));
+  }
+  for (b = numimages-1; b > a; b--) images[b] = images[b-1];
+  images[a] = ret;
+
+  return ret;
+}
+
+Fluid_Image::Fluid_Image(const char *name) {
+  name_ = strdup(name);
+  written = 0;
+  refcount = 0;
+}
+
+void Fluid_Image::increment() {
+  ++refcount;
+}
+
+void Fluid_Image::decrement() {
+  --refcount;
+  if (refcount > 0) return;
+  delete this;
+}
+
+Fluid_Image::~Fluid_Image() {
+  int a;
+  for (a = 0;; a++) if (images[a] == this) break;
+  numimages--;
+  for (; a < numimages; a++) images[a] = images[a+1];
+  free((void*)name_);
+}
+
+////////////////////////////////////////////////////////////////
+
+#include 
+
+const char *ui_find_image_name;
+Fluid_Image *ui_find_image(const char *oldname) {
+  goto_source_dir();
+  const char *name = fl_file_chooser("Image","*.{bm|xbm|xpm|gif}",oldname);
+  ui_find_image_name = name;
+  Fluid_Image *ret = (name && *name) ? Fluid_Image::find(name) : 0;
+  leave_source_dir();
+  return ret;
+}
diff --git a/fluid/Fluid_Image.h b/fluid/Fluid_Image.h
new file mode 100644
index 000000000..fdc7937bc
--- /dev/null
+++ b/fluid/Fluid_Image.h
@@ -0,0 +1,28 @@
+// Fluid_Image.H
+
+// This class stores the image labels for widgets in fluid.  This is
+// not a class in fltk itself, and this will produce different types of
+// code depending on what the image type is.  There are private subclasses
+// in Fluid_Image.C for each type of image format.  Right now only xpm
+// files are supported.
+
+class Fluid_Image {
+  const char *name_;
+  int refcount;
+protected:
+  Fluid_Image(const char *name); // no public constructor
+  virtual ~Fluid_Image(); // no public destructor
+public:
+  int written;
+  static Fluid_Image* find(const char *);
+  void decrement(); // reference counting & automatic free
+  void increment();
+  virtual void label(Fl_Widget *) = 0; // set the label of this widget
+  virtual void write_static() = 0;
+  virtual void write_code() = 0;
+  const char *name() const {return name_;}
+};
+
+// pop up file chooser and return a legal image selected by user,
+// or zero for any errors:
+Fluid_Image *ui_find_image(const char *);
diff --git a/fluid/Makefile b/fluid/Makefile
new file mode 100644
index 000000000..876b52a09
--- /dev/null
+++ b/fluid/Makefile
@@ -0,0 +1,83 @@
+PROGRAM = fluid
+
+CPPFILES = \
+	Fl_Function_Type.C \
+	Fl_Menu_Type.C \
+	Fl_Group_Type.C \
+	Fl_Widget_Type.C \
+	Fl_Type.C \
+	Fl_Window_Type.C \
+	Fluid_Image.C \
+	code.C \
+	factory.C \
+	file.C \
+	fluid.C \
+	about_panel.C \
+	widget_panel.C \
+	alignment_panel.C \
+	function_panel.C \
+	gif.C
+
+################################################################
+
+OBJECTS = $(CPPFILES:.C=.o)
+
+include ../makeinclude
+
+.SUFFIXES : .C .c .o .do .fl .H
+
+.C.o :
+	@echo $<:
+	@$(CXX) -I.. $(CXXFLAGS) -c $<
+.c.o :
+	@echo $<:
+	@$(CC) -I.. $(CFLAGS) -c $<
+.C :
+	@echo $@:
+	@$(CXX) -I.. $(CXXFLAGS) -o $@ $< -L../lib -lfltk $(LDLIBS)
+
+.fl.C .fl.H :
+	-fluid -c $<
+
+# better way to do this for gnu make:
+# %.H %.C: %.fl
+#	fluid -c $<
+
+$(PROGRAM) : $(OBJECTS) ../lib/$(LIBNAME)
+	@echo linking $@:
+	@$(CXX) $(CXXFLAGS) -o $(PROGRAM) $(OBJECTS) -L../lib -lfltk $(LDLIBS)
+
+clean :
+	-@ rm -f *.o $(PROGRAM) $(CLEAN) core *~ makedepend
+	@touch makedepend
+
+depend:
+	$(MAKEDEPEND) -I.. $(CXXFLAGS) $(CPPFILES) $(CFILES) > makedepend
+include makedepend
+
+install: $(PROGRAM)
+	strip $(PROGRAM)
+	cp $(PROGRAM) $(bindir)/$(PROGRAM)
+	@chmod a+rx,g-w,o-w $(bindir)/$(PROGRAM)
+
+uninstall:
+	-@ rm -f $(bindir)/$(PROGRAM)
+
+################################################################
+
+PROGRAM_D = $(PROGRAM)_d
+
+debug: $(PROGRAM_D)
+
+OBJECTS_D = $(CPPFILES:.C=.do) $(CFILES:.c=.do)
+
+.C.do :
+	@echo $<:
+	@$(CXX) -I.. $(CXXFLAGS_D) -c -o $@ $<
+.c.do :
+	@echo $<:
+	@$(CC) -I.. $(CFLAGS_D) -c -o $@ $<
+
+$(PROGRAM_D) : $(OBJECTS_D) ../lib/$(LIBNAME_D)
+	@echo linking $@:
+	@$(CXX) $(CXXFLAGS_D) -o $(PROGRAM_D) $(OBJECTS_D) -L../lib -lfltk_d $(LDLIBS)
diff --git a/fluid/README b/fluid/README
new file mode 100644
index 000000000..9fe6d6c36
--- /dev/null
+++ b/fluid/README
@@ -0,0 +1,214 @@
+Fluid (the FL User Interface Designer) is a graphical editor that
+is used to produce FL source code.
+
+Fluid edits and saves it's state in ".fl" files.  These files are
+text, and you could (with care) edit them in a text editor, perhaps to
+get some special effects.
+
+When asked to "compile", fluid outputs a .C source file and a .H
+header file: The .C file contains one or more public functions, each
+of which will create one or more FL windows and all the objects in
+those windows.  The .H file declares (as externs) all the functions
+and named objects created by the .C file, and includes all the
+necessary FL header files for those objects.
+
+The C file must be compiled and linked with a "main" source file(s)
+that you write.  This source code must include the .H output, and
+should call the functions in the .C file to create windows.  The main
+code must do show() on the windows and run the Fl::wait() loop.
+
+                               _________
+                              /        /
+    __________            +->/.C file /--------+
+   /         /           /  /________/         |
+  /.fl file /<==>[fluid]<     #include         |
+ /_________/             \     ___v_____       |
+                          \   /        /       |
+                           +>/.H file /        |
+                            /________/         |
+                                  ^            |
+                              #include         |
+                               ___|_____       |          __________
+                              /        /       V         /         /
+                             / main.C /--->[c++,link]-->/ program /
+                            /________/                 /_________/
+
+
+Objects created by fluid are either "named" or "unnamed".  If they
+are named, the .C file will declare a global variable with that name
+of type "*".  This pointer has a value of zero until the fluid
+function is called, the fluid function will set it to the instance of
+the .  Unnamed objects are only accessible through
+pointers from other objects.
+
+Windows may be named or unnamed.  Named windows are only created
+once even if you call the function several times (fluid outputs "if
+(!name) {...}" around the code that creates the window).  Unnamed
+windows lets you create many instances of the same window structure, a
+pointer to the unnamed window is returned from the fluid function (you
+can only put one unnamed window in a function).
+
+Objects may either call a named callback function that you write in
+another source file, or you can supply a small piece of C++ source and
+fluid will write a private callback function into the .C file.
+
+================================================================
+Worlds shortest tutorial:
+================================================================
+
+Type "fluid&"
+
+Pick "New/Function" off the menu.
+
+Delete the function name in the popup window and hit OK.  The text
+"main()" with a triangle next to it should appear highlighted in the
+main window.
+
+Pick "New/Window" off the menu.
+
+Move the window and resize it to the size you want.
+
+Pick "New/buttons/Button" off the menu.
+
+Hit the "OK" button to dismiss the panel that appears.
+
+In the window you created, try moving the button by dragging it
+around.  Notice that it "snaps" to fixed locations.  If you want to
+drag it smoothly, hold down Alt.  You can also change the size of the
+steps with Edit/Preferences.
+
+Try resizing the object by dragging the edges and corners.
+
+Type Alt+c to copy the object.
+
+Type Alt+v to paste a copy into the window.
+
+Type Alt+v several times.
+
+Drag the objects and resize them so they don't overlap.  Notice
+that you have to click an object to pick it first, then drag it.
+
+Try selecting several objects by dragging a box around them.  Check
+what happens when you move them, or when you drag an edge to resize
+them.
+
+You can also use Shift+click to toggle objects on and off.
+
+You can also select objects by clicking on them in the list in the
+main window, try that.
+
+Double-click one of the buttons.  You will get a control panel.
+
+Try changing the "label".  Try changing other items near the top of
+the panel.  To see any changes to the box type clearer, type "Alt+o"
+to make the red overlay disappear.
+
+Type "#include " into the first line of "extra code:".
+
+Type "exit(0);" into the "callback:".
+
+Hit OK.
+
+Pick "File/Save As" off the menu.
+
+Type "test.fl" into the file chooser and hit return.
+
+Pick "File/Write Code" off the menu.
+
+Go back to your terminal window.  Type "more test.C" and "more
+test.H" and you can see the code it made.
+
+Type "make test" (you may have to add libaries to your Makefile).
+
+Type "./test" to run your program.
+
+Try the buttons.  The one you put the code into will exit the
+program.
+
+Type "Alt+Q" to exit fluid.
+
+Ok, now try to make a real program.
+
+================================================================
+
+This code is quite a kludge and probably impossible to figure out.  I
+hope it will be fixed someday, but my intention was to make FL itself
+clean and simple, even if the user interface designer is forced to be
+more complex as a result.
+
+An object in fluid is represented by a subclass of "Fl_Type".
+
+Creating a new instance of an object is done by calling the virtual
+method "make()" on Fl_Type.  To allow an initial version of each type
+to be created, there is a static "factory" instance of every subclass
+of Fl_Type.  For now, make() is only called on these.  The intention
+was to use make() to copy objects, but that did not happen.  Instead I
+write the descriptions and read them back from a file in /usr/tmp,
+which is much more reliable because the read/write code is tested
+every time a file is saved!
+
+The (non-factory) instances are linked into a list by the previous and
+next pointers.  The "hierarchy" is stored by a "level" number on each
+object, and an "isparent" flag on the parent.  To find the "brother"
+of an object, code must search forward for the next object whose level
+is equal to this one.  A null pointer or an object with a lower level
+number indicates no brother.
+
+If the type is a subclass of Fl_Object, the "o" pointer points at an
+Fl_Object.  This allows the code in FL to be used to draw the object.
+The user_data() field on the Fl_Object is used as a back pointer to
+the Fl_Type.  The "factory" has an "o" pointer that points at the
+"template object".  This is an Fl_Object created the first time make()
+is called and is used to figure out what the default values for the
+fields are for the object.
+
+This "o" pointer exists in all Fl_Type objects, even the base class.
+If this is not an Fl_Object item, then the "o" pointer is zero.  This
+avoided a lot of virtual functions, but is mostly for historical
+reasons.  Rather than RTTI, I use some tests to determine subclasses:
+
+       if (o && level == 1)
+	  this is an Fl_Window_Type
+       else if (o && isparent)
+	  this is a Fl_Group_Type
+       else if (o)
+	  this is a Fl_Object_Type
+       else if (!level)
+          this is a function
+       else
+          this is a menu item or something
+	  (none of these implemented yet)
+
+
+  Fl_Type::first
+    |
+    |  NULL
+    |   ^
+    V   |
+  +---------+              +-----------+
+  | Fl_Type |------ o ---> | Fl_Window |
+  | level=0 |<-user_data()-|           |
+  |isparent |<-+           +-----------+
+  +---------+  |             |     ^
+    |   ^     parent       first   |
+  next prev   /              |   parent
+    V   |    /               V     |
+  +---------+              +-----------+
+  | Fl_Type |------ o ---> | Fl_Object |
+  | level=1 |              |           |
+  |         |<-user_data()-|           |
+  |         |              +-----------+
+  |         |          +---------+
+  |         |-factory->| Fl_Type |---- o ---->[Fl_Object]
+  +---------+          |         |           template object
+    |   ^              +---------+
+  next prev            (next,prev=NULL)
+    V   |
+  +---------+
+  | Fl_Type |
+  +---------+
+    |   ^
+    V   |
+   NULL |
+        |
+    Fl_Type::last
diff --git a/fluid/Shortcut_Button.h b/fluid/Shortcut_Button.h
new file mode 100644
index 000000000..eea4ddc70
--- /dev/null
+++ b/fluid/Shortcut_Button.h
@@ -0,0 +1,10 @@
+#include 
+
+class Shortcut_Button : public Fl_Button {
+public:
+  int svalue;
+  int handle(int);
+  void draw();
+  Shortcut_Button(int x, int y, int w, int h, const char* l = 0) :
+    Fl_Button(x,y,w,h,l) {svalue = 0;}
+};
diff --git a/fluid/about_panel.cxx b/fluid/about_panel.cxx
new file mode 100644
index 000000000..a880d39dd
--- /dev/null
+++ b/fluid/about_panel.cxx
@@ -0,0 +1,122 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "about_panel.H"
+
+Fl_Window *about_panel;
+
+Fl_Group *display_group;
+
+static void cb_1998(Fl_Button*, void*) {
+  display_group->hide();
+copyright_box->show();
+}
+
+Fl_Box *copyright_box;
+
+static void cb_OK(Fl_Return_Button* o, void*) {
+  ((Fl_Window*)(o->parent()))->hide();
+}
+
+Fl_Window* make_about_panel(const char *copyright) {
+  Fl_Window* w;
+  { Fl_Window* o = about_panel = w = new Fl_Window(309, 221, "about fluid");
+    o->box(FL_UP_BOX);
+    o->color(97);
+    o->selection_color(47);
+    w->hotspot(o);
+    { Fl_Group* o = display_group = new Fl_Group(24, 14, 275, 186);
+      { Fl_Box* o = new Fl_Box(64, 14, 50, 126);
+        o->box(FL_ROUND_UP_BOX);
+        o->color(14);
+        o->selection_color(47);
+        o->labelcolor(6);
+      }
+      { Fl_Box* o = new Fl_Box(54, 14, 70, 16);
+        o->box(FL_FLAT_BOX);
+        o->color(97);
+        o->selection_color(47);
+      }
+      { Fl_Box* o = new Fl_Box(68, 30, 42, 50);
+        o->box(FL_DOWN_BOX);
+        o->color(6);
+        o->selection_color(47);
+      }
+      { Fl_Box* o = new Fl_Box(54, 20, 70, 20);
+        o->box(FL_ROUND_UP_BOX);
+        o->color(6);
+        o->selection_color(47);
+        o->labelcolor(6);
+        o->align(16);
+      }
+      { Fl_Box* o = new Fl_Box(24, 110, 130, 90, "fluid");
+        o->box(FL_ROUND_UP_BOX);
+        o->color(14);
+        o->selection_color(47);
+        o->labeltype(FL_SHADOW_LABEL);
+        o->labelfont(1);
+        o->labelsize(40);
+        o->labelcolor(6);
+      }
+      { Fl_Box* o = new Fl_Box(67, 110, 44, 10);
+        o->box(FL_FLAT_BOX);
+        o->color(14);
+        o->selection_color(47);
+      }
+      { Fl_Box* o = new Fl_Box(84, 120, 15, 15, "` ");
+        o->box(FL_OVAL_BOX);
+        o->color(6);
+        o->selection_color(47);
+        o->labelsize(20);
+        o->labelcolor(7);
+        o->align(17);
+      }
+      { Fl_Box* o = new Fl_Box(75, 105, 15, 15, "` ");
+        o->box(FL_OVAL_BOX);
+        o->color(6);
+        o->selection_color(47);
+        o->labelsize(20);
+        o->labelcolor(7);
+        o->align(17);
+      }
+      { Fl_Box* o = new Fl_Box(89, 85, 15, 15, "` ");
+        o->box(FL_OVAL_BOX);
+        o->color(6);
+        o->selection_color(47);
+        o->labelsize(20);
+        o->labelcolor(7);
+        o->align(17);
+      }
+      { Fl_Box* o = new Fl_Box(159, 27, 131, 95, "Fltk User\nInterface\nDesigner\nVersion 1.00");
+        o->box(FL_OVAL_BOX);
+        o->color(12);
+        o->selection_color(47);
+        o->labeltype(FL_SHADOW_LABEL);
+        o->labelfont(1);
+        o->labelsize(18);
+        o->labelcolor(7);
+      }
+      { Fl_Button* o = new Fl_Button(169, 138, 115, 30, "\xa9\x31\x39\x39\x38 Bill Spitzak\n(click here)");
+        o->box(FL_THIN_UP_BOX);
+        o->labelsize(10);
+        o->labelcolor(136);
+        o->callback((Fl_Callback*)cb_1998);
+      }
+      o->end();
+    }
+    { Fl_Box* o = copyright_box = new Fl_Box(5, 5, 300, 210);
+      o->labelsize(8);
+      o->labelcolor(6);
+      o->align(148);
+      o->hide();
+      o->label(copyright);
+    }
+    { Fl_Return_Button* o = new Fl_Return_Button(168, 182, 116, 22, "OK");
+      o->labelsize(10);
+      o->callback((Fl_Callback*)cb_OK);
+    }
+    o->set_non_modal();
+    o->clear_border();
+    o->end();
+  }
+  return w;
+}
diff --git a/fluid/about_panel.fl b/fluid/about_panel.fl
new file mode 100644
index 000000000..b35c59251
--- /dev/null
+++ b/fluid/about_panel.fl
@@ -0,0 +1,71 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 0.99 
+gridx 2 
+gridy 2 
+snap 3
+Function {make_about_panel(const char *copyright)} {open
+} {
+  Fl_Window about_panel {
+    label {about fluid} open
+    xywh {345 417 309 221} box UP_BOX color {97 47} hide hotspot non_modal noborder
+  } {
+    Fl_Group display_group {open
+      xywh {24 14 275 186}
+    } {
+      Fl_Box {} {
+        xywh {64 14 50 126} box ROUND_UP_BOX color {14 47} labelcolor 6
+      }
+      Fl_Box {} {
+        xywh {54 14 70 16} box FLAT_BOX color {97 47}
+      }
+      Fl_Box {} {
+        xywh {68 30 42 50} box DOWN_BOX color {6 47}
+      }
+      Fl_Box {} {
+        xywh {54 20 70 20} box ROUND_UP_BOX color {6 47} labelcolor 6 align 16
+      }
+      Fl_Box {} {
+        label fluid
+        xywh {24 110 130 90} box ROUND_UP_BOX color {14 47} labeltype SHADOW_LABEL labelfont 1 labelsize 40 labelcolor 6
+      }
+      Fl_Box {} {
+        xywh {67 110 44 10} box FLAT_BOX color {14 47}
+      }
+      Fl_Box {} {
+        label {` }
+        xywh {84 120 15 15} box OVAL_BOX color {6 47} labelsize 20 labelcolor 7 align 17
+      }
+      Fl_Box {} {
+        label {` }
+        xywh {75 105 15 15} box OVAL_BOX color {6 47} labelsize 20 labelcolor 7 align 17
+      }
+      Fl_Box {} {
+        label {` }
+        xywh {89 85 15 15} box OVAL_BOX color {6 47} labelsize 20 labelcolor 7 align 17
+      }
+      Fl_Box {} {
+        label {Fltk User
+Interface
+Designer
+Version 1.00}
+        xywh {159 27 131 95} box OVAL_BOX color {12 47} labeltype SHADOW_LABEL labelfont 1 labelsize 18 labelcolor 7
+      }
+      Fl_Button {} {
+        label {©1998 Bill Spitzak
+(click here)}
+        callback {display_group->hide();
+copyright_box->show();}
+        xywh {169 138 115 30} box THIN_UP_BOX labelsize 10 labelcolor 136
+      }
+    }
+    Fl_Box copyright_box {selected
+      xywh {5 5 300 210} labelsize 8 labelcolor 6 align 148 hide
+      code0 {o->label(copyright);}
+    }
+    Fl_Return_Button {} {
+      label OK
+      callback {((Fl_Window*)(o->parent()))->hide();}
+      xywh {168 182 116 22} labelsize 10
+    }
+  }
+} 
diff --git a/fluid/about_panel.h b/fluid/about_panel.h
new file mode 100644
index 000000000..7113cf5cf
--- /dev/null
+++ b/fluid/about_panel.h
@@ -0,0 +1,12 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+extern Fl_Window *about_panel;
+extern Fl_Group *display_group;
+extern Fl_Box *copyright_box;
+Fl_Window* make_about_panel(const char *copyright);
diff --git a/fluid/alignment_panel.cxx b/fluid/alignment_panel.cxx
new file mode 100644
index 000000000..fa8c7c089
--- /dev/null
+++ b/fluid/alignment_panel.cxx
@@ -0,0 +1,73 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "alignment_panel.H"
+
+Fl_Window *alignment_window;
+
+Fl_Input *horizontal_input;
+
+Fl_Input *vertical_input;
+
+Fl_Input *snap_input;
+
+static void cb_close(Fl_Button*, void*) {
+  alignment_window->hide();
+}
+
+Fl_Input *header_file_input;
+
+Fl_Input *code_file_input;
+
+Fl_Window* make_alignment_window() {
+  Fl_Window *w;
+  { Fl_Window* o = alignment_window = w = new Fl_Window(210, 282, "fluid Preferences");
+    { Fl_Box* o = new Fl_Box(10, 20, 190, 100, "ALIGNMENT:");
+      o->box(FL_ENGRAVED_FRAME);
+      o->labelsize(10);
+      o->align(5);
+    }
+    { Fl_Input* o = horizontal_input = new Fl_Input(90, 30, 100, 20, "horizontal:");
+      o->type(2);
+      o->box(FL_THIN_DOWN_BOX);
+      o->callback((Fl_Callback*)alignment_cb, (void*)(1));
+      o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);
+    }
+    { Fl_Input* o = vertical_input = new Fl_Input(90, 60, 100, 20, "vertical:");
+      o->type(2);
+      o->box(FL_THIN_DOWN_BOX);
+      o->callback((Fl_Callback*)alignment_cb, (void*)(2));
+      o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);
+    }
+    { Fl_Input* o = snap_input = new Fl_Input(90, 90, 100, 20, "snap:");
+      o->type(2);
+      o->box(FL_THIN_DOWN_BOX);
+      o->callback((Fl_Callback*)alignment_cb, (void*)(3));
+      o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);
+    }
+    { Fl_Button* o = new Fl_Button(10, 250, 190, 20, "close");
+      o->callback((Fl_Callback*)cb_close);
+      w->hotspot(o);
+    }
+    { Fl_Box* o = new Fl_Box(10, 140, 190, 100, "OUTPUT FILE NAMES:");
+      o->box(FL_ENGRAVED_FRAME);
+      o->labelsize(10);
+      o->align(5);
+    }
+    { Fl_Box* o = new Fl_Box(10, 140, 190, 40, "Use \"name.ext\" to set name, use just \".ext\" to set only extension.");
+      o->labelsize(10);
+      o->align(128);
+    }
+    { Fl_Input* o = header_file_input = new Fl_Input(90, 180, 100, 20, "header file:");
+      o->box(FL_THIN_DOWN_BOX);
+      o->callback((Fl_Callback*)header_input_cb, (void*)(1));
+      o->when(1);
+    }
+    { Fl_Input* o = code_file_input = new Fl_Input(90, 210, 100, 20, "code file:");
+      o->box(FL_THIN_DOWN_BOX);
+      o->callback((Fl_Callback*)code_input_cb, (void*)(1));
+      o->when(1);
+    }
+    o->end();
+  }
+  return w;
+}
diff --git a/fluid/alignment_panel.fl b/fluid/alignment_panel.fl
new file mode 100644
index 000000000..c2e7f9286
--- /dev/null
+++ b/fluid/alignment_panel.fl
@@ -0,0 +1,65 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 0.99 
+header_name {.H} 
+code_name {.C} 
+gridx 10 
+gridy 10 
+snap 3
+Function {make_alignment_window()} {open
+} {
+  Fl_Window alignment_window {
+    label {fluid Preferences} open selected
+    xywh {303 187 210 282} visible
+  } {
+    Fl_Box {} {
+      label {ALIGNMENT:}
+      xywh {10 20 190 100} box ENGRAVED_FRAME labelsize 10 align 5
+    }
+    Fl_Input horizontal_input {
+      label {horizontal:}
+      user_data 1 user_data_type long
+      callback alignment_cb
+      xywh {90 30 100 20} type Int box THIN_DOWN_BOX
+      code0 {o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);}
+    }
+    Fl_Input vertical_input {
+      label {vertical:}
+      user_data 2 user_data_type long
+      callback alignment_cb
+      xywh {90 60 100 20} type Int box THIN_DOWN_BOX
+      code0 {o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);}
+    }
+    Fl_Input snap_input {
+      label {snap:}
+      user_data 3 user_data_type long
+      callback alignment_cb
+      xywh {90 90 100 20} type Int box THIN_DOWN_BOX
+      code0 {o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);}
+    }
+    Fl_Button {} {
+      label close
+      callback {alignment_window->hide();}
+      xywh {10 250 190 20} hotspot
+    }
+    Fl_Box {} {
+      label {OUTPUT FILE NAMES:}
+      xywh {10 140 190 100} box ENGRAVED_FRAME labelsize 10 align 5
+    }
+    Fl_Box {} {
+      label {Use "name.ext" to set name, use just ".ext" to set only extension.}
+      xywh {10 140 190 40} labelsize 10 align 128
+    }
+    Fl_Input header_file_input {
+      label {header file:}
+      user_data 1 user_data_type {void*}
+      callback header_input_cb
+      xywh {90 180 100 20} box THIN_DOWN_BOX when 1
+    }
+    Fl_Input code_file_input {
+      label {code file:}
+      user_data 1 user_data_type {void*}
+      callback code_input_cb
+      xywh {90 210 100 20} box THIN_DOWN_BOX when 1
+    }
+  }
+} 
diff --git a/fluid/alignment_panel.h b/fluid/alignment_panel.h
new file mode 100644
index 000000000..437d7640f
--- /dev/null
+++ b/fluid/alignment_panel.h
@@ -0,0 +1,17 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include 
+#include 
+#include 
+#include 
+#include 
+extern void alignment_cb(Fl_Input*, long);
+extern void code_input_cb(Fl_Input*, void*);
+extern void header_input_cb(Fl_Input*, void*);
+extern Fl_Window *alignment_window;
+extern Fl_Input *horizontal_input;
+extern Fl_Input *vertical_input;
+extern Fl_Input *snap_input;
+extern Fl_Input *header_file_input;
+extern Fl_Input *code_file_input;
+Fl_Window* make_alignment_window();
diff --git a/fluid/class.C b/fluid/class.C
new file mode 100644
index 000000000..e547cf2a7
--- /dev/null
+++ b/fluid/class.C
@@ -0,0 +1,123 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "class.H"
+
+inline void essai::cb_button_i(Fl_Button*, void*) {
+  printf("button\n");
+}
+void essai::cb_button(Fl_Button* o, void* v) {
+  ((essai*)(o->parent()->user_data()))->cb_button_i(o,v);
+}
+
+inline void essai::cb_unnamed_i(Fl_Button*, void*) {
+  printf("unnamed\n");
+}
+void essai::cb_unnamed(Fl_Button* o, void* v) {
+  ((essai*)(o->parent()->user_data()))->cb_unnamed_i(o,v);
+}
+
+inline void essai::cb_src_i(Fl_Button*, void*) {
+  (new essai)->win->show();
+}
+void essai::cb_src(Fl_Button* o, void* v) {
+  ((essai*)(o->parent()->user_data()))->cb_src_i(o,v);
+}
+
+#include 
+static char bits_ew_mask[] = {  
+0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 28, 56, 254, 127, 255, 255, 255, 255, 254, 127, 28, 56, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0
+};
+static Fl_Bitmap bitmap_ew_mask(bits_ew_mask, 16, 16);
+
+inline void essai::cb_change_i(Fl_Menu_*, void*) {
+  cbox->color(cbox->color()+1);
+cbox->redraw();
+}
+void essai::cb_change(Fl_Menu_* o, void* v) {
+  ((essai*)(o->parent()->user_data()))->cb_change_i(o,v);
+}
+
+Fl_Menu_Item essai::menu_menu[] = {
+ {"change color", 0,  (Fl_Callback*)essai::cb_change, 0, 0, 0, 3, 14, 0},
+ {"radio off", 0,  0, 0, 8, 0, 3, 14, 0},
+ {"radio on", 0,  0, 0, 12, 0, 3, 14, 0},
+ {"toggle off", 0,  0, 0, 2, 0, 3, 14, 0},
+ {"toggle on", 0,  0, 0, 6, 0, 3, 14, 0},
+ {"new item 5", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 6", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 7", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 8", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 9", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 10", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 11", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 12", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 13", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 14", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 15", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 16", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 17", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 18", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 19", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 20", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 21", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 22", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 23", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"new item 24", 0,  0, 0, 0, 0, 3, 14, 0},
+ {0}
+};
+
+inline void essai::cb_color_i(Fl_Button*, void*) {
+  cbox->color(cbox->color()+1);
+cbox->redraw();
+}
+void essai::cb_color(Fl_Button* o, void* v) {
+  ((essai*)(o->parent()->user_data()))->cb_color_i(o,v);
+}
+
+inline void essai::cb_delete_i(Fl_Button*, void*) {
+  delete this;
+}
+void essai::cb_delete(Fl_Button* o, void* v) {
+  ((essai*)(o->parent()->user_data()))->cb_delete_i(o,v);
+}
+
+essai::essai() {
+  Fl_Window *w;
+  { Fl_Window* o = win = w = new Fl_Window(282, 193);
+    o->user_data((void*)(this));
+    { Fl_Button* o = new Fl_Button(10, 10, 55, 35, "button");
+      o->callback((Fl_Callback*)cb_button);
+    }
+    { Fl_Button* o = new Fl_Button(10, 45, 145, 35, "unnamed");
+      o->callback((Fl_Callback*)cb_unnamed);
+    }
+    { Fl_Button* o = new Fl_Button(10, 80, 145, 35);
+      bitmap_ew_mask.label(o);
+      o->callback((Fl_Callback*)cb_src);
+    }
+    { Fl_Menu_Button* o = new Fl_Menu_Button(10, 115, 145, 35, "menu");
+      o->menu(menu_menu);
+    }
+    { Fl_Button* o = new Fl_Button(70, 150, 85, 35, "color");
+      o->callback((Fl_Callback*)cb_color);
+    }
+    new Fl_Button(200, 10, 55, 35, "boring");
+    { Fl_Box* o = cbox = new Fl_Box(165, 80, 55, 35, "color");
+      o->box(FL_FLAT_BOX);
+    }
+    { Fl_Button* o = new Fl_Button(200, 125, 55, 35, "delete this");
+      o->callback((Fl_Callback*)cb_delete);
+    }
+    button_variable = new Fl_Button(100, 10, 55, 35, "button");
+    w->end();
+  }
+}
+
+essai::~essai() {
+  delete win;
+}
+
+int main(int argc, char **argv) {
+  essai E; E.win->show();
+  return Fl::run();
+}
diff --git a/fluid/class.H b/fluid/class.H
new file mode 100644
index 000000000..302ce0486
--- /dev/null
+++ b/fluid/class.H
@@ -0,0 +1,34 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+class essai {
+public:
+  essai();
+  Fl_Window *win;
+private:
+  inline void cb_button_i(Fl_Button*, void*);
+  static void cb_button(Fl_Button*, void*);
+  inline void cb_unnamed_i(Fl_Button*, void*);
+  static void cb_unnamed(Fl_Button*, void*);
+  inline void cb_src_i(Fl_Button*, void*);
+  static void cb_src(Fl_Button*, void*);
+  static Fl_Menu_Item menu_menu[];
+  inline void cb_change_i(Fl_Menu_*, void*);
+  static void cb_change(Fl_Menu_*, void*);
+  inline void cb_color_i(Fl_Button*, void*);
+  static void cb_color(Fl_Button*, void*);
+public:
+  Fl_Box *cbox;
+private:
+  inline void cb_delete_i(Fl_Button*, void*);
+  static void cb_delete(Fl_Button*, void*);
+public:
+  Fl_Button *button_variable;
+  ~essai();
+};
diff --git a/fluid/code.cxx b/fluid/code.cxx
new file mode 100644
index 000000000..171593fff
--- /dev/null
+++ b/fluid/code.cxx
@@ -0,0 +1,263 @@
+/*	code.C
+
+	Code to write .C files from Fluid
+
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include "Fl_Type.H"
+
+static FILE *code_file;
+static FILE *header_file;
+
+// return true if c can be in a C identifier.  I needed this so
+// it is not messed up by locale settings:
+int is_id(char c) {
+  return c>='a' && c<='z' || c>='A' && c<='Z' || c>='0' && c<='9' || c=='_';
+}
+
+////////////////////////////////////////////////////////////////
+// Generate unique but human-readable identifiers:
+
+struct id {
+  char* text;
+  void* object;
+  id *left, *right;
+  id (const char* t, void* o) : text(strdup(t)), object(o) {left = right = 0;}
+  ~id();
+};
+
+id::~id() {
+  delete left;
+  free((void *)text);
+  delete right;
+}
+
+static id* id_root;
+
+const char* unique_id(void* o, const char* type, const char* name, const char* label) {
+  char buffer[128];
+  char* q = buffer;
+  while (*type) *q++ = *type++;
+  *q++ = '_';
+  const char* n = name;
+  if (!n || !*n) n = label;
+  if (n && *n) {
+    while (!is_id(*n)) n++;
+    while (is_id(*n)) *q++ = *n++;
+  }
+  *q = 0;
+  // okay, search the tree and see if the name was already used:
+  id** p = &id_root;
+  int which = 0;
+  while (*p) {
+    int i = strcmp(buffer, (*p)->text);
+    if (!i) {
+      if ((*p)->object == o) return (*p)->text;
+      // already used, we need to pick a new name:
+      sprintf(q,"%x",++which);
+      p = &id_root;
+      continue;
+    }
+    else if (i < 0) p = &((*p)->left);
+    else p  = &((*p)->right);
+  }
+  *p = new id(buffer, o);
+  return (*p)->text;
+}
+
+////////////////////////////////////////////////////////////////
+// return current indentation:
+
+static const char* spaces = "                ";
+int indentation;
+const char* indent() {
+  int i = indentation; if (i>16) i = 16;
+  return spaces+16-i;
+}
+
+////////////////////////////////////////////////////////////////
+// declarations/include files:
+// These are sorted in alphabetical order and only included once each:
+// Relies on '#' being less than any letter to put #include first.
+// I use a binary tree to sort these out.
+
+struct included {
+  char *text;
+  included *left, *right;
+  included(const char *t) {
+    text = strdup(t);
+    left = right = 0;
+  }
+  ~included();
+};
+
+included::~included() {
+  delete left;
+  fprintf(header_file,"%s\n",text);
+  free((void *)text);
+  delete right;
+}
+static included *included_root;
+
+int write_declare(const char *format, ...) {
+  va_list args;
+  char buf[1024];
+  va_start(args, format);
+  vsprintf(buf, format, args);
+  va_end(args);
+  included **p = &included_root;
+  while (*p) {
+    int i = strcmp(buf,(*p)->text);
+    if (!i) return 0;
+    else if (i < 0) p = &((*p)->left);
+    else p  = &((*p)->right);
+  }
+  *p = new included(buf);
+  return 1;
+}
+
+////////////////////////////////////////////////////////////////
+
+// silly thing to prevent declaring unused variables:
+// When this symbol is on, all attempts to write code don't write
+// anything, but set a variable if it looks like the varaible "o" is used:
+int varused_test;
+int varused;
+
+// write an array of C characters (adds a null):
+void write_cstring(const char *w, int length) {
+  if (varused_test) return;
+  const char *e = w+length;
+  int linelength = 1;
+  putc('\"', code_file);
+  for (; w < e;) {
+    if (linelength >= 75) {fputs("\\\n",code_file); linelength = 0;}
+    int c = *w++;
+    switch (c) {
+    case '\b': c = 'b'; goto QUOTED;
+    case '\t': c = 't'; goto QUOTED;
+    case '\n': c = 'n'; goto QUOTED;
+    case '\f': c = 'f'; goto QUOTED;
+    case '\r': c = 'r'; goto QUOTED;
+    case '\"':
+    case '\'':
+    case '\\':
+    QUOTED:
+      putc('\\',code_file);
+      putc(c,code_file);
+      linelength += 2;
+      break;
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+      if (*w < '0' || *w > '9') {c += '0'; goto QUOTED;}
+      // else fall through:
+    default:
+      if (c < ' ' || c >= 127) {
+      QUOTENEXT:
+	fprintf(code_file, "\\x%02x",c&255);
+	linelength += 4;
+	c = *w;
+	if (w < e && (c>='0'&&c<='9' || c>='a'&&c<='f' || c>='A'&&c<='F')) {
+	  w++; goto QUOTENEXT;
+	}
+      } else {
+	putc(c,code_file);
+	linelength++;
+      }
+      break;
+    }
+  }
+  putc('\"', code_file);
+}
+
+// write a C string, quoting characters if necessary:
+void write_cstring(const char *w) {write_cstring(w,strlen(w));}
+
+void write_c(const char* format,...) {
+  if (varused_test) {varused = 1; return;}
+  va_list args;
+  va_start(args, format);
+  vfprintf(code_file, format, args);
+  va_end(args);
+}
+
+void write_h(const char* format,...) {
+  if (varused_test) return;
+  va_list args;
+  va_start(args, format);
+  vfprintf(header_file, format, args);
+  va_end(args);
+}
+
+#include 
+int write_number;
+
+// recursively dump code, putting children between the two parts
+// of the parent code:
+static Fl_Type* write_code(Fl_Type* p) {
+  p->write_code1();
+  Fl_Type* q;
+  for (q = p->next; q && q->level > p->level;) q = write_code(q);
+  p->write_code2();
+  return q;
+}
+
+int write_code(const char *s, const char *t) {
+  write_number++;
+  delete id_root; id_root = 0;
+  indentation = 0;
+  if (!s) code_file = stdout;
+  else {
+    FILE *f = fopen(s,"w");
+    if (!f) return 0;
+    code_file = f;
+  }
+  if (!t) header_file = stdout;
+  else {
+    FILE *f = fopen(t,"w");
+    if (!f) {fclose(code_file); return 0;}
+    header_file = f;
+  }
+  const char *hdr = "\
+// generated by Fast Light User Interface Designer (fluid) version %.2f\n\n";
+  fprintf(header_file, hdr, FL_VERSION);
+  fprintf(code_file, hdr, FL_VERSION);
+  Fl_Type *p;
+
+  for (p = Fl_Type::first; p; p = p->next) p->write_declare();
+  delete included_root; included_root = 0;
+
+  if (t) write_c("#include \"%s\"\n", filename_name(t));
+  for (p = Fl_Type::first; p; p = p->next) p->write_static();
+  for (p = Fl_Type::first; p;) p = write_code(p);
+
+  if (!s) return 1;
+  int x = fclose(code_file);
+  code_file = 0;
+  int y = fclose(header_file);
+  header_file = 0;
+  return x >= 0 && y >= 0;
+}
+
+////////////////////////////////////////////////////////////////
+
+void Fl_Type::write_declare() {}
+void Fl_Type::write_static() {}
+void Fl_Type::write_code1() {
+  write_h("// Header for %s\n", title());
+  write_c("// Code for %s\n", title());
+}
+void Fl_Type::write_code2() {}
diff --git a/fluid/factory.cxx b/fluid/factory.cxx
new file mode 100644
index 000000000..5a5ff5383
--- /dev/null
+++ b/fluid/factory.cxx
@@ -0,0 +1,651 @@
+/*	factory.C
+
+	Type classes for most of the fltk widgets.  Most of the work
+	is done by code in Fl_Widget_Type.C.  Also a factory instance
+	of each of these type classes.
+
+	This file also contains the "new" menu, which has a pointer
+	to a factory instance for every class (both the ones defined
+	here and ones in other files)
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if defined(WIN32) || defined(__EMX__)
+#define strcasecmp stricmp
+#endif
+
+#include "Fl_Widget_Type.H"
+
+////////////////////////////////////////////////////////////////
+
+#include 
+class Fl_Box_Type : public Fl_Widget_Type {
+public:
+  virtual const char *type_name() {return "Fl_Box";}
+  Fl_Widget *widget(int x,int y,int w, int h) {
+    return new Fl_Box(x,y,w,h,"label");}
+  Fl_Widget_Type *_make() {return new Fl_Box_Type();}
+};
+static Fl_Box_Type Fl_Box_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+static Fl_Menu_Item button_type_menu[] = {
+  {"Normal",0,0,(void*)0},
+  {"Toggle",0,0,(void*)FL_TOGGLE_BUTTON},
+  {"Radio",0,0,(void*)FL_RADIO_BUTTON},
+  {0}};
+class Fl_Button_Type : public Fl_Widget_Type {
+  Fl_Menu_Item *subtypes() {return button_type_menu;}
+public:
+  virtual const char *type_name() {return "Fl_Button";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Button(x,y,w,h,"button");}
+  Fl_Widget_Type *_make() {return new Fl_Button_Type();}
+  int is_button() const {return 1;}
+};
+static Fl_Button_Type Fl_Button_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+class Fl_Return_Button_Type : public Fl_Button_Type {
+public:
+  virtual const char *type_name() {return "Fl_Return_Button";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Return_Button(x,y,w,h,0);}
+  Fl_Widget_Type *_make() {return new Fl_Return_Button_Type();}
+};
+static Fl_Return_Button_Type Fl_Return_Button_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+class Fl_Repeat_Button_Type : public Fl_Widget_Type {
+public:
+  virtual const char *type_name() {return "Fl_Repeat_Button";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Repeat_Button(x,y,w,h,0);}
+  Fl_Widget_Type *_make() {return new Fl_Repeat_Button_Type();}
+};
+static Fl_Repeat_Button_Type Fl_Repeat_Button_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+class Fl_Light_Button_Type : public Fl_Button_Type {
+public:
+  virtual const char *type_name() {return "Fl_Light_Button";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Light_Button(x,y,w,h,"button");}
+  Fl_Widget_Type *_make() {return new Fl_Light_Button_Type();}
+};
+static Fl_Light_Button_Type Fl_Light_Button_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+class Fl_Check_Button_Type : public Fl_Button_Type {
+public:
+  virtual const char *type_name() {return "Fl_Check_Button";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Check_Button(x,y,w,h,"button");}
+  Fl_Widget_Type *_make() {return new Fl_Check_Button_Type();}
+};
+static Fl_Check_Button_Type Fl_Check_Button_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+class Fl_Round_Button_Type : public Fl_Button_Type {
+public:
+  virtual const char *type_name() {return "Fl_Round_Button";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Round_Button(x,y,w,h,"button");}
+  Fl_Widget_Type *_make() {return new Fl_Round_Button_Type();}
+};
+static Fl_Round_Button_Type Fl_Round_Button_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+static Fl_Menu_Item browser_type_menu[] = {
+  {"No Select",0,0,(void*)FL_NORMAL_BROWSER},
+  {"Select",0,0,(void*)FL_SELECT_BROWSER},
+  {"Hold",0,0,(void*)FL_HOLD_BROWSER},
+  {"Multi",0,0,(void*)FL_MULTI_BROWSER},
+  {0}};
+class Fl_Browser_Type : public Fl_Widget_Type {
+  Fl_Menu_Item *subtypes() {return browser_type_menu;}
+  int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+    Fl_Browser *o = (Fl_Browser*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+    switch (w) {
+    case 4:
+    case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break;
+    case 1: o->textfont(f); break;
+    case 2: o->textsize(s); break;
+    case 3: o->textcolor(c); break;
+    }
+    return 1;
+  }
+public:
+  virtual const char *type_name() {return "Fl_Browser";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    Fl_Browser* b = new Fl_Browser(x,y,w,h);
+    char buffer[20];
+    for (int i = 1; i <= 20; i++) {
+      sprintf(buffer,"Browser Line %d",i);
+      b->add(buffer);
+    }
+    return b;
+  }
+  Fl_Widget_Type *_make() {return new Fl_Browser_Type();}
+};
+static Fl_Browser_Type Fl_Browser_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+static Fl_Menu_Item counter_type_menu[] = {
+  {"Normal",0,0,(void*)FL_NORMAL_COUNTER},
+  {"Simple",0,0,(void*)FL_SIMPLE_COUNTER},
+  {0}};
+class Fl_Counter_Type : public Fl_Widget_Type {
+  Fl_Menu_Item *subtypes() {return counter_type_menu;}
+  int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+    Fl_Counter *o = (Fl_Counter*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+    switch (w) {
+    case 4:
+    case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break;
+    case 1: o->textfont(f); break;
+    case 2: o->textsize(s); break;
+    case 3: o->textcolor(c); break;
+    }
+    return 1;
+  }
+  int is_valuator() const {return 1;}
+public:
+  virtual const char *type_name() {return "Fl_Counter";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Counter(x,y,w,h,"counter:");}
+  Fl_Widget_Type *_make() {return new Fl_Counter_Type();}
+};
+static Fl_Counter_Type Fl_Counter_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+static Fl_Menu_Item input_type_menu[] = {
+  {"Normal",0,0,(void*)FL_NORMAL_INPUT},
+  {"Multiline",0,0,(void*)FL_MULTILINE_INPUT},
+  {"Secret",0,0,(void*)FL_SECRET_INPUT},
+  {"Int",0,0,(void*)FL_INT_INPUT},
+  {"Float",0,0,(void*)FL_FLOAT_INPUT},
+  {0}};
+class Fl_Input_Type : public Fl_Widget_Type {
+  Fl_Menu_Item *subtypes() {return input_type_menu;}
+  int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+    Fl_Input_ *o = (Fl_Input_*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+    switch (w) {
+    case 4:
+    case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break;
+    case 1: o->textfont(f); break;
+    case 2: o->textsize(s); break;
+    case 3: o->textcolor(c); break;
+    }
+    return 1;
+  }
+public:
+  virtual const char *type_name() {return "Fl_Input";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    Fl_Input *o = new Fl_Input(x,y,w,h,"input:");
+    o->value("Text Input");
+    return o;
+  }
+  Fl_Widget_Type *_make() {return new Fl_Input_Type();}
+};
+static Fl_Input_Type Fl_Input_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+class Fl_Clock_Type : public Fl_Widget_Type {
+public:
+  virtual const char *type_name() {return "Fl_Clock";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Clock(x,y,w,h);}
+  Fl_Widget_Type *_make() {return new Fl_Clock_Type();}
+};
+static Fl_Clock_Type Fl_Clock_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+class Fl_Adjuster_Type : public Fl_Widget_Type {
+  int is_valuator() const {return 1;}
+public:
+  virtual const char *type_name() {return "Fl_Adjuster";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Adjuster(x,y,w,h);}
+  Fl_Widget_Type *_make() {return new Fl_Adjuster_Type();}
+};
+static Fl_Adjuster_Type Fl_Adjuster_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+static Fl_Menu_Item dial_type_menu[] = {
+  {"Dot",0,0,(void*)0},
+  {"Line",0,0,(void*)FL_LINE_DIAL},
+  {"Fill",0,0,(void*)FL_FILL_DIAL},
+  {0}};
+class Fl_Dial_Type : public Fl_Widget_Type {
+  Fl_Menu_Item *subtypes() {return dial_type_menu;}
+  int is_valuator() const {return 1;}
+public:
+  virtual const char *type_name() {return "Fl_Dial";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Dial(x,y,w,h);}
+  Fl_Widget_Type *_make() {return new Fl_Dial_Type();}
+};
+static Fl_Dial_Type Fl_Dial_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+static Fl_Menu_Item roller_type_menu[] = {
+  {"Vertical",0,0,(void*)0},
+  {"Horizontal",0,0,(void*)FL_HORIZONTAL},
+  {0}};
+class Fl_Roller_Type : public Fl_Widget_Type {
+  Fl_Menu_Item *subtypes() {return roller_type_menu;}
+  int is_valuator() const {return 1;}
+public:
+  virtual const char *type_name() {return "Fl_Roller";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Roller(x,y,w,h);}
+  Fl_Widget_Type *_make() {return new Fl_Roller_Type();}
+};
+static Fl_Roller_Type Fl_Roller_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+static Fl_Menu_Item slider_type_menu[] = {
+  {"Vertical",0,0,(void*)FL_VERT_SLIDER},
+  {"Horizontal",0,0,(void*)FL_HOR_SLIDER},
+  {"Vert Fill",0,0,(void*)FL_VERT_FILL_SLIDER},
+  {"Horz Fill",0,0,(void*)FL_HOR_FILL_SLIDER},
+  {"Vert Knob",0,0,(void*)FL_VERT_NICE_SLIDER},
+  {"Horz Knob",0,0,(void*)FL_HOR_NICE_SLIDER},
+  {0}};
+class Fl_Slider_Type : public Fl_Widget_Type {
+  Fl_Menu_Item *subtypes() {return slider_type_menu;}
+  int is_valuator() const {return 2;}
+public:
+  virtual const char *type_name() {return "Fl_Slider";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Slider(x,y,w,h);}
+  Fl_Widget_Type *_make() {return new Fl_Slider_Type();}
+};
+static Fl_Slider_Type Fl_Slider_type;
+
+static Fl_Menu_Item scrollbar_type_menu[] = {
+  {"Vertical",0,0,(void*)FL_VERT_SLIDER},
+  {"Horizontal",0,0,(void*)FL_HOR_SLIDER},
+  {0}};
+class Fl_Scrollbar_Type : public Fl_Slider_Type {
+  Fl_Menu_Item *subtypes() {return scrollbar_type_menu;}
+public:
+  virtual const char *type_name() {return "Fl_Scrollbar";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Scrollbar(x,y,w,h);}
+  Fl_Widget_Type *_make() {return new Fl_Scrollbar_Type();}
+};
+static Fl_Scrollbar_Type Fl_Scrollbar_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+static Fl_Menu_Item output_type_menu[] = {
+  {"Normal",0,0,(void*)FL_NORMAL_INPUT},
+  {"Multiline",0,0,(void*)FL_MULTILINE_INPUT},
+  {0}};
+class Fl_Output_Type : public Fl_Input_Type {
+  Fl_Menu_Item *subtypes() {return output_type_menu;}
+public:
+  virtual const char *type_name() {return "Fl_Output";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    Fl_Output *o = new Fl_Output(x,y,w,h,"output:");
+    o->value("Text Output");
+    return o;
+  }
+  Fl_Widget_Type *_make() {return new Fl_Output_Type();}
+};
+static Fl_Output_Type Fl_Output_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+class Fl_Value_Input_Type : public Fl_Widget_Type {
+public:
+  virtual const char *type_name() {return "Fl_Value_Input";}
+  int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+    Fl_Value_Input *o = (Fl_Value_Input*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+    switch (w) {
+    case 4:
+    case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break;
+    case 1: o->textfont(f); break;
+    case 2: o->textsize(s); break;
+    case 3: o->textcolor(c); break;
+    }
+    return 1;
+  }
+  int is_valuator() const {return 1;}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    Fl_Value_Input *o = new Fl_Value_Input(x,y,w,h,"value:");
+    return o;
+  }
+  Fl_Widget_Type *_make() {return new Fl_Value_Input_Type();}
+};
+static Fl_Value_Input_Type Fl_Value_Input_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+class Fl_Value_Output_Type : public Fl_Widget_Type {
+public:
+  virtual const char *type_name() {return "Fl_Value_Output";}
+  int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+    Fl_Value_Output *o = (Fl_Value_Output*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+    switch (w) {
+    case 4:
+    case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break;
+    case 1: o->textfont(f); break;
+    case 2: o->textsize(s); break;
+    case 3: o->textcolor(c); break;
+    }
+    return 1;
+  }
+  int is_valuator() const {return 1;}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    Fl_Value_Output *o = new Fl_Value_Output(x,y,w,h,"value:");
+    return o;
+  }
+  Fl_Widget_Type *_make() {return new Fl_Value_Output_Type();}
+};
+static Fl_Value_Output_Type Fl_Value_Output_type;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+class Fl_Value_Slider_Type : public Fl_Slider_Type {
+  int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) {
+    Fl_Value_Slider *o = (Fl_Value_Slider*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o);
+    switch (w) {
+    case 4:
+    case 0: f = o->textfont(); s = o->textsize(); c = o->textcolor(); break;
+    case 1: o->textfont(f); break;
+    case 2: o->textsize(s); break;
+    case 3: o->textcolor(c); break;
+    }
+    return 1;
+  }
+public:
+  virtual const char *type_name() {return "Fl_Value_Slider";}
+  Fl_Widget *widget(int x,int y,int w,int h) {
+    return new Fl_Value_Slider(x,y,w,h);}
+  Fl_Widget_Type *_make() {return new Fl_Value_Slider_Type();}
+};
+static Fl_Value_Slider_Type Fl_Value_Slider_type;
+
+////////////////////////////////////////////////////////////////
+
+extern class Fl_Function_Type Fl_Function_type;
+extern class Fl_Code_Type Fl_Code_type;
+extern class Fl_CodeBlock_Type Fl_CodeBlock_type;
+extern class Fl_Decl_Type Fl_Decl_type;
+extern class Fl_DeclBlock_Type Fl_DeclBlock_type;
+extern class Fl_Class_Type Fl_Class_type;
+extern class Fl_Window_Type Fl_Window_type;
+extern class Fl_Group_Type Fl_Group_type;
+extern class Fl_Tabs_Type Fl_Tabs_type;
+extern class Fl_Scroll_Type Fl_Scroll_type;
+extern class Fl_Tile_Type Fl_Tile_type;
+extern class Fl_Choice_Type Fl_Choice_type;
+extern class Fl_Menu_Bar_Type Fl_Menu_Bar_type;
+extern class Fl_Menu_Button_Type Fl_Menu_Button_type;
+extern class Fl_Menu_Item_Type Fl_Menu_Item_type;
+extern class Fl_Submenu_Type Fl_Submenu_type;
+
+extern void select(Fl_Type *,int);
+extern void select_only(Fl_Type *);
+
+static void cb(Fl_Widget *, void *v) {
+  Fl_Type *t = ((Fl_Type*)v)->make();
+  if (t) {select_only(t); modflag = 1; t->open();}
+}
+
+Fl_Menu_Item New_Menu[] = {
+{"code",0,0,0,FL_SUBMENU},
+  {"function/method",0,cb,(void*)&Fl_Function_type},
+  {"code",0,cb,(void*)&Fl_Code_type},
+  {"code block",0,cb,(void*)&Fl_CodeBlock_type},
+  {"declaration",0,cb,(void*)&Fl_Decl_type},
+  {"declaration block",0,cb,(void*)&Fl_DeclBlock_type},
+  {"class",0,cb,(void*)&Fl_Class_type},
+{0},
+{"group",0,0,0,FL_SUBMENU},
+  {0,0,cb,(void*)&Fl_Window_type},
+  {0,0,cb,(void*)&Fl_Group_type},
+  {0,0,cb,(void*)&Fl_Tabs_type},
+  {0,0,cb,(void*)&Fl_Scroll_type},
+  {0,0,cb,(void*)&Fl_Tile_type},
+{0},
+{"buttons",0,0,0,FL_SUBMENU},
+  {0,0,cb,(void*)&Fl_Button_type},
+  {0,0,cb,(void*)&Fl_Return_Button_type},
+  {0,0,cb,(void*)&Fl_Light_Button_type},
+  {0,0,cb,(void*)&Fl_Check_Button_type},
+  {0,0,cb,(void*)&Fl_Round_Button_type},
+  {0,0,cb,(void*)&Fl_Repeat_Button_type},
+{0},
+{"valuators",0,0,0,FL_SUBMENU},
+  {0,0,cb,(void*)&Fl_Slider_type},
+  {0,0,cb,(void*)&Fl_Scrollbar_type},
+  {0,0,cb,(void*)&Fl_Value_Slider_type},
+  {0,0,cb,(void*)&Fl_Adjuster_type},
+  {0,0,cb,(void*)&Fl_Counter_type},
+  {0,0,cb,(void*)&Fl_Dial_type},
+  {0,0,cb,(void*)&Fl_Roller_type},
+  {0,0,cb,(void*)&Fl_Value_Input_type},
+  {0,0,cb,(void*)&Fl_Value_Output_type},
+{0},
+{"text",0,0,0,FL_SUBMENU},
+  {0,0,cb,(void*)&Fl_Input_type},
+  {0,0,cb,(void*)&Fl_Output_type},
+{0},
+{"menus",0,0,0,FL_SUBMENU},
+  {0,0,cb,(void*)&Fl_Menu_Bar_type},
+  {0,0,cb,(void*)&Fl_Menu_Button_type},
+  {0,0,cb,(void*)&Fl_Choice_type},
+  {0,0,cb, (void*)&Fl_Submenu_type},
+  {0,0,cb, (void*)&Fl_Menu_Item_type},
+{0},
+{"other",0,0,0,FL_SUBMENU},
+  {0,0,cb,(void*)&Fl_Browser_type},
+  {0,0,cb,(void*)&Fl_Box_type},
+  {0,0,cb,(void*)&Fl_Clock_type},
+{0},
+{0}};
+
+void fill_in_New_Menu() {
+  for (unsigned i = 0; i < sizeof(New_Menu)/sizeof(*New_Menu); i++) {
+    Fl_Menu_Item *m = New_Menu+i;
+    if (m->user_data() && !m->text) {
+      const char *n = ((Fl_Type*)(m->user_data()))->type_name();
+      if (!strncmp(n,"Fl_",3)) n += 3;
+      m->text = n;
+    }
+  }
+}
+
+// use keyword to pick the type, this is used to parse files:
+int reading_file;
+Fl_Type *Fl_Type_make(const char *tn) {
+  reading_file = 1; // makes labels be null
+  Fl_Type *r = 0;
+  for (unsigned i = 0; i < sizeof(New_Menu)/sizeof(*New_Menu); i++) {
+    Fl_Menu_Item *m = New_Menu+i;
+    if (!m->user_data()) continue;
+    Fl_Type *t = (Fl_Type*)(m->user_data());
+    if (!strcasecmp(tn,t->type_name())) {r = t->make(); break;}
+  }
+  reading_file = 0;
+  return r;
+}
+
+////////////////////////////////////////////////////////////////
+
+// Since I have included all the .H files, do this table here:
+// This table is only used to read fdesign files:
+
+struct symbol {const char *name; int value;};
+
+static symbol table[] = {
+  {"BLACK",	FL_BLACK},
+  {"RED",	FL_RED},
+  {"GREEN",	FL_GREEN},
+  {"YELLOW",	FL_YELLOW},
+  {"BLUE",	FL_BLUE},
+  {"MAGENTA",	FL_MAGENTA},
+  {"CYAN",	FL_CYAN},
+  {"WHITE",	FL_WHITE},
+
+  {"LCOL",		 FL_BLACK},
+  {"COL1",		 FL_GRAY},
+  {"MCOL",		 FL_LIGHT1},
+  {"LEFT_BCOL",		 FL_LIGHT3},
+  {"TOP_BCOL",		 FL_LIGHT2},
+  {"BOTTOM_BCOL",	 FL_DARK2},
+  {"RIGHT_BCOL",		 FL_DARK3},
+  {"INACTIVE",		 FL_INACTIVE_COLOR},
+  {"INACTIVE_COL",	 FL_INACTIVE_COLOR},
+  {"FREE_COL1",		 FL_FREE_COLOR},
+  {"FREE_COL2",		 FL_FREE_COLOR+1},
+  {"FREE_COL3",		 FL_FREE_COLOR+2},
+  {"FREE_COL4",		 FL_FREE_COLOR+3},
+  {"FREE_COL5",		 FL_FREE_COLOR+4},
+  {"FREE_COL6",		 FL_FREE_COLOR+5},
+  {"FREE_COL7",		 FL_FREE_COLOR+6},
+  {"FREE_COL8",		 FL_FREE_COLOR+7},
+  {"FREE_COL9",		 FL_FREE_COLOR+8},
+  {"FREE_COL10",		 FL_FREE_COLOR+9},
+  {"FREE_COL11",		 FL_FREE_COLOR+10},
+  {"FREE_COL12",		 FL_FREE_COLOR+11},
+  {"FREE_COL13",		 FL_FREE_COLOR+12},
+  {"FREE_COL14",		 FL_FREE_COLOR+13},
+  {"FREE_COL15",		 FL_FREE_COLOR+14},
+  {"FREE_COL16",		 FL_FREE_COLOR+15},
+  {"TOMATO",		 131},
+  {"INDIANRED",		 164},
+  {"SLATEBLUE",		 195},
+  {"DARKGOLD",		 84},
+  {"PALEGREEN",		 157},
+  {"ORCHID",		 203},
+  {"DARKCYAN",		 189},
+  {"DARKTOMATO",		 113},
+  {"WHEAT",		 174},
+  {"ALIGN_CENTER",	FL_ALIGN_CENTER},
+  {"ALIGN_TOP",		FL_ALIGN_TOP},
+  {"ALIGN_BOTTOM",	FL_ALIGN_BOTTOM},
+  {"ALIGN_LEFT",	FL_ALIGN_LEFT},
+  {"ALIGN_RIGHT",	FL_ALIGN_RIGHT},
+  {"ALIGN_INSIDE",	FL_ALIGN_INSIDE},
+  {"ALIGN_TOP_LEFT",	 FL_ALIGN_TOP | FL_ALIGN_LEFT},
+  {"ALIGN_TOP_RIGHT",	 FL_ALIGN_TOP | FL_ALIGN_RIGHT},
+  {"ALIGN_BOTTOM_LEFT",	 FL_ALIGN_BOTTOM | FL_ALIGN_LEFT},
+  {"ALIGN_BOTTOM_RIGHT", FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT},
+  {"ALIGN_CENTER|FL_ALIGN_INSIDE",	FL_ALIGN_CENTER|FL_ALIGN_INSIDE},
+  {"ALIGN_TOP|FL_ALIGN_INSIDE",		FL_ALIGN_TOP|FL_ALIGN_INSIDE},
+  {"ALIGN_BOTTOM|FL_ALIGN_INSIDE",	FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE},
+  {"ALIGN_LEFT|FL_ALIGN_INSIDE",	FL_ALIGN_LEFT|FL_ALIGN_INSIDE},
+  {"ALIGN_RIGHT|FL_ALIGN_INSIDE",	FL_ALIGN_RIGHT|FL_ALIGN_INSIDE},
+  {"ALIGN_INSIDE|FL_ALIGN_INSIDE",	FL_ALIGN_INSIDE|FL_ALIGN_INSIDE},
+  {"ALIGN_TOP_LEFT|FL_ALIGN_INSIDE",	FL_ALIGN_TOP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE},
+  {"ALIGN_TOP_RIGHT|FL_ALIGN_INSIDE",	FL_ALIGN_TOP|FL_ALIGN_RIGHT|FL_ALIGN_INSIDE},
+  {"ALIGN_BOTTOM_LEFT|FL_ALIGN_INSIDE",	FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_INSIDE},
+  {"ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE",FL_ALIGN_BOTTOM|FL_ALIGN_RIGHT|FL_ALIGN_INSIDE},
+
+  {"ALIGN_LEFT_TOP",	 FL_ALIGN_TOP | FL_ALIGN_LEFT},
+  {"ALIGN_RIGHT_TOP",	 FL_ALIGN_TOP | FL_ALIGN_RIGHT},
+  {"ALIGN_LEFT_BOTTOM",	 FL_ALIGN_BOTTOM | FL_ALIGN_LEFT},
+  {"ALIGN_RIGHT_BOTTOM", FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT},
+  {"INVALID_STYLE",	 255},
+  {"NORMAL_STYLE",	 FL_HELVETICA},
+  {"BOLD_STYLE",		 FL_HELVETICA|FL_BOLD},
+  {"ITALIC_STYLE",	 FL_HELVETICA|FL_ITALIC},
+  {"BOLDITALIC_STYLE",	 FL_HELVETICA|FL_BOLD|FL_ITALIC},
+  {"FIXED_STYLE",	 FL_COURIER},
+  {"FIXEDBOLD_STYLE",	 FL_COURIER|FL_BOLD},
+  {"FIXEDITALIC_STYLE",	 FL_COURIER|FL_ITALIC},
+  {"FIXEDBOLDITALIC_STYLE",  FL_COURIER|FL_BOLD|FL_ITALIC},
+  {"TIMES_STYLE",	 FL_TIMES},
+  {"TIMESBOLD_STYLE",	 FL_TIMES|FL_BOLD},
+  {"TIMESITALIC_STYLE",	 FL_TIMES|FL_ITALIC},
+  {"TIMESBOLDITALIC_STYLE",  FL_TIMES|FL_BOLD|FL_ITALIC},
+  {"SHADOW_STYLE",	(_FL_SHADOW_LABEL<<8)},
+  {"ENGRAVED_STYLE",	(_FL_ENGRAVED_LABEL<<8)},
+  {"EMBOSSED_STYLE",	(_FL_EMBOSSED_LABEL<<0)},
+  {"TINY_SIZE",		 8},
+  {"SMALL_SIZE",		 11},
+  {"NORMAL_SIZE",	 FL_NORMAL_SIZE},
+  {"MEDIUM_SIZE",	 18},
+  {"LARGE_SIZE",		 24},
+  {"HUGE_SIZE",		 32},
+  {"DEFAULT_SIZE",	 FL_NORMAL_SIZE},
+  {"TINY_FONT",		 8},
+  {"SMALL_FONT",		 11},
+  {"NORMAL_FONT",	 FL_NORMAL_SIZE},
+  {"MEDIUM_FONT",	 18},
+  {"LARGE_FONT",		 24},
+  {"HUGE_FONT",		 32},
+  {"NORMAL_FONT1",	 11},
+  {"NORMAL_FONT2",	 FL_NORMAL_SIZE},
+  {"DEFAULT_FONT",	 11},
+  {"RETURN_END_CHANGED",  0},
+  {"RETURN_CHANGED",	 1},
+  {"RETURN_END",		 2},
+  {"RETURN_ALWAYS",	 3},
+  {"PUSH_BUTTON",	FL_TOGGLE_BUTTON},
+  {"RADIO_BUTTON",	FL_RADIO_BUTTON},
+  {"HIDDEN_BUTTON",	FL_HIDDEN_BUTTON},
+  {"SELECT_BROWSER",	FL_SELECT_BROWSER},
+  {"HOLD_BROWSER",	FL_HOLD_BROWSER},
+  {"MULTI_BROWSER",	FL_MULTI_BROWSER},
+  {"SIMPLE_COUNTER",	FL_SIMPLE_COUNTER},
+  {"LINE_DIAL",		FL_LINE_DIAL},
+  {"FILL_DIAL",		FL_FILL_DIAL},
+  {"VERT_SLIDER",	FL_VERT_SLIDER},
+  {"HOR_SLIDER",	FL_HOR_SLIDER},
+  {"VERT_FILL_SLIDER",	FL_VERT_FILL_SLIDER},
+  {"HOR_FILL_SLIDER",	FL_HOR_FILL_SLIDER},
+  {"VERT_NICE_SLIDER",	FL_VERT_NICE_SLIDER},
+  {"HOR_NICE_SLIDER",	FL_HOR_NICE_SLIDER},
+};
+
+#include 
+
+int lookup_symbol(const char *name, int &v, int numberok) {
+  if (name[0]=='F' && name[1]=='L' && name[2]=='_') name += 3;
+  for (int i=0; i < int(sizeof(table)/sizeof(*table)); i++)
+    if (!strcasecmp(name,table[i].name)) {v = table[i].value; return 1;}
+  if (numberok && ((v = atoi(name)) || !strcmp(name,"0"))) return 1;
+  return 0;
+}
diff --git a/fluid/file.cxx b/fluid/file.cxx
new file mode 100644
index 000000000..69bc97d17
--- /dev/null
+++ b/fluid/file.cxx
@@ -0,0 +1,562 @@
+/*	file.C
+
+	Code to read and write Fluid .fl files
+
+	You may find the basic read_* and write_* routines to
+	be useful for other programs.  I have used them many times.
+	They are somewhat similar to tcl, using matching { and }
+	to quote strings.
+
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+////////////////////////////////////////////////////////////////
+// BASIC FILE WRITING:
+
+static FILE *fout;
+
+int open_write(const char *s) {
+  if (!s) {fout = stdout; return 1;}
+  FILE *f = fopen(s,"w");
+  if (!f) return 0;
+  fout = f;
+  return 1;
+}
+
+int close_write() {
+  if (fout != stdout) {
+    int x = fclose(fout);
+    fout = stdout;
+    return x >= 0;
+  }
+  return 1;
+}
+
+static int needspace;
+int is_id(char); // in code.C
+
+// write a string, quoting characters if necessary:
+void write_word(const char *w) {
+  if (needspace) putc(' ', fout);
+  needspace = 1;
+  if (!w || !*w) {fprintf(fout,"{}"); return;}
+  const char *p;
+  // see if it is a single word:
+  for (p = w; is_id(*p); p++) ;
+  if (!*p) {fprintf(fout,"%s",w); return;}
+  // see if there are matching braces:
+  int n = 0;
+  for (p = w; *p; p++) {
+    if (*p == '{') n++;
+    else if (*p == '}') {n--; if (n<0) break;}
+  }
+  int mismatched = (n != 0);
+  // write out brace-quoted string:
+  putc('{', fout);
+  for (; *w; w++) {
+    switch (*w) {
+    case '{':
+    case '}':
+      if (!mismatched) break;
+    case '\\':
+    case '#':
+      putc('\\',fout);
+      break;
+    }
+    putc(*w,fout);
+  }
+  putc('}', fout);
+}
+
+// write an arbitrary formatted word, or a comment, etc:
+void write_string(const char *format, ...) {
+  va_list args;
+  va_start(args, format);
+  if (needspace) fputc(' ',fout);
+  vfprintf(fout, format, args);
+  va_end(args);
+  needspace = !isspace(format[strlen(format)-1]);
+}
+
+// start a new line and indent it for a given nesting level:
+void write_indent(int n) {
+  fputc('\n',fout);
+  while (n--) {fputc(' ',fout); fputc(' ',fout);}
+  needspace = 0;
+}
+
+// write a '{' at the given indenting level:
+void write_open(int) {
+  if (needspace) fputc(' ',fout);
+  fputc('{',fout);
+  needspace = 0;
+}
+
+// write a '}' at the given indenting level:
+void write_close(int n) {
+  if (needspace) write_indent(n);
+  fputc('}',fout);
+  needspace = 1;
+}
+
+////////////////////////////////////////////////////////////////
+// BASIC FILE READING:
+
+static FILE *fin;
+static int lineno;
+static const char *fname;
+
+int open_read(const char *s) {
+  lineno = 1;
+  if (!s) {fin = stdin; fname = "stdin"; return 1;}
+  FILE *f = fopen(s,"r");
+  if (!f) return 0;
+  fin = f;
+  fname = s;
+  return 1;
+}
+
+int close_read() {
+  if (fin != stdin) {
+    int x = fclose(fin);
+    fin = 0;
+    return x >= 0;
+  }
+  return 1;
+}
+
+#include 
+
+void read_error(const char *format, ...) {
+  va_list args;
+  va_start(args, format);
+  if (!fin) {
+    char buffer[1024];
+    vsprintf(buffer, format, args);
+    fl_message(buffer);
+  } else {
+    fprintf(stderr, "%s:%d: ", fname, lineno);
+    vfprintf(stderr, format, args);
+    fprintf(stderr, "\n");
+  }
+  va_end(args);
+}
+
+static int hexdigit(int x) {
+  if (isdigit(x)) return x-'0';
+  if (isupper(x)) return x-'A'+10;
+  if (islower(x)) return x-'a'+10;
+  return 20;
+}
+
+
+static int read_quoted() {	// read whatever character is after a \ .
+  int c,d,x;
+  switch(c = fgetc(fin)) {
+  case '\n': lineno++; return -1;
+  case 'a' : return('\a');
+  case 'b' : return('\b');
+  case 'f' : return('\f');
+  case 'n' : return('\n');
+  case 'r' : return('\r');
+  case 't' : return('\t');
+  case 'v' : return('\v');
+  case 'x' :	/* read hex */
+    for (c=x=0; x<3; x++) {
+      int ch = fgetc(fin);
+      d = hexdigit(ch);
+      if (d > 15) {ungetc(ch,fin); break;}
+      c = (c<<4)+d;
+    }
+    break;
+  default:		/* read octal */
+    if (c<'0' || c>'7') break;
+    c -= '0';
+    for (x=0; x<2; x++) {
+      int ch = fgetc(fin);
+      d = hexdigit(ch);
+      if (d>7) {ungetc(ch,fin); break;}
+      c = (c<<3)+d;
+    }
+    break;
+  }
+  return(c);
+}
+
+// return a word read from the file, or NULL at the EOF:
+// This will skip all comments (# to end of line), and evaluate
+// all \xxx sequences and use \ at the end of line to remove the newline.
+// A word is any one of:
+//	a continuous string of non-space chars except { and } and #
+//	everything between matching {...} (unless wantbrace != 0)
+//	the characters '{' and '}'
+
+static char *buffer;
+static int buflen;
+static void expand_buffer(int length) {
+  if (length >= buflen) {
+    if (!buflen) {
+      buflen = length+1;
+      buffer = (char*)malloc(buflen);
+    } else {
+      buflen = 2*buflen;
+      if (length >= buflen) buflen = length+1;
+      buffer = (char *)realloc((void *)buffer,buflen);
+    }
+  }
+}
+
+const char *read_word(int wantbrace) {
+  int x;
+
+  // skip all the whitespace before it:
+  for (;;) {
+    x = getc(fin);
+    if (x < 0) {	// eof
+      return 0;
+    } else if (x == '#') {	// comment
+      do x = getc(fin); while (x >= 0 && x != '\n');
+      lineno++;
+      continue;
+    } else if (x == '\n') {
+      lineno++;
+    } else if (!isspace(x)) {
+      break;
+    }
+  }
+
+  expand_buffer(100);
+
+  if (x == '{' && !wantbrace) {
+
+    // read in whatever is between braces
+    int length = 0;
+    int nesting = 0;
+    for (;;) {
+      x = getc(fin);
+      if (x<0) {read_error("Missing '}'"); break;}
+      else if (x == '#') { // embedded comment
+	do x = getc(fin); while (x >= 0 && x != '\n');
+	lineno++;
+	continue;
+      } else if (x == '\n') lineno++;
+      else if (x == '\\') {x = read_quoted(); if (x<0) continue;}
+      else if (x == '{') nesting++;
+      else if (x == '}') {if (!nesting--) break;}
+      buffer[length++] = x;
+      expand_buffer(length);
+    }
+    buffer[length] = 0;
+    return buffer;
+
+  } else if (x == '{' || x == '}') {
+    // all the punctuation is a word:
+    buffer[0] = x;
+    buffer[1] = 0;
+    return buffer;
+
+  } else {
+
+    // read in an unquoted word:
+    int length = 0;
+    for (;;) {
+      if (x == '\\') {x = read_quoted(); if (x<0) continue;}
+      else if (x<0 || isspace(x) || x=='{' || x=='}' || x=='#') break;
+      buffer[length++] = x;
+      expand_buffer(length);
+      x = getc(fin);
+    }
+    ungetc(x, fin);
+    buffer[length] = 0;
+    return buffer;
+
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+#include 
+#include "Fl_Widget_Type.H"
+
+// global int variables:
+extern int gridx, gridy, snap;
+static struct {const char* name; int* value;} inttable[] = {
+  {"gridx", &gridx},
+  {"gridy", &gridy},
+  {"snap", &snap}
+};
+
+extern const char* header_file_name;
+extern const char* code_file_name;
+
+int write_file(const char *filename, int selected_only) {
+  if (!open_write(filename)) return 0;
+  write_string("# data file for the Fltk User Interface Designer (fluid)\n"
+	       "version %.2f",FL_VERSION);
+  if (!selected_only) {
+    write_string("\nheader_name"); write_word(header_file_name);
+    write_string("\ncode_name"); write_word(code_file_name);
+    for (unsigned int i=0; iselected) {
+      p->write();
+      write_string("\n");
+      int q = p->level;
+      for (p = p->next; p && p->level > q; p = p->next);
+    } else {
+      p = p->next;
+    }
+  }
+  return close_write();
+}
+
+////////////////////////////////////////////////////////////////
+// read all the objects out of the input file:
+
+void read_fdesign();
+
+double read_version;
+
+extern Fl_Type *Fl_Type_make(const char *tn);
+
+static void read_children(Fl_Type *p, int paste) {
+  Fl_Type::current = p;
+  for (;;) {
+    unsigned int i;
+    const char *c = read_word();
+  REUSE_C:
+    if (!c) {
+      if (p && !paste) read_error("Missing '}'");
+      break;
+    }
+
+    if (!strcmp(c,"}")) {
+      if (!p) read_error("Unexpected '}'");
+      break;
+    }
+
+    // this is the first word in a .fd file:
+    if (!strcmp(c,"Magic:")) {
+      read_fdesign();
+      return;
+    }
+
+    if (!strcmp(c,"version")) {
+      c = read_word();
+      read_version = strtod(c,0);
+      if (read_version<=0 || read_version>FL_VERSION)
+	read_error("unknown version '%s'",c);
+      continue;
+    }
+
+    // back compatability with Vincent Penne's original class code:
+    if (!p && !strcmp(c,"define_in_struct")) {
+      Fl_Type *t = Fl_Type_make("class");
+      t->name(read_word());
+      Fl_Type::current = p = t;
+      paste = 1; // stops "missing }" error
+      continue;
+    }
+
+    if (!strcmp(c,"header_name")) {
+      header_file_name = strdup(read_word());
+      goto CONTINUE;
+    }
+
+    if (!strcmp(c,"code_name")) {
+      code_file_name = strdup(read_word());
+      goto CONTINUE;
+    }
+
+    for (i=0; iname(read_word());
+
+    c = read_word(1);
+    if (strcmp(c,"{")) {
+      read_error("Missing property list for %s\n",t->title());
+      goto REUSE_C;
+    }
+
+    t->open_ = 0;
+    for (;;) {
+      const char *c = read_word();
+      if (!c || !strcmp(c,"}")) break;
+      t->read_property(c);
+    }
+
+    if (!t->is_parent()) continue;
+    c = read_word(1);
+    if (strcmp(c,"{")) {
+      read_error("Missing child list for %s\n",t->title());
+      goto REUSE_C;
+    }
+    read_children(t, 0);}
+    Fl_Type::current = p;
+  CONTINUE:;
+  }
+}
+
+extern void deselect();
+
+int read_file(const char *filename, int merge) {
+  read_version = 0.0;
+  if (!open_read(filename)) return 0;
+  if (merge) deselect(); else delete_all();
+  read_children(Fl_Type::current, merge);
+  Fl_Type::current = 0;
+  for (Fl_Type *o = Fl_Type::first; o; o = o->next)
+    if (o->selected) {Fl_Type::current = o; break;}
+  return close_read();
+}
+
+////////////////////////////////////////////////////////////////
+// Read Forms and XForms fdesign files:
+
+int read_fdesign_line(const char*& name, const char*& value) {
+
+  int length = 0;
+  int x;
+  // find a colon:
+  for (;;) {
+    x = getc(fin);
+    if (x < 0) return 0;
+    if (x == '\n') {length = 0; continue;} // no colon this line...
+    if (!isspace(x)) {
+      buffer[length++] = x;
+      expand_buffer(length);
+    }
+    if (x == ':') break;
+  }
+  int valueoffset = length;
+  buffer[length-1] = 0;
+
+  // skip to start of value:
+  for (;;) {
+    x = getc(fin);
+    if (x < 0 || x == '\n' || !isspace(x)) break;
+  }
+
+  // read the value:
+  for (;;) {
+    if (x == '\\') {x = read_quoted(); if (x<0) continue;}
+    else if (x == '\n') break;
+    buffer[length++] = x;
+    expand_buffer(length);
+    x = getc(fin);
+  }
+  buffer[length] = 0;
+  name = buffer;
+  value = buffer+valueoffset;
+  return 1;
+}
+
+int fdesign_flip;
+int fdesign_magic;
+#include 
+
+static const char *class_matcher[] = {
+"FL_CHECKBUTTON", "Fl_Check_Button",
+"FL_ROUNDBUTTON", "Fl_Round_Button",
+"FL_ROUND3DBUTTON", "Fl_Round_Button",
+"FL_LIGHTBUTTON", "Fl_Light_Button",
+"FL_FRAME", "Fl_Box",
+"FL_LABELFRAME", "Fl_Box",
+"FL_TEXT", "Fl_Box",
+"FL_VALSLIDER", "Fl_Value_Slider",
+"FL_MENU", "Fl_Menu_Button",
+"3", "FL_BITMAP",
+"1", "FL_BOX",
+"71","FL_BROWSER",
+"11","FL_BUTTON",
+"4", "FL_CHART",
+"42","FL_CHOICE",
+"61","FL_CLOCK",
+"25","FL_COUNTER",
+"22","FL_DIAL",
+"101","FL_FREE",
+"31","FL_INPUT",
+"12","Fl_Light_Button",
+"41","FL_MENU",
+"23","FL_POSITIONER",
+"13","Fl_Round_Button",
+"21","FL_SLIDER",
+"2", "FL_BOX", // was FL_TEXT
+"62","FL_TIMER",
+"24","Fl_Value_Slider",
+0};
+
+void read_fdesign() {
+  fdesign_magic = atoi(read_word());
+  fdesign_flip = (fdesign_magic < 13000);
+  Fl_Widget_Type *window = 0;
+  Fl_Widget_Type *group = 0;
+  Fl_Widget_Type *widget = 0;
+  if (!Fl_Type::current) {
+    Fl_Type *t = Fl_Type_make("Function");
+    t->name("create_the_forms()");
+    Fl_Type::current = t;
+  }
+  for (;;) {
+    const char *name;
+    const char *value;
+    if (!read_fdesign_line(name, value)) break;
+
+    if (!strcmp(name,"Name")) {
+
+      window = (Fl_Widget_Type*)Fl_Type_make("Fl_Window");
+      window->name(value);
+      window->label(value);
+      Fl_Type::current = widget = window;
+
+    } else if (!strcmp(name,"class")) {
+
+      if (!strcmp(value,"FL_BEGIN_GROUP")) {
+	group = widget = (Fl_Widget_Type*)Fl_Type_make("Fl_Group");
+	Fl_Type::current = group;
+      } else if (!strcmp(value,"FL_END_GROUP")) {
+	if (group) {
+	  Fl_Group* g = (Fl_Group*)(group->o);
+	  g->begin();
+	  g->forms_end();
+	  Fl_Group::current(0);
+	}
+	group = widget = 0;
+	Fl_Type::current = window;
+      } else {
+	for (int i = 0; class_matcher[i]; i += 2)
+	  if (!strcmp(value,class_matcher[i])) {
+	    value = class_matcher[i+1]; break;}
+	widget = (Fl_Widget_Type*)Fl_Type_make(value);
+	if (!widget) {
+	  printf("class %s not found, using Fl_Button\n", value);
+	  widget = (Fl_Widget_Type*)Fl_Type_make("Fl_Button");
+	}
+      }
+
+    } else if (widget) {
+      if (!widget->read_fdesign(name, value))
+	printf("Ignoring \"%s: %s\"\n", name, value);
+    }
+  }
+}
+
+
diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx
new file mode 100644
index 000000000..384eb5104
--- /dev/null
+++ b/fluid/fluid.cxx
@@ -0,0 +1,387 @@
+// fluid.C
+
+// Please see README for some information about the construction of this
+// rather nasty piece of code.
+
+const char *copyright =
+"The FLTK user interface designer version 0.99\n"
+"Copyright \xa9 1998 Bill Spitzak\n"
+"\n"
+"This library is free software; you can redistribute it and/or "
+"modify it under the terms of the GNU Library General Public "
+"License as published by the Free Software Foundation; either "
+"version 2 of the License, or (at your option) any later version.\n"
+"\n"
+"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 Library General Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU Library 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.\n"
+"\n"
+"Written by Bill Spitzak spitzak@d2.com\n";
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if defined(WIN32) && !defined(CYGNUS)
+# include 
+#else
+# include 
+#endif
+
+#include "about_panel.H"
+
+#include "Fl_Type.H"
+
+////////////////////////////////////////////////////////////////
+
+void nyi(Fl_Widget *,void *) {
+    fl_message("That's not yet implemented, sorry");
+}
+
+static const char *filename;
+void set_filename(const char *c);
+int modflag;
+
+static char* pwd;
+static char in_source_dir;
+void goto_source_dir() {
+  if (in_source_dir) return;
+  if (!filename || !*filename) return;
+  const char *p = filename_name(filename);
+  if (p <= filename) return; // it is in the current directory
+  char buffer[1024];
+  strcpy(buffer,filename);
+  int n = p-filename; if (n>1) n--; buffer[n] = 0;
+  if (!pwd) {
+    pwd = getcwd(0,1024);
+    if (!pwd) {fprintf(stderr,"getwd : %s\n",strerror(errno)); return;}
+  }
+  if (chdir(buffer)<0) {fprintf(stderr, "Can't chdir to %s : %s\n",
+				buffer, strerror(errno)); return;}
+  in_source_dir = 1;
+}
+
+void leave_source_dir() {
+  if (!in_source_dir) return;
+  if (chdir(pwd)<0) {fprintf(stderr, "Can't chdir to %s : %s\n",
+				pwd, strerror(errno));}
+  in_source_dir = 0;
+}
+  
+Fl_Window *main_window;
+
+void exit_cb(Fl_Widget *,void *) {
+  if (!modflag || fl_ask("Exit without saving changes?")) exit(0);
+}
+
+void save_cb(Fl_Widget *, void *v) {
+  const char *c = filename;
+  if (v || !c || !*c) {
+    if (!(c=fl_file_chooser("Save to:", "*.f[ld]", c))) return;
+    set_filename(c);
+  }
+  if (!write_file(c)) {
+    fl_show_message("Error writing", c, strerror(errno));
+    return;
+  }
+  modflag = 0;
+}
+
+void open_cb(Fl_Widget *, void *v) {
+  if (!v && modflag && !fl_ask("Discard changes?")) return;
+  const char *c;
+  if (!(c = fl_file_chooser("Open:", "*.f[ld]", filename))) return;
+  if (!read_file(c, v!=0)) {
+    fl_show_message("Can't read", c, strerror(errno));
+    return;
+  }
+  if (!v) {set_filename(c); modflag = 0;}
+  else modflag = 1;
+}
+
+void new_cb(Fl_Widget *, void *v) {
+  if (!v && modflag && !fl_ask("Discard changes?")) return;
+  const char *c;
+  if (!(c = fl_file_chooser("New:", "*.f[ld]", 0))) return;
+  delete_all();
+  set_filename(c);
+  modflag = 0;
+}
+
+static int compile_only;
+
+const char* header_file_name = ".H";
+const char* code_file_name = ".C";
+
+void write_cb(Fl_Widget *, void *) {
+  if (!filename) {
+    save_cb(0,0);
+    if (!filename) return;
+  }
+  char cname[1024];
+  char hname[1024];
+  if (*code_file_name == '.') {
+    strcpy(cname,filename_name(filename));
+    filename_setext(cname, code_file_name);
+  } else {
+    strcpy(cname, code_file_name);
+  }
+  if (*header_file_name == '.') {
+    strcpy(hname,filename_name(filename));
+    filename_setext(hname, header_file_name);
+  } else {
+    strcpy(hname, header_file_name);
+  }
+  int x = write_code(cname,hname);
+  strcat(cname, "/"); strcat(cname,header_file_name);
+  if (compile_only) {
+    if (!x) {fprintf(stderr,"%s : %s\n",cname,strerror(errno)); exit(1);}
+  } else {
+    if (!x) {
+      fl_show_message("Can't write", cname, strerror(errno));
+    } else {
+      fl_show_message("Wrote", cname, 0);
+    }
+  }
+}
+
+void openwidget_cb(Fl_Widget *, void *) {
+  if (!Fl_Type::current) {
+    fl_message("Please select a widget");
+    return;
+  }
+  Fl_Type::current->open();
+}
+
+void toggle_overlays(Fl_Widget *,void *);
+
+void select_all_cb(Fl_Widget *,void *);
+
+void group_cb(Fl_Widget *, void *);
+
+void ungroup_cb(Fl_Widget *, void *);
+
+extern int pasteoffset;
+static int ipasteoffset;
+
+static char* cutfname() {
+#ifdef WIN32
+  return ".fluid_cut_buffer";
+#else
+  static char name[256] = "~/.fluid_cut_buffer";
+  static char beenhere;
+  if (!beenhere) {beenhere = 1; filename_expand(name,name);}
+  return name;
+#endif
+}
+
+void copy_cb(Fl_Widget*, void*) {
+  if (!Fl_Type::current) return;
+  ipasteoffset = 10;
+  if (!write_file(cutfname(),1)) {
+    fl_show_message("Can't write", cutfname(), strerror(errno));
+    return;
+  }
+}
+
+extern void select_only(Fl_Type *);
+void cut_cb(Fl_Widget *, void *) {
+  if (!Fl_Type::current) return;
+  ipasteoffset = 0;
+  Fl_Type *p = Fl_Type::current->parent;
+  while (p && p->selected) p = p->parent;
+  if (!write_file(cutfname(),1)) {
+    fl_show_message("Can't write", cutfname(), strerror(errno));
+    return;
+  }
+  delete_all(1);
+  if (p) select_only(p);
+}
+
+extern int force_parent, gridx, gridy;
+
+void paste_cb(Fl_Widget*, void*) {
+  if (ipasteoffset) force_parent = 1;
+  pasteoffset = ipasteoffset;
+  if (gridx>1) pasteoffset = ((pasteoffset-1)/gridx+1)*gridx;
+  if (gridy>1) pasteoffset = ((pasteoffset-1)/gridy+1)*gridy;
+  if (!read_file(cutfname(), 1)) {
+    fl_show_message("Can't read", cutfname(), strerror(errno));
+  }
+  pasteoffset = 0;
+  ipasteoffset += 10;
+  force_parent = 0;
+}
+
+void earlier_cb(Fl_Widget*,void*);
+
+void later_cb(Fl_Widget*,void*);
+
+Fl_Type *sort(Fl_Type *parent);
+
+static void sort_cb(Fl_Widget *,void *) {
+  sort((Fl_Type*)0);
+}
+
+void show_alignment_cb(Fl_Widget *, void *);
+
+void about_cb(Fl_Widget *, void *) {
+  if (!about_panel) make_about_panel(copyright);
+  copyright_box->hide();
+  display_group->show();
+  about_panel->show();
+}
+
+////////////////////////////////////////////////////////////////
+
+extern Fl_Menu_Item New_Menu[];
+
+Fl_Menu_Item Main_Menu[] = {
+{"File",0,0,0,FL_SUBMENU},
+  {"New", FL_ALT+'N', new_cb, 0},
+  {"Open...", FL_ALT+'O', open_cb, 0},
+  {"Save", FL_ALT+'s', save_cb, 0},
+  {"Save As...", FL_ALT+'S', save_cb, (void*)1},
+  {"Merge...", FL_ALT+'i', open_cb, (void*)1, FL_MENU_DIVIDER},
+  {"Write code", FL_ALT+'C', write_cb, 0},
+  {"Quit", FL_ALT+'q', exit_cb},
+  {0},
+{"Edit",0,0,0,FL_SUBMENU},
+  {"Undo", FL_ALT+'z', nyi},
+  {"Cut", FL_ALT+'x', cut_cb},
+  {"Copy", FL_ALT+'c', copy_cb},
+  {"Paste", FL_ALT+'v', paste_cb},
+  {"Select All", FL_ALT+'a', select_all_cb, 0, FL_MENU_DIVIDER},
+  {"Open...", FL_F+1, openwidget_cb},
+  {"Sort",0,sort_cb},
+  {"Earlier", FL_F+2, earlier_cb},
+  {"Later", FL_F+3, later_cb},
+//{"Show", FL_F+5, show_cb},
+//{"Hide", FL_F+6, hide_cb},
+  {"Group", FL_F+7, group_cb},
+  {"Ungroup", FL_F+8, ungroup_cb,0, FL_MENU_DIVIDER},
+//{"Deactivate", 0, nyi},
+//{"Activate", 0, nyi, 0, FL_MENU_DIVIDER},
+  {"Overlays on/off",FL_ALT+'o',toggle_overlays},
+  {"Preferences",FL_ALT+'p',show_alignment_cb},
+  {0},
+{"New", 0, 0, (void *)New_Menu, FL_SUBMENU_POINTER},
+{"Help",0,0,0,FL_SUBMENU},
+  {"About fluid",0,about_cb},
+  {"Manual",0,nyi},
+  {0},
+{0}};
+
+#define BROWSERWIDTH 300
+#define BROWSERHEIGHT 500
+#define WINWIDTH 300
+#define MENUHEIGHT 30
+#define WINHEIGHT (BROWSERHEIGHT+MENUHEIGHT)
+
+extern void fill_in_New_Menu();
+
+void make_main_window() {
+  if (!main_window) {
+    Fl_Widget *o;
+    main_window = new Fl_Double_Window(WINWIDTH,WINHEIGHT,"fluid");
+    main_window->box(FL_NO_BOX);
+    o = make_widget_browser(0,MENUHEIGHT,BROWSERWIDTH,BROWSERHEIGHT);
+    o->box(FL_FLAT_BOX);
+    main_window->resizable(o);
+    Fl_Menu_Bar *m = new Fl_Menu_Bar(0,0,BROWSERWIDTH,MENUHEIGHT);
+    m->menu(Main_Menu);
+    m->global();
+    fill_in_New_Menu();
+    main_window->end();
+  }
+}
+
+void set_filename(const char *c) {
+  if (filename) free((void *)filename);
+  filename = strdup(c);
+  if (main_window) main_window->label(filename);
+}
+
+////////////////////////////////////////////////////////////////
+
+static int arg(int argc, char** argv, int& i) {
+  if (argv[i][1] == 'c' && !argv[i][2]) {compile_only = 1; i++; return 1;}
+  if (argv[i][1] == 'o' && !argv[i][2] && i+1 < argc) {
+    code_file_name = argv[i+1]; i += 2; return 2;}
+  if (argv[i][1] == 'h' && !argv[i][2]) {
+    header_file_name = argv[i+1]; i += 2; return 2;}
+  return 0;
+}
+
+#ifndef WIN32
+
+#include 
+#ifdef _sigargs
+#define SIGARG _sigargs
+#else
+#ifdef __sigargs
+#define SIGARG __sigargs
+#else
+#define SIGARG int // you may need to fix this for older systems
+#endif
+#endif
+
+static void sigint(SIGARG) {
+  signal(SIGINT,sigint);
+  exit_cb(0,0);
+}
+
+#endif
+
+int main(int argc,char **argv) {
+  int i = 1;
+  if (!Fl::args(argc,argv,i,arg) || i < argc-1) {
+    fprintf(stderr,"usage: %s  name.fl\n"
+" -c : write .C and .H and exit\n"
+" -o  : .C output filename, or extension if  starts with '.'\n"
+" -h  : .H output filename, or extension if  starts with '.'\n"
+"%s\n", argv[0], Fl::help);
+    return 1;
+  }
+  const char *c = argv[i];
+  make_main_window();
+  if (c) set_filename(c);
+  if (!compile_only) {
+    Fl::visual((Fl_Mode)(FL_DOUBLE|FL_INDEX));
+    main_window->callback(exit_cb);
+    main_window->show(argc,argv);
+  }
+  if (c && !read_file(c,0)) {
+    if (compile_only) {
+      fprintf(stderr,"%s : %s\n", c, strerror(errno));
+      exit(1);
+    }
+    fl_show_message("Can't read", c, strerror(errno));
+  }
+  if (compile_only) {write_cb(0,0); exit(0);}
+  modflag = 0;
+#ifndef WIN32
+  signal(SIGINT,sigint);
+#endif
+  return Fl::run();
+}
diff --git a/fluid/function_panel.cxx b/fluid/function_panel.cxx
new file mode 100644
index 000000000..0b6bccd61
--- /dev/null
+++ b/fluid/function_panel.cxx
@@ -0,0 +1,262 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "function_panel.H"
+
+Fl_Window *function_panel;
+
+Fl_Light_Button *f_public_button;
+
+Fl_Input *f_name_input;
+
+Fl_Input *f_return_type_input;
+
+Fl_Return_Button *f_panel_ok;
+
+Fl_Button *f_panel_cancel;
+
+Fl_Window *code_panel;
+
+Fl_Input *code_input;
+
+Fl_Return_Button *code_panel_ok;
+
+Fl_Button *code_panel_cancel;
+
+Fl_Window *codeblock_panel;
+
+Fl_Input *code_before_input;
+
+Fl_Input *code_after_input;
+
+Fl_Return_Button *codeblock_panel_ok;
+
+Fl_Button *codeblock_panel_cancel;
+
+Fl_Window *declblock_panel;
+
+Fl_Input *decl_before_input;
+
+Fl_Input *decl_after_input;
+
+Fl_Return_Button *declblock_panel_ok;
+
+Fl_Button *declblock_panel_cancel;
+
+Fl_Window *decl_panel;
+
+Fl_Light_Button *decl_public_button;
+
+Fl_Input *decl_input;
+
+Fl_Return_Button *decl_panel_ok;
+
+Fl_Button *decl_panel_cancel;
+
+Fl_Window *class_panel;
+
+Fl_Light_Button *c_public_button;
+
+Fl_Input *c_name_input;
+
+Fl_Input *c_subclass_input;
+
+Fl_Return_Button *c_panel_ok;
+
+Fl_Button *c_panel_cancel;
+
+Fl_Window* make_function_panel() {
+  Fl_Window *w;
+  { Fl_Window* o = new Fl_Window(287, 173, "function/method");
+    w = function_panel = o;
+    w->set_modal();
+    { Fl_Light_Button* o = new Fl_Light_Button(10, 15, 65, 25, "public");
+      f_public_button = o;
+      o->labelsize(10);
+      o->when(0);
+    }
+    { Fl_Input* o = new Fl_Input(10, 60, 270, 25, "name(args): (blank for main())");
+      f_name_input = o;
+      o->labelsize(12);
+      o->align(5);
+      o->when(0);
+      Fl_Group::current()->resizable(o);
+    }
+    { Fl_Input* o = new Fl_Input(10, 105, 270, 25, "return type: (blank to return outermost widget)");
+      f_return_type_input = o;
+      o->labelsize(12);
+      o->align(5);
+      o->when(0);
+    }
+    { Fl_Return_Button* o = new Fl_Return_Button(110, 140, 80, 25, "OK");
+      f_panel_ok = o;
+      w->hotspot(o);
+    }
+    { Fl_Button* o = new Fl_Button(200, 140, 80, 25, "cancel");
+      f_panel_cancel = o;
+      o->shortcut(0xff1b);
+    }
+    w->end();
+  }
+  return w;
+}
+
+Fl_Window* make_code_panel() {
+  Fl_Window *w;
+  { Fl_Window* o = new Fl_Window(291, 178, "code");
+    w = code_panel = o;
+    w->set_modal();
+    { Fl_Input* o = new Fl_Input(6, 5, 280, 135);
+      code_input = o;
+      o->type(4);
+      o->labelsize(12);
+      o->align(0);
+      o->when(0);
+      Fl_Group::current()->resizable(o);
+    }
+    { Fl_Return_Button* o = new Fl_Return_Button(115, 145, 80, 25, "OK");
+      code_panel_ok = o;
+      w->hotspot(o);
+    }
+    { Fl_Button* o = new Fl_Button(205, 145, 80, 25, "cancel");
+      code_panel_cancel = o;
+      o->shortcut(0xff1b);
+    }
+    w->end();
+  }
+  return w;
+}
+
+Fl_Window* make_codeblock_panel() {
+  Fl_Window *w;
+  { Fl_Window* o = new Fl_Window(293, 134, "codeblock");
+    w = codeblock_panel = o;
+    w->set_modal();
+    { Fl_Input* o = new Fl_Input(10, 5, 275, 25);
+      code_before_input = o;
+      o->labelsize(12);
+      o->align(5);
+      o->when(0);
+      Fl_Group::current()->resizable(o);
+    }
+    { Fl_Box* o = new Fl_Box(10, 35, 270, 25, "\"{...child code...}\" is inserted here");
+      o->align(20);
+    }
+    { Fl_Input* o = new Fl_Input(10, 65, 275, 25);
+      code_after_input = o;
+      o->labelsize(12);
+      o->align(5);
+      o->when(0);
+    }
+    { Fl_Return_Button* o = new Fl_Return_Button(115, 100, 80, 25, "OK");
+      codeblock_panel_ok = o;
+      w->hotspot(o);
+    }
+    { Fl_Button* o = new Fl_Button(205, 100, 80, 25, "cancel");
+      codeblock_panel_cancel = o;
+      o->shortcut(0xff1b);
+    }
+    w->end();
+  }
+  return w;
+}
+
+Fl_Window* make_declblock_panel() {
+  Fl_Window *w;
+  { Fl_Window* o = new Fl_Window(293, 134, "declaration block");
+    w = declblock_panel = o;
+    w->set_modal();
+    { Fl_Input* o = new Fl_Input(15, 10, 275, 25);
+      decl_before_input = o;
+      o->labelsize(12);
+      o->align(5);
+      o->when(0);
+      Fl_Group::current()->resizable(o);
+    }
+    { Fl_Box* o = new Fl_Box(15, 40, 270, 25, "\"\\n...child code...\\n\" is inserted here");
+      o->align(20);
+    }
+    { Fl_Input* o = new Fl_Input(15, 70, 275, 25);
+      decl_after_input = o;
+      o->labelsize(12);
+      o->align(5);
+      o->when(0);
+    }
+    { Fl_Return_Button* o = new Fl_Return_Button(120, 105, 80, 25, "OK");
+      declblock_panel_ok = o;
+      w->hotspot(o);
+    }
+    { Fl_Button* o = new Fl_Button(210, 105, 80, 25, "cancel");
+      declblock_panel_cancel = o;
+      o->shortcut(0xff1b);
+    }
+    w->end();
+  }
+  return w;
+}
+
+Fl_Window* make_decl_panel() {
+  Fl_Window *w;
+  { Fl_Window* o = new Fl_Window(290, 176, "declaration");
+    w = decl_panel = o;
+    { Fl_Light_Button* o = new Fl_Light_Button(10, 15, 65, 25, "public");
+      decl_public_button = o;
+      o->labelsize(10);
+      o->when(0);
+    }
+    { Fl_Input* o = new Fl_Input(10, 50, 270, 25, "can be any declartion, like \"int x;\",\nan external symbol like \"extern \
+int foo();\",\na #directive like \"#include \",\nor a comment like \"\
+//foo\" or \"/*foo*/\"");
+      decl_input = o;
+      o->labelsize(12);
+      o->align(6);
+      o->when(0);
+      Fl_Group::current()->resizable(o);
+    }
+    { Fl_Return_Button* o = new Fl_Return_Button(115, 145, 80, 25, "OK");
+      decl_panel_ok = o;
+      w->hotspot(o);
+    }
+    { Fl_Button* o = new Fl_Button(205, 145, 80, 25, "cancel");
+      decl_panel_cancel = o;
+      o->shortcut(0xff1b);
+    }
+    w->end();
+  }
+  return w;
+}
+
+Fl_Window* make_class_panel() {
+  Fl_Window *w;
+  { Fl_Window* o = new Fl_Window(287, 173, "class");
+    w = class_panel = o;
+    w->set_modal();
+    { Fl_Light_Button* o = new Fl_Light_Button(10, 10, 65, 25, "public");
+      c_public_button = o;
+      o->labelsize(10);
+      o->when(0);
+    }
+    { Fl_Input* o = new Fl_Input(10, 55, 270, 25, "name:");
+      c_name_input = o;
+      o->labelsize(12);
+      o->align(5);
+      o->when(0);
+      Fl_Group::current()->resizable(o);
+    }
+    { Fl_Input* o = new Fl_Input(10, 100, 270, 25, "subclass of (text between : and {)");
+      c_subclass_input = o;
+      o->labelsize(12);
+      o->align(5);
+      o->when(0);
+    }
+    { Fl_Return_Button* o = new Fl_Return_Button(110, 135, 80, 25, "OK");
+      c_panel_ok = o;
+      w->hotspot(o);
+    }
+    { Fl_Button* o = new Fl_Button(200, 135, 80, 25, "cancel");
+      c_panel_cancel = o;
+      o->shortcut(0xff1b);
+    }
+    w->end();
+  }
+  return w;
+}
diff --git a/fluid/function_panel.fl b/fluid/function_panel.fl
new file mode 100644
index 000000000..e4ad307f1
--- /dev/null
+++ b/fluid/function_panel.fl
@@ -0,0 +1,164 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 0.99 
+gridx 10 
+gridy 5 
+snap 3
+Function {make_function_panel()} {open
+} {
+  Fl_Window function_panel {
+    label {function/method} open
+    xywh {281 608 287 173} modal visible
+  } {
+    Fl_Light_Button f_public_button {
+      label public
+      xywh {10 15 65 25} labelsize 10 when 0
+    }
+    Fl_Input f_name_input {
+      label {name(args): (blank for main())}
+      xywh {10 60 270 25} labelsize 12 align 5 when 0 resizable
+    }
+    Fl_Input f_return_type_input {
+      label {return type: (blank to return outermost widget)}
+      xywh {10 105 270 25} labelsize 12 align 5 when 0
+    }
+    Fl_Return_Button f_panel_ok {
+      label OK
+      xywh {110 140 80 25} hotspot
+    }
+    Fl_Button f_panel_cancel {
+      label cancel
+      xywh {200 140 80 25} shortcut 0xff1b
+    }
+  }
+} 
+
+Function {make_code_panel()} {open
+} {
+  Fl_Window code_panel {
+    label code open
+    xywh {256 219 291 178} modal visible
+  } {
+    Fl_Input code_input {
+      xywh {6 5 280 135} type Multiline labelsize 12 align 0 when 0 resizable
+    }
+    Fl_Return_Button code_panel_ok {
+      label OK
+      xywh {115 145 80 25} hotspot
+    }
+    Fl_Button code_panel_cancel {
+      label cancel
+      xywh {205 145 80 25} shortcut 0xff1b
+    }
+  }
+} 
+
+Function {make_codeblock_panel()} {open
+} {
+  Fl_Window codeblock_panel {
+    label codeblock open
+    xywh {285 439 293 134} modal visible
+  } {
+    Fl_Input code_before_input {
+      xywh {10 5 275 25} labelsize 12 align 5 when 0 resizable
+    }
+    Fl_Box {} {
+      label {"{...child code...}" is inserted here}
+      xywh {10 35 270 25} align 20
+    }
+    Fl_Input code_after_input {
+      xywh {10 65 275 25} labelsize 12 align 5 when 0
+    }
+    Fl_Return_Button codeblock_panel_ok {
+      label OK
+      xywh {115 100 80 25} hotspot
+    }
+    Fl_Button codeblock_panel_cancel {
+      label cancel
+      xywh {205 100 80 25} shortcut 0xff1b
+    }
+  }
+} 
+
+Function {make_declblock_panel()} {open
+} {
+  Fl_Window declblock_panel {
+    label {declaration block} open
+    xywh {296 118 293 134} modal visible
+  } {
+    Fl_Input decl_before_input {
+      xywh {15 10 275 25} labelsize 12 align 5 when 0 resizable
+    }
+    Fl_Box {} {
+      label {"\\n...child code...\\n" is inserted here}
+      xywh {15 40 270 25} align 20
+    }
+    Fl_Input decl_after_input {
+      xywh {15 70 275 25} labelsize 12 align 5 when 0
+    }
+    Fl_Return_Button declblock_panel_ok {
+      label OK
+      xywh {120 105 80 25} hotspot
+    }
+    Fl_Button declblock_panel_cancel {
+      label cancel
+      xywh {210 105 80 25} shortcut 0xff1b
+    }
+  }
+} 
+
+Function {make_decl_panel()} {open
+} {
+  Fl_Window decl_panel {
+    label declaration open
+    xywh {278 800 290 176} visible
+  } {
+    Fl_Light_Button decl_public_button {
+      label public
+      xywh {10 15 65 25} labelsize 10 when 0
+    }
+    Fl_Input decl_input {
+      label {can be any declartion, like "int x;",
+an external symbol like "extern int foo();",
+a \#directive like "\#include ",
+or a comment like "//foo" or "/*foo*/"}
+      xywh {10 50 270 25} labelsize 12 align 6 when 0 resizable
+    }
+    Fl_Return_Button decl_panel_ok {
+      label OK
+      xywh {115 145 80 25} hotspot
+    }
+    Fl_Button decl_panel_cancel {
+      label cancel
+      xywh {205 145 80 25} shortcut 0xff1b
+    }
+  }
+} 
+
+Function {make_class_panel()} {open
+} {
+  Fl_Window class_panel {
+    label class open selected
+    xywh {291 618 287 173} modal visible
+  } {
+    Fl_Light_Button c_public_button {
+      label public
+      xywh {10 10 65 25} labelsize 10 when 0
+    }
+    Fl_Input c_name_input {
+      label {name:}
+      xywh {10 55 270 25} labelsize 12 align 5 when 0 resizable
+    }
+    Fl_Input c_subclass_input {
+      label {subclass of (text between : and \{)}
+      xywh {10 100 270 25} labelsize 12 align 5 when 0
+    }
+    Fl_Return_Button c_panel_ok {
+      label OK
+      xywh {110 135 80 25} hotspot
+    }
+    Fl_Button c_panel_cancel {
+      label cancel
+      xywh {200 135 80 25} shortcut 0xff1b
+    }
+  }
+} 
diff --git a/fluid/function_panel.h b/fluid/function_panel.h
new file mode 100644
index 000000000..f0a9d2506
--- /dev/null
+++ b/fluid/function_panel.h
@@ -0,0 +1,46 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+extern Fl_Window *function_panel;
+extern Fl_Light_Button *f_public_button;
+extern Fl_Input *f_name_input;
+extern Fl_Input *f_return_type_input;
+extern Fl_Return_Button *f_panel_ok;
+extern Fl_Button *f_panel_cancel;
+extern Fl_Window *code_panel;
+extern Fl_Input *code_input;
+extern Fl_Return_Button *code_panel_ok;
+extern Fl_Button *code_panel_cancel;
+extern Fl_Window *codeblock_panel;
+extern Fl_Input *code_before_input;
+extern Fl_Input *code_after_input;
+extern Fl_Return_Button *codeblock_panel_ok;
+extern Fl_Button *codeblock_panel_cancel;
+extern Fl_Window *declblock_panel;
+extern Fl_Input *decl_before_input;
+extern Fl_Input *decl_after_input;
+extern Fl_Return_Button *declblock_panel_ok;
+extern Fl_Button *declblock_panel_cancel;
+extern Fl_Window *decl_panel;
+extern Fl_Light_Button *decl_public_button;
+extern Fl_Input *decl_input;
+extern Fl_Return_Button *decl_panel_ok;
+extern Fl_Button *decl_panel_cancel;
+extern Fl_Window *class_panel;
+extern Fl_Light_Button *c_public_button;
+extern Fl_Input *c_name_input;
+extern Fl_Input *c_subclass_input;
+extern Fl_Return_Button *c_panel_ok;
+extern Fl_Button *c_panel_cancel;
+Fl_Window* make_function_panel();
+Fl_Window* make_code_panel();
+Fl_Window* make_codeblock_panel();
+Fl_Window* make_declblock_panel();
+Fl_Window* make_decl_panel();
+Fl_Window* make_class_panel();
diff --git a/fluid/gif.cxx b/fluid/gif.cxx
new file mode 100644
index 000000000..1af6556a7
--- /dev/null
+++ b/fluid/gif.cxx
@@ -0,0 +1,336 @@
+// gif.C
+
+// Read a .gif file and convert it to a "xpm" format (actually my
+// modified one with compressed colormaps).
+
+// Extensively modified from original code for gif2ras by
+// Patrick J. Naughton of Sun Microsystems.  The original
+// copyright notice follows:
+
+/* gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image.
+ *
+ * Copyright (c) 1988 by Patrick J. Naughton
+ *
+ * Author: Patrick J. Naughton
+ * naughton@wind.sun.com
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * This file is provided AS IS with no warranties of any kind.  The author
+ * shall have no liability with respect to the infringement of copyrights,
+ * trade secrets or any patents by this file or any part thereof.  In no
+ * event will the author be liable for any lost revenue or profits or
+ * other special, indirect and consequential damages.
+ *
+ * Comments and additions should be sent to the author:
+ *
+ *                     Patrick J. Naughton
+ *                     Sun Microsystems, Inc.
+ *                     2550 Garcia Ave, MS 14-40
+ *                     Mountain View, CA 94043
+ *                     (415) 336-1080
+ */
+
+#include 
+#include 
+#include 
+
+typedef unsigned char uchar;
+
+#define NEXTBYTE getc(GifFile)
+#define GETSHORT(var) var = NEXTBYTE; var += NEXTBYTE << 8
+
+int gif2xpm(
+    const char *infname,// filename for error messages
+    FILE *GifFile,	// file to read
+    char*** datap,	// return xpm data here
+    int** lengthp,	// return line lengths here
+    int inumber		// which image in movie (0 = first)
+) {
+
+  {char b[6];
+  if (fread(b,1,6,GifFile)<6) return 0; /* quit on eof */
+  if (b[0]!='G' || b[1]!='I' || b[2] != 'F') {
+    fprintf(stderr,"%s is not a GIF file.\n", infname); return 0;}
+  if (b[3]!='8' || b[4]>'9' || b[5]!= 'a')
+    fprintf(stderr,"%s is version %c%c%c.\n",infname,b[3],b[4],b[5]);
+  }
+
+  int Width; GETSHORT(Width);
+  int Height; GETSHORT(Height);
+
+  uchar ch = NEXTBYTE;
+  char HasColormap = ((ch & 0x80) != 0);
+  int BitsPerPixel = (ch & 7) + 1;
+  int ColorMapSize = 1 << BitsPerPixel;
+  // int OriginalResolution = ((ch>>4)&7)+1;
+  // int SortedTable = (ch&8)!=0;
+  NEXTBYTE; // Background Color index
+  NEXTBYTE; // Aspect ratio is N/64
+
+  // Read in global colormap:
+  uchar transparent_pixel = 0;
+  char has_transparent = 0;
+  uchar Red[256], Green[256], Blue[256]; /* color map */
+  if (HasColormap) {
+    for (int i=0; i < ColorMapSize; i++) {	
+      Red[i] = NEXTBYTE;
+      Green[i] = NEXTBYTE;
+      Blue[i] = NEXTBYTE;
+    }
+  } else {
+    fprintf(stderr,"%s does not have a colormap.\n", infname);
+    for (int i = 0; i < ColorMapSize; i++)
+      Red[i] = Green[i] = Blue[i] = (i*256+ColorMapSize-1)/ColorMapSize;
+  }
+
+  int CodeSize;		/* Code size, init from GIF header, increases... */
+  char Interlace;
+
+  for (;;) {
+
+    int i = NEXTBYTE;
+    if (i<0) {fprintf(stderr,"%s: unexpected EOF\n",infname); return 0;}
+    int blocklen;
+
+    //  if (i == 0x3B) return 0;  eof code
+
+    if (i == 0x21) {		// a "gif extension"
+
+      ch = NEXTBYTE;
+      blocklen = NEXTBYTE;
+
+      if (ch==0xF9 && blocklen==4) { // Netscape animation extension
+
+	char bits;
+	bits = NEXTBYTE;
+	NEXTBYTE; NEXTBYTE; // GETSHORT(delay);
+	transparent_pixel = NEXTBYTE;
+	if (bits & 1) has_transparent = 1;
+	blocklen = NEXTBYTE;
+
+      } else if (ch == 0xFF) { // Netscape repeat count
+	;
+
+      } else if (ch == 0xFE) { //Gif Comment
+#if 0
+	if(blocklen>0) {
+	  char *comment=new char[blocklen+1];
+	  int l;
+	  for(l=0;blocklen;l++,blocklen--)
+	    comment[l]=NEXTBYTE;
+	  comment[l]=0;
+	  fprintf(stderr,"%s: Gif Comment: '%s'\n", infname, comment);
+	  delete comment;
+	  NEXTBYTE; //End marker
+	}
+#endif 
+      } else {
+	fprintf(stderr,"%s: unknown gif extension 0x%02x\n", infname, ch);
+
+      }
+
+    } else if (i == 0x2c) {	// an image
+
+      NEXTBYTE; NEXTBYTE; // GETSHORT(x_position);
+      NEXTBYTE; NEXTBYTE; // GETSHORT(y_position);
+      GETSHORT(Width);
+      GETSHORT(Height);
+      ch = NEXTBYTE;
+      Interlace = ((ch & 0x40) != 0);
+      if (ch&0x80) { 
+	// read local color map
+	int n = 1<<((ch&7)+1); // does this replace ColorMapSize ??
+	for (i=0; i < n; i++) {	
+	  Red[i] = NEXTBYTE;
+	  Green[i] = NEXTBYTE;
+	  Blue[i] = NEXTBYTE;
+	}
+      }
+      CodeSize = NEXTBYTE+1;
+
+      if (!inumber--) break; // okay, this is the image we want
+      blocklen = NEXTBYTE;
+      
+    } else {
+      fprintf(stderr,"%s: unknown gif code 0x%02x\n", infname, i);
+      blocklen = 0;
+    }
+
+    // skip the data:
+    while (blocklen>0) {while (blocklen--) {NEXTBYTE;} blocklen=NEXTBYTE;}
+  }
+
+  uchar *Image = new uchar[Width*Height];
+  if (!Image) {
+    fprintf (stderr, "Insufficient memory\n");
+    exit (2);
+  }
+  int YC = 0, Pass = 0; /* Used to de-interlace the picture */
+  uchar *p = Image;
+  uchar *eol = p+Width;
+
+  int InitCodeSize = CodeSize;
+  int ClearCode = (1 << (CodeSize-1));
+  int EOFCode = ClearCode + 1;
+  int FirstFree = ClearCode + 2;
+  int FinChar = 0;
+  int ReadMask = (1< 7) {
+      if (blocklen <= 0) {
+	blocklen = NEXTBYTE;
+	if (blocklen <= 0) break;
+      }
+      thisbyte = NEXTBYTE; blocklen--;
+      CurCode |= thisbyte<<8;
+    }
+    if (frombit+CodeSize > 15) {
+      if (blocklen <= 0) {
+	blocklen = NEXTBYTE;
+	if (blocklen <= 0) break;
+      }
+      thisbyte = NEXTBYTE; blocklen--;
+      CurCode |= thisbyte<<16;
+    }
+    CurCode = (CurCode>>frombit)&ReadMask;
+    frombit = (frombit+CodeSize)%8;
+
+    if (CurCode == ClearCode) {
+      CodeSize = InitCodeSize;
+      ReadMask = (1<= ColorMapSize) {*tp++ = Suffix[i]; i = Prefix[i];}
+    *tp++ = FinChar = i;
+    while (tp > OutCode) {
+      *p++ = *--tp;
+      if (p >= eol) {
+	if (!Interlace) YC++;
+	else switch (Pass) {
+	case 0: YC += 8; if (YC >= Height) {Pass++; YC = 4;} break;
+	case 1: YC += 8; if (YC >= Height) {Pass++; YC = 2;} break;
+	case 2: YC += 4; if (YC >= Height) {Pass++; YC = 1;} break;
+	case 3: YC += 2; break;
+	}
+	if (YC>=Height) YC=0; /* cheap bug fix when excess data */
+	p = Image + YC*Width;
+	eol = p+Width;
+      }
+    }
+
+    if (OldCode != ClearCode) {
+      Prefix[FreeCode] = OldCode;
+      Suffix[FreeCode] = FinChar;
+      FreeCode++;
+      if (FreeCode > ReadMask) {
+	if (CodeSize < 12) {
+	  CodeSize++;
+	  ReadMask = (1 << CodeSize) - 1;
+	}
+	else FreeCode--;
+      }
+    }
+    OldCode = CurCode;
+  }
+
+  // We are done reading the file, now convert to xpm:
+
+  // allocate line pointer arrays:
+  char** data = new char*[Height+3];
+  *datap = data;
+  int* length = new int[Height+2];
+  *lengthp = length;
+
+  // transparent pixel must be zero, swap if it isn't:
+  if (has_transparent && transparent_pixel != 0) {
+    // swap transparent pixel with zero
+    p = Image+Width*Height;
+    while (p-- > Image) {
+      if (*p==transparent_pixel) *p = 0;
+      else if (!*p) *p = transparent_pixel;
+    }
+    uchar t;
+    t = Red[0]; Red[0] = Red[transparent_pixel]; Red[transparent_pixel] = t;
+    t =Green[0];Green[0]=Green[transparent_pixel];Green[transparent_pixel]=t;
+    t =Blue[0];Blue[0] =Blue[transparent_pixel];Blue[transparent_pixel] = t;
+  }
+
+  // find out what colors are actually used:
+  uchar used[256]; uchar remap[256];
+  int i;
+  for (i = 0; i < ColorMapSize; i++) used[i] = 0;
+  p = Image+Width*Height;
+  while (p-- > Image) used[*p] = 1;
+
+  // remap them to start with printing characters:
+  int base = has_transparent && used[0] ? ' ' : ' '+1;
+  int numcolors = 0;
+  for (i = 0; i < ColorMapSize; i++) if (used[i]) {
+    remap[i] = base++;
+    numcolors++;
+  }
+
+  // write the first line of xpm data (use suffix as temp array):
+  length[0] = sprintf((char*)(Suffix),
+		      "%d %d %d %d",Width,Height,-numcolors,1);
+  data[0] = new char[length[0]+1];
+  strcpy(data[0], (char*)Suffix);
+
+  // write the colormap
+  length[1] = 4*numcolors;
+  data[1] = (char*)(p = new uchar[4*numcolors]);
+  for (i = 0; i < ColorMapSize; i++) if (used[i]) {
+    *p++ = remap[i];
+    *p++ = Red[i];
+    *p++ = Green[i];
+    *p++ = Blue[i];
+  }
+
+  // remap the image data:
+  p = Image+Width*Height;
+  while (p-- > Image) *p = remap[*p];
+
+  // split the image data into lines:
+  for (i=0; ilabelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Escape));
+ }
+ {Fl_Button* o = new Fl_Button(50, 50, 20, 20, "F1");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+1));
+ }
+ {Fl_Button* o = new Fl_Button(70, 50, 20, 20, "F2");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+2));
+ }
+ {Fl_Button* o = new Fl_Button(90, 50, 20, 20, "F3");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+3));
+ }
+ {Fl_Button* o = new Fl_Button(110, 50, 20, 20, "F4");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+4));
+ }
+ {Fl_Button* o = new Fl_Button(140, 50, 20, 20, "F5");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+5));
+ }
+ {Fl_Button* o = new Fl_Button(160, 50, 20, 20, "F6");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+6));
+ }
+ {Fl_Button* o = new Fl_Button(180, 50, 20, 20, "F7");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+7));
+ }
+ {Fl_Button* o = new Fl_Button(200, 50, 20, 20, "F8");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+8));
+ }
+ {Fl_Button* o = new Fl_Button(230, 50, 20, 20, "F9");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+9));
+ }
+ {Fl_Button* o = new Fl_Button(250, 50, 20, 20, "F10");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+10));
+ }
+ {Fl_Button* o = new Fl_Button(270, 50, 20, 20, "F11");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+11));
+ }
+ {Fl_Button* o = new Fl_Button(290, 50, 20, 20, "F12");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+12));
+ }
+ {Fl_Button* o = new Fl_Button(325, 50, 20, 20, "Print");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Print));
+ }
+ {Fl_Button* o = new Fl_Button(345, 50, 20, 20, "Sclk");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Scroll_Lock));
+ }
+ {Fl_Button* o = new Fl_Button(365, 50, 20, 20, "Paus");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Pause));
+ }
+ {Fl_Button* o = new Fl_Button(15, 80, 20, 20, "`");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(35, 80, 20, 20, "1");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(55, 80, 20, 20, "2");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(75, 80, 20, 20, "3");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(95, 80, 20, 20, "4");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(115, 80, 20, 20, "5");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(135, 80, 20, 20, "6");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(155, 80, 20, 20, "7");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(175, 80, 20, 20, "8");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(195, 80, 20, 20, "9");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(215, 80, 20, 20, "0");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(235, 80, 20, 20, "-");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(255, 80, 20, 20, "=");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(275, 80, 35, 20, "Bksp");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_BackSpace));
+ }
+ {Fl_Button* o = new Fl_Button(325, 80, 20, 20, "Ins");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Insert));
+ }
+ {Fl_Button* o = new Fl_Button(345, 80, 20, 20, "Home");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Home));
+ }
+ {Fl_Button* o = new Fl_Button(365, 80, 20, 20, "pgup");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Page_Up));
+ }
+ {Fl_Button* o = new Fl_Button(400, 80, 20, 20, "Num");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Num_Lock));
+ }
+ {Fl_Button* o = new Fl_Button(420, 80, 20, 20, "/");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'/'));
+ }
+ {Fl_Button* o = new Fl_Button(440, 80, 20, 20, "*");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'*'));
+ }
+ {Fl_Button* o = new Fl_Button(460, 80, 20, 20, "-");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'-'));
+ }
+ {Fl_Button* o = new Fl_Button(15, 100, 27, 20, "Tab");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Tab));
+ }
+ {Fl_Button* o = new Fl_Button(42, 100, 20, 20, "Q");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(62, 100, 20, 20, "W");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(82, 100, 20, 20, "E");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(102, 100, 20, 20, "R");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(122, 100, 20, 20, "T");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(142, 100, 20, 20, "Y");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(162, 100, 20, 20, "U");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(182, 100, 20, 20, "I");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(202, 100, 20, 20, "O");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(222, 100, 20, 20, "P");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(242, 100, 20, 20, "[");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(262, 100, 20, 20, "]");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(282, 100, 28, 20, "\\");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)('|'));
+  o->align(20);
+ }
+ {Fl_Button* o = new Fl_Button(325, 100, 20, 20, "Del");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Delete));
+ }
+ {Fl_Button* o = new Fl_Button(345, 100, 20, 20, "End");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_End));
+ }
+ {Fl_Button* o = new Fl_Button(365, 100, 20, 20, "pgdn");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Page_Down));
+ }
+ {Fl_Button* o = new Fl_Button(400, 100, 20, 20, "7");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'7'));
+ }
+ {Fl_Button* o = new Fl_Button(420, 100, 20, 20, "8");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'8'));
+ }
+ {Fl_Button* o = new Fl_Button(440, 100, 20, 20, "9");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'9'));
+ }
+ {Fl_Button* o = new Fl_Button(460, 100, 20, 40, "+");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'+'));
+  o->align(17);
+ }
+ {Fl_Button* o = new Fl_Button(15, 120, 36, 20, "Lock");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Caps_Lock));
+ }
+ {Fl_Button* o = new Fl_Button(51, 120, 20, 20, "A");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(71, 120, 20, 20, "S");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(91, 120, 20, 20, "D");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(111, 120, 20, 20, "F");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(131, 120, 20, 20, "G");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(151, 120, 20, 20, "H");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(171, 120, 20, 20, "J");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(191, 120, 20, 20, "K");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(211, 120, 20, 20, "L");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(231, 120, 20, 20, ";");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(251, 120, 20, 20, "\'");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(271, 120, 39, 20, "Enter");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Enter));
+ }
+ {Fl_Button* o = new Fl_Button(400, 120, 20, 20, "4");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'4'));
+ }
+ {Fl_Button* o = new Fl_Button(420, 120, 20, 20, "5");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'5'));
+ }
+ {Fl_Button* o = new Fl_Button(440, 120, 20, 20, "6");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'6'));
+ }
+ {Fl_Button* o = new Fl_Button(15, 140, 45, 20, "Shift");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Shift_L));
+ }
+ {Fl_Button* o = new Fl_Button(60, 140, 20, 20, "Z");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(80, 140, 20, 20, "X");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(100, 140, 20, 20, "C");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(120, 140, 20, 20, "V");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(140, 140, 20, 20, "B");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(160, 140, 20, 20, "N");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(180, 140, 20, 20, "M");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(200, 140, 20, 20, ",");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(220, 140, 20, 20, ".");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(240, 140, 20, 20, "/");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(260, 140, 50, 20, "Shift");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Shift_R));
+ }
+ {Fl_Button* o = new Fl_Button(345, 140, 20, 20, "@8->");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->labelsize(10);
+  o->labelcolor(47);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Up));
+ }
+ {Fl_Button* o = new Fl_Button(400, 140, 20, 20, "1");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'1'));
+ }
+ {Fl_Button* o = new Fl_Button(420, 140, 20, 20, "2");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'2'));
+ }
+ {Fl_Button* o = new Fl_Button(440, 140, 20, 20, "3");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'3'));
+ }
+ {Fl_Button* o = new Fl_Button(460, 140, 20, 40);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP_Enter));
+ }
+ {Fl_Button* o = new Fl_Button(15, 160, 30, 20, "Ctrl");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Control_L));
+ }
+ {Fl_Button* o = new Fl_Button(45, 160, 30, 20, "Meta");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Meta_L));
+ }
+ {Fl_Button* o = new Fl_Button(75, 160, 30, 20, "Alt");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Alt_L));
+ }
+ {Fl_Button* o = new Fl_Button(105, 160, 85, 20);
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(' '));
+ }
+ {Fl_Button* o = new Fl_Button(190, 160, 30, 20, "Alt");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Alt_R));
+ }
+ {Fl_Button* o = new Fl_Button(220, 160, 30, 20, "Meta");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Meta_R));
+ }
+ {Fl_Button* o = new Fl_Button(250, 160, 30, 20, "Menu");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Menu));
+ }
+ {Fl_Button* o = new Fl_Button(280, 160, 30, 20, "Ctrl");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Control_R));
+ }
+ {Fl_Button* o = new Fl_Button(325, 160, 20, 20, "@4->");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->labelsize(10);
+  o->labelcolor(47);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Left));
+ }
+ {Fl_Button* o = new Fl_Button(345, 160, 20, 20, "@2->");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->labelsize(10);
+  o->labelcolor(47);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Down));
+ }
+ {Fl_Button* o = new Fl_Button(365, 160, 20, 20, "@6->");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->labelsize(10);
+  o->labelcolor(47);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Right));
+ }
+ {Fl_Button* o = new Fl_Button(400, 160, 40, 20, "0");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'0'));
+  o->align(20);
+ }
+ {Fl_Button* o = new Fl_Button(440, 160, 20, 20, ".");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'.'));
+ }
+ {Fl_Input* o = new Fl_Input(15, 10, 370, 30);
+ }
+ {Fl_Button* o = new Fl_Button(400, 5, 20, 10, "shift");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_SHIFT));
+ }
+ {Fl_Button* o = new Fl_Button(420, 5, 20, 10, "lock");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_CAPS_LOCK));
+ }
+ {Fl_Button* o = new Fl_Button(440, 5, 20, 10, "ctrl");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_CTRL));
+ }
+ {Fl_Button* o = new Fl_Button(460, 5, 20, 10, "alt");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_ALT));
+ }
+ {Fl_Button* o = new Fl_Button(440, 15, 20, 10, "meta");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_META));
+ }
+ {Fl_Button* o = new Fl_Button(420, 15, 20, 10, "?");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(0x20));
+ }
+ {Fl_Button* o = new Fl_Button(400, 15, 20, 10, "num");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_NUM_LOCK));
+ }
+ {Fl_Button* o = new Fl_Button(400, 25, 20, 10, "b1");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_BUTTON1));
+ }
+ {Fl_Button* o = new Fl_Button(420, 25, 20, 10, "b2");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_BUTTON2));
+ }
+ {Fl_Button* o = new Fl_Button(440, 25, 20, 10, "b3");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_BUTTON3));
+ }
+ {Fl_Button* o = new Fl_Button(460, 15, 20, 10, "sclk");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_SCROLL_LOCK));
+ }
+ {Fl_Button* o = new Fl_Button(460, 25, 20, 10, "?");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(0x800));
+ }
+ {Fl_Button* o = new Fl_Button(400, 35, 20, 10, "?");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(0x1000));
+ }
+ {Fl_Button* o = new Fl_Button(420, 35, 20, 10, "?");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(0x2000));
+ }
+ {Fl_Button* o = new Fl_Button(440, 35, 20, 10, "?");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(0x4000));
+ }
+ {Fl_Button* o = new Fl_Button(460, 35, 20, 10, "?");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(0x8000));
+ }
+ w->end();
+ return w;
+}
diff --git a/fluid/keyboard_ui.h b/fluid/keyboard_ui.h
new file mode 100644
index 000000000..ec1ba7722
--- /dev/null
+++ b/fluid/keyboard_ui.h
@@ -0,0 +1,8 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+#include 
+#include 
+#include 
+#include 
+extern void key_cb(Fl_Button*, void*);
+extern void shift_cb(Fl_Button*, void*);
+Fl_Window *make_window();
diff --git a/fluid/penne.C b/fluid/penne.C
new file mode 100644
index 000000000..cc1db0937
--- /dev/null
+++ b/fluid/penne.C
@@ -0,0 +1,85 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "penne.H"
+
+inline void UserInterface::cb_New_i(Fl_Button*, void*) {
+  new UserInterface;
+}
+void UserInterface::cb_New(Fl_Button* o, void* v) {
+  ((UserInterface*)(o->parent()->user_data()))->cb_New_i(o,v);
+}
+
+inline void UserInterface::cb_Delete_i(Fl_Button*, void*) {
+  delete this;
+}
+void UserInterface::cb_Delete(Fl_Button* o, void* v) {
+  ((UserInterface*)(o->parent()->user_data()))->cb_Delete_i(o,v);
+}
+
+inline void UserInterface::cb_button1_i(Fl_Light_Button* o, void*) {
+  Button->value(o->value());
+}
+void UserInterface::cb_button1(Fl_Light_Button* o, void* v) {
+  ((UserInterface*)(o->parent()->user_data()))->cb_button1_i(o,v);
+}
+
+inline void UserInterface::cb_When_i(Fl_Menu_* o, void*) {
+  Button->value(o->value());
+}
+void UserInterface::cb_When(Fl_Menu_* o, void* v) {
+  ((UserInterface*)(o->parent()->user_data()))->cb_When_i(o,v);
+}
+
+Fl_Menu_Item UserInterface::menu_[] = {
+ {"coucou", 0,  0, 0, 64, 0, 3, 14, 0},
+ {"When you press this, it should crash !", 0,  (Fl_Callback*)UserInterface::cb_When, 0, 2, 0, 3, 14, 0},
+ {0},
+ {0}
+};
+
+UserInterface::UserInterface() {
+  Fl_Window *w;
+  { Fl_Window* o = new Fl_Window(375, 199);
+    w = Win = o;
+    o->user_data((void*)(this));
+    { Fl_Button* o = new Fl_Button(35, 145, 120, 35, "New window");
+      o->callback((Fl_Callback*)cb_New);
+    }
+    { Fl_Button* o = new Fl_Button(215, 145, 120, 35, "Delete window");
+      o->callback((Fl_Callback*)cb_Delete);
+    }
+    { Fl_Light_Button* o = new Fl_Light_Button(45, 25, 95, 25, "button1");
+      o->callback((Fl_Callback*)cb_button1);
+    }
+    { Fl_Check_Button* o = new Fl_Check_Button(220, 25, 95, 25, "button2");
+      Button = o;
+      o->down_box(FL_DIAMOND_DOWN_BOX);
+    }
+    { Fl_Tile* o = new Fl_Tile(110, 55, 165, 80);
+      { Fl_Box* o = new Fl_Box(110, 55, 165, 50, "label");
+        o->box(FL_DOWN_BOX);
+      }
+      { Fl_Box* o = new Fl_Box(110, 105, 80, 30, "label");
+        o->box(FL_DOWN_BOX);
+      }
+      { Fl_Box* o = new Fl_Box(190, 105, 85, 30, "label");
+        o->box(FL_DOWN_BOX);
+      }
+      o->end();
+    }
+    { Fl_Menu_Bar* o = new Fl_Menu_Bar(0, 0, 375, 25);
+      o->menu(menu_);
+    }
+    w->end();
+  }
+  Win->show();
+}
+
+UserInterface::~UserInterface() {
+  delete Win;
+}
+
+int main() {
+  new UserInterface;
+return Fl::run();
+}
diff --git a/fluid/penne.H b/fluid/penne.H
new file mode 100644
index 000000000..ebabab473
--- /dev/null
+++ b/fluid/penne.H
@@ -0,0 +1,32 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+class UserInterface {
+public:
+  UserInterface();
+  Fl_Window *Win;
+private:
+  inline void cb_New_i(Fl_Button*, void*);
+  static void cb_New(Fl_Button*, void*);
+  inline void cb_Delete_i(Fl_Button*, void*);
+  static void cb_Delete(Fl_Button*, void*);
+  inline void cb_button1_i(Fl_Light_Button*, void*);
+  static void cb_button1(Fl_Light_Button*, void*);
+public:
+  Fl_Check_Button *Button;
+  static Fl_Menu_Item menu_[];
+private:
+  inline void cb_When_i(Fl_Menu_*, void*);
+  static void cb_When(Fl_Menu_*, void*);
+public:
+  ~UserInterface();
+};
+int main();
diff --git a/fluid/primes.fl b/fluid/primes.fl
new file mode 100644
index 000000000..e221b739a
--- /dev/null
+++ b/fluid/primes.fl
@@ -0,0 +1,22 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 0.99 
+gridx 10 
+gridy 10 
+snap 3
+decl {// This is a demo of fluid used to write a normal C program} {} 
+
+decl {\#include } {} 
+
+Function {main()} {open selected
+} {
+  code {printf("%d ", 2);} {}
+  codeblock {for (int x=3; x < 10000; x += 2)} {open
+  } {
+    code {for (int y=3; x%y; y += 2)} {}
+    codeblock {if (y*y > x)} {open
+    } {
+      code {printf("%d ", x);
+break;} {}
+    }
+  }
+} 
diff --git a/fluid/widget_panel.cxx b/fluid/widget_panel.cxx
new file mode 100644
index 000000000..23ee01e19
--- /dev/null
+++ b/fluid/widget_panel.cxx
@@ -0,0 +1,316 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "widget_panel.H"
+
+Fl_Input *v_input[4];
+
+Fl_Window* make_widget_panel() {
+  Fl_Window *w;
+  { Fl_Window* o = w = new Fl_Window(370, 480);
+    w->hotspot(o);
+    { Fl_Input* o = new Fl_Input(90, 10, 210, 20, "name:");
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)name_cb);
+      o->when(0);
+    }
+    { Fl_Light_Button* o = new Fl_Light_Button(300, 10, 60, 20, "public");
+      o->box(FL_THIN_UP_BOX);
+      o->selection_color(1);
+      o->labelsize(10);
+      o->callback((Fl_Callback*)name_public_cb);
+      o->when(1);
+    }
+    { Fl_Input* o = new Fl_Input(90, 35, 170, 20, "class:");
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)subclass_cb, (void*)(4));
+      o->when(0);
+    }
+    { Fl_Choice* o = new Fl_Choice(260, 35, 100, 20);
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)subtype_cb);
+    }
+    { Fl_Input* o = new Fl_Input(90, 60, 270, 20, "label:");
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)label_cb);
+      o->when(1);
+    }
+    { Fl_Choice* o = new Fl_Choice(90, 80, 150, 20, "labeltype:");
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)labeltype_cb);
+      o->menu(labeltypemenu);
+    }
+    { Fl_Button* o = new Fl_Button(240, 80, 20, 20, "@-1<-");
+      o->type(1);
+      o->box(FL_THIN_UP_BOX);
+      o->labeltype(FL_SYMBOL_LABEL);
+      o->labelcolor(8);
+      o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_LEFT));
+    }
+    { Fl_Button* o = new Fl_Button(260, 80, 20, 20, "@-1->");
+      o->type(1);
+      o->box(FL_THIN_UP_BOX);
+      o->labeltype(FL_SYMBOL_LABEL);
+      o->labelcolor(8);
+      o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_RIGHT));
+    }
+    { Fl_Button* o = new Fl_Button(280, 80, 20, 20, "@-18");
+      o->type(1);
+      o->box(FL_THIN_UP_BOX);
+      o->labeltype(FL_SYMBOL_LABEL);
+      o->labelcolor(8);
+      o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_TOP));
+    }
+    { Fl_Button* o = new Fl_Button(300, 80, 20, 20, "@-12");
+      o->type(1);
+      o->box(FL_THIN_UP_BOX);
+      o->labeltype(FL_SYMBOL_LABEL);
+      o->labelcolor(8);
+      o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_BOTTOM));
+    }
+    { Fl_Button* o = new Fl_Button(320, 80, 20, 20, "@-3square");
+      o->type(1);
+      o->box(FL_THIN_UP_BOX);
+      o->labeltype(FL_SYMBOL_LABEL);
+      o->labelcolor(8);
+      o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_INSIDE));
+    }
+    { Fl_Button* o = new Fl_Button(340, 80, 20, 10, "wrap");
+      o->type(1);
+      o->box(FL_THIN_UP_BOX);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_WRAP));
+    }
+    { Fl_Button* o = new Fl_Button(340, 90, 20, 10, "clip");
+      o->type(1);
+      o->box(FL_THIN_UP_BOX);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)align_cb, (void*)(FL_ALIGN_CLIP));
+    }
+    { Fl_Choice* o = new Fl_Choice(90, 100, 170, 20, "labelfont:");
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)labelfont_cb);
+      o->menu(fontmenu);
+    }
+    { Fl_Value_Input* o = new Fl_Value_Input(260, 100, 50, 20);
+      o->box(FL_THIN_UP_BOX);
+      o->maximum(100);
+      o->step(1);
+      o->value(14);
+      o->callback((Fl_Callback*)labelsize_cb);
+    }
+    { Fl_Button* o = new Fl_Button(310, 100, 50, 20, "labelcolor");
+      o->box(FL_THIN_UP_BOX);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)labelcolor_cb);
+    }
+    { Fl_Choice* o = new Fl_Choice(90, 125, 220, 20, "box:");
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)box_cb);
+      o->menu(boxmenu);
+    }
+    { Fl_Button* o = new Fl_Button(310, 125, 50, 20, "color");
+      o->box(FL_THIN_UP_BOX);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)color_cb);
+    }
+    { Fl_Choice* o = new Fl_Choice(90, 145, 220, 20, "down_box:");
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)down_box_cb);
+      o->menu(boxmenu);
+    }
+    { Fl_Button* o = new Fl_Button(310, 145, 50, 20, "select color");
+      o->box(FL_THIN_UP_BOX);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)color2_cb);
+    }
+    { Fl_Choice* o = new Fl_Choice(90, 170, 170, 20, "textfont:");
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)textfont_cb);
+      o->hide();
+      o->menu(fontmenu);
+    }
+    { Fl_Input* o = new Fl_Input(90, 170, 170, 20, "xclass:");
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)xclass_cb);
+      o->when(0);
+    }
+    { Shortcut_Button* o = new Shortcut_Button(90, 170, 270, 20, "shortcut:");
+      o->box(FL_THIN_UP_BOX);
+      o->color(7);
+      o->selection_color(7);
+      o->callback((Fl_Callback*)shortcut_in_cb);
+      o->align(4);
+    }
+    { Fl_Value_Input* o = new Fl_Value_Input(260, 170, 50, 20);
+      o->box(FL_THIN_UP_BOX);
+      o->maximum(100);
+      o->step(1);
+      o->value(14);
+      o->callback((Fl_Callback*)textsize_cb);
+      o->hide();
+    }
+    { Fl_Button* o = new Fl_Button(310, 170, 50, 20, "textcolor");
+      o->box(FL_THIN_UP_BOX);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)textcolor_cb);
+      o->hide();
+    }
+    { Fl_Value_Input* o = new Fl_Value_Input(20, 205, 60, 20, "size:");
+      o->box(FL_THIN_UP_BOX);
+      o->labelsize(10);
+      o->step(0.010101);
+      o->callback((Fl_Callback*)slider_size_cb);
+      o->align(5);
+    }
+    { Fl_Value_Input* o = new Fl_Value_Input(90, 205, 60, 20, "minimum:");
+      o->box(FL_THIN_UP_BOX);
+      o->labelsize(10);
+      o->callback((Fl_Callback*)min_cb);
+      o->align(5);
+    }
+    { Fl_Value_Input* o = new Fl_Value_Input(160, 205, 60, 20, "maximum:");
+      o->box(FL_THIN_UP_BOX);
+      o->labelsize(10);
+      o->value(1);
+      o->callback((Fl_Callback*)max_cb);
+      o->align(5);
+    }
+    { Fl_Value_Input* o = new Fl_Value_Input(230, 205, 60, 20, "step:");
+      o->box(FL_THIN_UP_BOX);
+      o->labelsize(10);
+      o->callback((Fl_Callback*)step_cb);
+      o->align(5);
+    }
+    { Fl_Value_Input* o = new Fl_Value_Input(300, 205, 60, 20, "value:");
+      o->box(FL_THIN_UP_BOX);
+      o->labelsize(10);
+      o->callback((Fl_Callback*)value_cb);
+      o->align(5);
+    }
+    { Fl_Group* o = new Fl_Group(20, 230, 340, 20);
+      o->callback((Fl_Callback*)propagate_load);
+      o->align(5);
+      { Fl_Light_Button* o = new Fl_Light_Button(20, 230, 70, 20, "non_modal");
+        o->box(FL_THIN_UP_BOX);
+        o->selection_color(1);
+        o->labelsize(9);
+        o->callback((Fl_Callback*)non_modal_cb);
+        o->align(148);
+      }
+      { Fl_Light_Button* o = new Fl_Light_Button(90, 230, 60, 20, "visible");
+        o->box(FL_THIN_UP_BOX);
+        o->selection_color(1);
+        o->labelsize(10);
+        o->callback((Fl_Callback*)visible_cb);
+      }
+      { Fl_Light_Button* o = new Fl_Light_Button(90, 230, 60, 20, "modal");
+        o->box(FL_THIN_UP_BOX);
+        o->selection_color(1);
+        o->labelsize(10);
+        o->callback((Fl_Callback*)modal_cb);
+      }
+      { Fl_Light_Button* o = new Fl_Light_Button(160, 230, 60, 20, "active");
+        o->box(FL_THIN_UP_BOX);
+        o->selection_color(1);
+        o->labelsize(10);
+        o->callback((Fl_Callback*)active_cb);
+      }
+      { Fl_Light_Button* o = new Fl_Light_Button(160, 230, 60, 20, "border");
+        o->box(FL_THIN_UP_BOX);
+        o->selection_color(1);
+        o->labelsize(10);
+        o->callback((Fl_Callback*)border_cb);
+      }
+      { Fl_Light_Button* o = new Fl_Light_Button(230, 230, 60, 20, "resizable");
+        o->box(FL_THIN_UP_BOX);
+        o->selection_color(1);
+        o->labelsize(10);
+        o->callback((Fl_Callback*)resizable_cb);
+        o->when(1);
+      }
+      { Fl_Light_Button* o = new Fl_Light_Button(300, 230, 60, 20, "hotspot");
+        o->box(FL_THIN_UP_BOX);
+        o->selection_color(1);
+        o->labelsize(10);
+        o->callback((Fl_Callback*)hotspot_cb);
+        o->when(1);
+      }
+      o->end();
+    }
+    { Fl_Input* o = v_input[0] = new Fl_Input(90, 260, 270, 20, "extra code:");
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)v_input_cb, (void*)(0));
+      o->when(0);
+    }
+    { Fl_Input* o = v_input[1] = new Fl_Input(90, 280, 270, 20);
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)v_input_cb, (void*)(1));
+      o->when(0);
+    }
+    { Fl_Input* o = v_input[2] = new Fl_Input(90, 300, 270, 20);
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)v_input_cb, (void*)(2));
+      o->when(0);
+    }
+    { Fl_Input* o = v_input[3] = new Fl_Input(90, 320, 270, 20);
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)v_input_cb, (void*)(3));
+      o->when(0);
+    }
+    { Fl_Box* o = new Fl_Box(0, 350, 90, 20, "callback:");
+      o->align(24);
+    }
+    { Fl_Input* o = new Fl_Input(90, 350, 270, 50);
+      o->type(4);
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)callback_cb);
+      o->when(0);
+    }
+    { Fl_Box* o = new Fl_Box(90, 370, 100, 30, "label");
+      o->hide();
+      o->deactivate();
+      Fl_Group::current()->resizable(o);
+    }
+    { Fl_Input* o = new Fl_Input(90, 400, 170, 20, "user_data:");
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)user_data_cb);
+      o->when(0);
+    }
+    { Fl_Input* o = new Fl_Input(300, 400, 60, 20, "type:");
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)user_data_type_cb);
+      o->when(0);
+    }
+    { Fl_Choice* o = new Fl_Choice(90, 420, 100, 20, "when:");
+      o->box(FL_THIN_UP_BOX);
+      o->callback((Fl_Callback*)when_cb);
+      o->when(0);
+      o->menu(whenmenu);
+    }
+    { Fl_Light_Button* o = new Fl_Light_Button(190, 420, 70, 20, "no change");
+      o->box(FL_THIN_UP_BOX);
+      o->selection_color(1);
+      o->labelsize(10);
+      o->callback((Fl_Callback*)when_button_cb);
+      o->when(0);
+    }
+    { Fl_Group* o = new Fl_Group(10, 450, 350, 20);
+      { Fl_Button* o = new Fl_Button(10, 450, 80, 20, "no &overlay");
+        o->labelcolor(1);
+        o->callback((Fl_Callback*)overlay_cb);
+      }
+      { Fl_Button* o = new Fl_Button(100, 450, 80, 20, "Revert");
+        o->callback((Fl_Callback*)revert_cb);
+      }
+      { Fl_Button* o = new Fl_Button(190, 450, 80, 20, "Cancel");
+        o->callback((Fl_Callback*)cancel_cb);
+      }
+      { Fl_Return_Button* o = new Fl_Return_Button(280, 450, 80, 20, "OK");
+        o->callback((Fl_Callback*)ok_cb);
+      }
+      o->end();
+    }
+    o->end();
+  }
+  return w;
+}
diff --git a/fluid/widget_panel.fl b/fluid/widget_panel.fl
new file mode 100644
index 000000000..0fb973c51
--- /dev/null
+++ b/fluid/widget_panel.fl
@@ -0,0 +1,300 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 0.99 
+header_name {.H} 
+code_name {.C} 
+gridx 10 
+gridy 5 
+snap 3
+Function {make_widget_panel()} {open
+} {
+  Fl_Window {} {open
+    xywh {189 164 370 480} hotspot visible
+  } {
+    Fl_Input {} {
+      label {name:}
+      callback name_cb
+      xywh {90 10 210 20} box THIN_UP_BOX when 0
+    }
+    Fl_Light_Button {} {
+      label public
+      callback name_public_cb
+      xywh {300 10 60 20} box THIN_UP_BOX color {49 1} labelsize 10 when 1
+    }
+    Fl_Input {} {
+      label {class:}
+      user_data 4
+      callback subclass_cb
+      xywh {90 35 170 20} box THIN_UP_BOX when 0
+    }
+    Fl_Choice {} {
+      callback subtype_cb
+      xywh {260 35 100 20} box THIN_UP_BOX
+    } {}
+    Fl_Input {} {
+      label {label:}
+      callback label_cb
+      xywh {90 60 270 20} box THIN_UP_BOX when 1
+    }
+    Fl_Choice {} {
+      label {labeltype:}
+      callback labeltype_cb
+      xywh {90 80 150 20} box THIN_UP_BOX
+      code0 {extern Fl_Menu_Item labeltypemenu[];}
+      code1 {o->menu(labeltypemenu);}
+    } {}
+    Fl_Button {} {
+      label {@-1<-}
+      user_data FL_ALIGN_LEFT
+      callback align_cb
+      xywh {240 80 20 20} type Toggle box THIN_UP_BOX labeltype SYMBOL_LABEL labelcolor 8
+    }
+    Fl_Button {} {
+      label {@-1->}
+      user_data FL_ALIGN_RIGHT
+      callback align_cb
+      xywh {260 80 20 20} type Toggle box THIN_UP_BOX labeltype SYMBOL_LABEL labelcolor 8
+    }
+    Fl_Button {} {
+      label {@-18}
+      user_data FL_ALIGN_TOP
+      callback align_cb
+      xywh {280 80 20 20} type Toggle box THIN_UP_BOX labeltype SYMBOL_LABEL labelcolor 8
+    }
+    Fl_Button {} {
+      label {@-12}
+      user_data FL_ALIGN_BOTTOM
+      callback align_cb
+      xywh {300 80 20 20} type Toggle box THIN_UP_BOX labeltype SYMBOL_LABEL labelcolor 8
+    }
+    Fl_Button {} {
+      label {@-3square}
+      user_data FL_ALIGN_INSIDE
+      callback align_cb
+      xywh {320 80 20 20} type Toggle box THIN_UP_BOX labeltype SYMBOL_LABEL labelcolor 8
+    }
+    Fl_Button {} {
+      label wrap
+      user_data FL_ALIGN_WRAP
+      callback align_cb
+      xywh {340 80 20 10} type Toggle box THIN_UP_BOX labelsize 8
+    }
+    Fl_Button {} {
+      label clip
+      user_data FL_ALIGN_CLIP
+      callback align_cb
+      xywh {340 90 20 10} type Toggle box THIN_UP_BOX labelsize 8
+    }
+    Fl_Choice {} {
+      label {labelfont:}
+      callback labelfont_cb
+      xywh {90 100 170 20} box THIN_UP_BOX
+      code0 {extern Fl_Menu_Item fontmenu[];}
+      code1 {o->menu(fontmenu);}
+    } {}
+    Fl_Value_Input {} {
+      callback labelsize_cb
+      xywh {260 100 50 20} box THIN_UP_BOX maximum 100 step 1 value 14
+    }
+    Fl_Button {} {
+      label labelcolor
+      callback labelcolor_cb
+      xywh {310 100 50 20} box THIN_UP_BOX labelsize 8
+    }
+    Fl_Choice {} {
+      label {box:}
+      callback box_cb
+      xywh {90 125 220 20} box THIN_UP_BOX
+      code0 {extern Fl_Menu_Item boxmenu[];}
+      code1 {o->menu(boxmenu);}
+    } {}
+    Fl_Button {} {
+      label color
+      callback color_cb
+      xywh {310 125 50 20} box THIN_UP_BOX labelsize 8
+    }
+    Fl_Choice {} {
+      label {down_box:}
+      callback down_box_cb
+      xywh {90 145 220 20} box THIN_UP_BOX
+      code0 {extern Fl_Menu_Item boxmenu[];}
+      code1 {o->menu(boxmenu);}
+    } {}
+    Fl_Button {} {
+      label {select color}
+      callback color2_cb
+      xywh {310 145 50 20} box THIN_UP_BOX labelsize 8
+    }
+    Fl_Choice {} {
+      label {textfont:}
+      callback textfont_cb selected
+      xywh {90 170 170 20} box THIN_UP_BOX hide
+      code0 {extern Fl_Menu_Item fontmenu[];}
+      code1 {o->menu(fontmenu);}
+    } {}
+    Fl_Input {} {
+      label {xclass:}
+      callback xclass_cb
+      xywh {90 170 170 20} box THIN_UP_BOX when 0
+    }
+    Fl_Button {} {
+      label {shortcut:}
+      callback shortcut_in_cb
+      xywh {90 170 270 20} box THIN_UP_BOX color {7 7} align 4
+      code0 {\#include "Shortcut_Button.H"}
+      class Shortcut_Button
+    }
+    Fl_Value_Input {} {
+      callback textsize_cb
+      xywh {260 170 50 20} box THIN_UP_BOX maximum 100 step 1 value 14 hide
+    }
+    Fl_Button {} {
+      label textcolor
+      callback textcolor_cb
+      xywh {310 170 50 20} box THIN_UP_BOX labelsize 8 hide
+    }
+    Fl_Value_Input {} {
+      label {size:}
+      callback slider_size_cb
+      xywh {20 205 60 20} box THIN_UP_BOX labelsize 10 align 5 step 0.010101
+    }
+    Fl_Value_Input {} {
+      label {minimum:}
+      callback min_cb
+      xywh {90 205 60 20} box THIN_UP_BOX labelsize 10 align 5
+    }
+    Fl_Value_Input {} {
+      label {maximum:}
+      callback max_cb
+      xywh {160 205 60 20} box THIN_UP_BOX labelsize 10 align 5 value 1
+    }
+    Fl_Value_Input {} {
+      label {step:}
+      callback step_cb
+      xywh {230 205 60 20} box THIN_UP_BOX labelsize 10 align 5
+    }
+    Fl_Value_Input {} {
+      label {value:}
+      callback value_cb
+      xywh {300 205 60 20} box THIN_UP_BOX labelsize 10 align 5
+    }
+    Fl_Group {} {
+      callback propagate_load open
+      xywh {20 230 340 20} align 5
+    } {
+      Fl_Light_Button {} {
+        label non_modal
+        callback non_modal_cb
+        xywh {20 230 70 20} box THIN_UP_BOX color {49 1} labelsize 9 align 148
+      }
+      Fl_Light_Button {} {
+        label visible
+        callback visible_cb
+        xywh {90 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10
+      }
+      Fl_Light_Button {} {
+        label modal
+        callback modal_cb
+        xywh {90 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10
+      }
+      Fl_Light_Button {} {
+        label active
+        callback active_cb
+        xywh {160 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10
+      }
+      Fl_Light_Button {} {
+        label border
+        callback border_cb
+        xywh {160 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10
+      }
+      Fl_Light_Button {} {
+        label resizable
+        callback resizable_cb
+        xywh {230 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10 when 1
+      }
+      Fl_Light_Button {} {
+        label hotspot
+        callback hotspot_cb
+        xywh {300 230 60 20} box THIN_UP_BOX color {49 1} labelsize 10 when 1
+      }
+    }
+    Fl_Input {v_input[0]} {
+      label {extra code:}
+      user_data 0
+      callback v_input_cb
+      xywh {90 260 270 20} box THIN_UP_BOX when 0
+    }
+    Fl_Input {v_input[1]} {
+      user_data 1
+      callback v_input_cb
+      xywh {90 280 270 20} box THIN_UP_BOX when 0
+    }
+    Fl_Input {v_input[2]} {
+      user_data 2
+      callback v_input_cb
+      xywh {90 300 270 20} box THIN_UP_BOX when 0
+    }
+    Fl_Input {v_input[3]} {
+      user_data 3
+      callback v_input_cb
+      xywh {90 320 270 20} box THIN_UP_BOX when 0
+    }
+    Fl_Box {} {
+      label {callback:}
+      xywh {0 350 90 20} align 24
+    }
+    Fl_Input {} {
+      callback callback_cb
+      xywh {90 350 270 50} type Multiline box THIN_UP_BOX when 0
+    }
+    Fl_Box {} {
+      label label
+      xywh {90 370 100 30} hide deactivate resizable
+    }
+    Fl_Input {} {
+      label {user_data:}
+      callback user_data_cb
+      xywh {90 400 170 20} box THIN_UP_BOX when 0
+    }
+    Fl_Input {} {
+      label {type:}
+      callback user_data_type_cb
+      xywh {300 400 60 20} box THIN_UP_BOX when 0
+    }
+    Fl_Choice {} {
+      label {when:}
+      callback when_cb
+      xywh {90 420 100 20} box THIN_UP_BOX when 0
+      code0 {extern Fl_Menu_Item whenmenu[];}
+      code1 {o->menu(whenmenu);}
+    } {}
+    Fl_Light_Button {} {
+      label {no change}
+      callback when_button_cb
+      xywh {190 420 70 20} box THIN_UP_BOX color {49 1} labelsize 10 when 0
+    }
+    Fl_Group {} {open
+      xywh {10 450 350 20}
+    } {
+      Fl_Button {} {
+        label {no &overlay}
+        callback overlay_cb
+        xywh {10 450 80 20} labelcolor 1
+      }
+      Fl_Button {} {
+        label Revert
+        callback revert_cb
+        xywh {100 450 80 20}
+      }
+      Fl_Button {} {
+        label Cancel
+        callback cancel_cb
+        xywh {190 450 80 20}
+      }
+      Fl_Return_Button {} {
+        label OK
+        callback ok_cb
+        xywh {280 450 80 20}
+      }
+    }
+  }
+} 
diff --git a/fluid/widget_panel.h b/fluid/widget_panel.h
new file mode 100644
index 000000000..9e304d16a
--- /dev/null
+++ b/fluid/widget_panel.h
@@ -0,0 +1,61 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "Shortcut_Button.H"
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+extern Fl_Menu_Item boxmenu[];
+extern Fl_Menu_Item fontmenu[];
+extern Fl_Menu_Item labeltypemenu[];
+extern Fl_Menu_Item whenmenu[];
+extern void active_cb(Fl_Light_Button*, void*);
+extern void align_cb(Fl_Button*, void*);
+extern void border_cb(Fl_Light_Button*, void*);
+extern void box_cb(Fl_Choice*, void*);
+extern void callback_cb(Fl_Input*, void*);
+extern void cancel_cb(Fl_Button*, void*);
+extern void color2_cb(Fl_Button*, void*);
+extern void color_cb(Fl_Button*, void*);
+extern void down_box_cb(Fl_Choice*, void*);
+extern void hotspot_cb(Fl_Light_Button*, void*);
+extern void label_cb(Fl_Input*, void*);
+extern void labelcolor_cb(Fl_Button*, void*);
+extern void labelfont_cb(Fl_Choice*, void*);
+extern void labelsize_cb(Fl_Value_Input*, void*);
+extern void labeltype_cb(Fl_Choice*, void*);
+extern void max_cb(Fl_Value_Input*, void*);
+extern void min_cb(Fl_Value_Input*, void*);
+extern void modal_cb(Fl_Light_Button*, void*);
+extern void name_cb(Fl_Input*, void*);
+extern void name_public_cb(Fl_Light_Button*, void*);
+extern void non_modal_cb(Fl_Light_Button*, void*);
+extern void ok_cb(Fl_Return_Button*, void*);
+extern void overlay_cb(Fl_Button*, void*);
+extern void propagate_load(Fl_Group*, void*);
+extern void resizable_cb(Fl_Light_Button*, void*);
+extern void revert_cb(Fl_Button*, void*);
+extern void shortcut_in_cb(Shortcut_Button*, void*);
+extern void slider_size_cb(Fl_Value_Input*, void*);
+extern void step_cb(Fl_Value_Input*, void*);
+extern void subclass_cb(Fl_Input*, void*);
+extern void subtype_cb(Fl_Choice*, void*);
+extern void textcolor_cb(Fl_Button*, void*);
+extern void textfont_cb(Fl_Choice*, void*);
+extern void textsize_cb(Fl_Value_Input*, void*);
+extern void user_data_cb(Fl_Input*, void*);
+extern void user_data_type_cb(Fl_Input*, void*);
+extern void v_input_cb(Fl_Input*, void*);
+extern void value_cb(Fl_Value_Input*, void*);
+extern void visible_cb(Fl_Light_Button*, void*);
+extern void when_button_cb(Fl_Light_Button*, void*);
+extern void when_cb(Fl_Choice*, void*);
+extern void xclass_cb(Fl_Input*, void*);
+extern Fl_Input *v_input[4];
+Fl_Window* make_widget_panel();
diff --git a/forms.h b/forms.h
new file mode 100644
index 000000000..967b24b67
--- /dev/null
+++ b/forms.h
@@ -0,0 +1,3 @@
+// this file allows some forms programs to be compiled with no change.
+// put it in your include path.
+#include 
diff --git a/install-sh b/install-sh
new file mode 100644
index 000000000..89fc9b098
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	true
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+	else
+		instcmd=mkdir
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f $src -o -d $src ]
+	then
+		true
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		true
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		true
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='	
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		true
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		true
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/lib/... b/lib/...
new file mode 100644
index 000000000..e69de29bb
diff --git a/makedist b/makedist
new file mode 100755
index 000000000..480aa01a3
--- /dev/null
+++ b/makedist
@@ -0,0 +1,26 @@
+#!/bin/tcsh
+# I use tcsh to get the better glob matching.  Wish there were a more
+# portable way...
+# argument to this script is the version number or word like "BETA"
+
+if ( $1 == "" ) then
+echo "Version number needed"
+exit 1
+endif
+
+set f="fltk-$1"
+rm -f $f
+ln -s . $f
+
+echo "Making $f.tgz"
+tar -cf \
+	$f.tar $f/README $f/COPYING $f/version $f/Makefile \
+	$f/configure $f/*.in $f/makefiles/* $f/makedist $f/install-sh \
+	$f/{src,fluid,FL,test,GL}/{README,Makefile,*.{fl,[CHch],x?m,menu}} \
+	$f/documentation/*.{html,gif,jpg} $f/documentation/CHANGES \
+	$f/forms.h $f/win32/* $f/lib/... \
+
+gzip -f $f.tar
+mv $f.tar.gz $f.tgz
+
+rm -f $f
diff --git a/makefiles/aixmakesharedlib b/makefiles/aixmakesharedlib
new file mode 100755
index 000000000..8fd62a8d7
--- /dev/null
+++ b/makefiles/aixmakesharedlib
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# aixmakesharedlib - a simple script for AIX shared lib creation from a
+#                    non shared library
+#
+# Notes:
+#   - Should work for both AIX 3.2.x & 4.1.x
+#   - Copies original (non shared) lib to be lib.NS
+#   - May require slight modifications for different uses (this was written
+#     with the FL library in mind)
+#
+
+/bin/rm -f shr.o syms.exp
+
+# create the exports list:
+echo "#!" > syms.exp
+dump -g $1 | egrep -e '[ \t]*[0-9]+' | sed 's/^[ \t]*[0-9][0-9]*[ \t]*[^ \t]//' | sed 's/^\.//' | sort | uniq >> syms.exp
+
+xlC -o shr.o $1 -bM:SRE -bE:syms.exp -bnoentry -lc -lm -lX11
+
+mv $1 $1.NS
+
+ar ruv $1 shr.o syms.exp
+/bin/rm -f shr.o syms.exp
diff --git a/makefiles/makeinclude.cygnus b/makefiles/makeinclude.cygnus
new file mode 100644
index 000000000..239e87661
--- /dev/null
+++ b/makefiles/makeinclude.cygnus
@@ -0,0 +1,43 @@
+# !!!! YOU PROBABLY WANT TO USE makeinclude.mingw32 INSTEAD !!!!
+
+# Makeinclude file for the Cygwin B19 release of GCC for Windoze
+#
+# This will try to use Cygwin's Unix emulation as much as possible,
+# which means it will link in Cygwin's libraries.  This seems to
+# result in much slower performance, and the only real difference
+# is that the file chooser uses cygwin's scandir implementation
+# rather than my own.  To compile with direct windoze calls
+# use the file makeinclude.mingw32.
+
+# Copy this file to .. and run make.
+# Thanks to Philipp Knirsch at Lucent and Carl Thompson
+
+prefix          =/usr/local
+exec_prefix     =${prefix}
+bindir          =${exec_prefix}/bin
+includedir      =${prefix}/include
+libdir          =${exec_prefix}/lib
+srcdir          =.
+
+# compiler names:
+CXX     =g++
+CC      =gcc
+
+# flags for C++ compiler:
+CFLAGS          =-Wall -O2 -DCYGNUS
+CXXFLAGS        =-Wall -O2 -DCYGNUS
+CXXFLAGS_D      =-Wall -g -DDEBUG -DCYGNUS
+
+# program to make the archive:
+LIBNAME         =libfltk.a
+LIBNAME_D       =libfltk_d.a
+AR              =ar -ruv
+RANLIB          =ranlib
+
+# libraries to link with:
+LDLIBS  =-lgdi32 -luser32 -lm
+
+# libraries to link with when using GL:
+GLDLIBS =-lgdi32 -luser32 -lglu32 -lopengl32 -lm
+
+INSTALL =/CYGNUS/B19/H-I386~1/BIN/install -c
diff --git a/makefiles/makeinclude.mingw32 b/makefiles/makeinclude.mingw32
new file mode 100644
index 000000000..3390f113a
--- /dev/null
+++ b/makefiles/makeinclude.mingw32
@@ -0,0 +1,36 @@
+# Makeinclude file for the Cygwin B19 release of GCC for Windoze
+
+# This will compile the code to directly call Windows interfaces
+# and does not use the CYGWIN library.
+
+# Thanks to Philipp Knirsch at Lucent and Carl Thompson
+
+prefix          =/usr/local
+exec_prefix     =${prefix}
+bindir          =${exec_prefix}/bin
+includedir      =${prefix}/include
+libdir          =${exec_prefix}/lib
+srcdir          =.
+
+# compiler names:
+CXX     =g++
+CC      =g++
+
+# flags for C++ compiler:
+CFLAGS          =-Wall -O2 -DWIN32
+CXXFLAGS        =-Wall -O2 -DWIN32
+CXXFLAGS_D      =-Wall -g -DDEBUG -DWIN32
+
+# program to make the archive:
+LIBNAME         =libfltk.a
+LIBNAME_D       =libfltk_d.a
+AR              =ar -ruv
+RANLIB          =ranlib
+
+# libraries to link with:
+LDLIBS  =-lgdi32 -luser32 -lm -mwindows
+
+# libraries to link with when using GL:
+GLDLIBS =-lgdi32 -luser32 -lglu32 -lopengl32 -lm -mwindows
+
+INSTALL =/CYGNUS/B19/H-I386~1/BIN/install -c
diff --git a/makeinclude.in b/makeinclude.in
new file mode 100644
index 000000000..1791e680f
--- /dev/null
+++ b/makeinclude.in
@@ -0,0 +1,32 @@
+# @configure_input@
+
+prefix		=@prefix@
+exec_prefix	=@exec_prefix@
+bindir		=@bindir@
+includedir	=@includedir@
+libdir		=@libdir@
+srcdir		=@srcdir@
+VPATH		=@srcdir@
+
+# compiler names:
+CXX	=@CXX@
+CC	=@CC@
+MAKEDEPEND =@MAKEDEPEND@
+
+# flags for C++ compiler:
+CFLAGS		=@CFLAGS@
+CFLAGS_D	=@CFLAGS_D@
+CXXFLAGS	=@CXXFLAGS@ @X_CFLAGS@
+CXXFLAGS_D	=@CXXFLAGS_D@ @X_CFLAGS@
+
+# program to make the archive:
+LIBNAME		=libfltk.a
+LIBNAME_D	=libfltk_d.a
+AR		=ar rc
+RANLIB		=@RANLIB@
+
+# libraries to link with:
+LDLIBS	=@LIBS@ -lX11 -lXext @X_EXTRA_LIBS@ -lm
+
+# libraries to link with when using GL:
+GLDLIBS	=@LIBS@ @GLLIB@ -lX11 -lXext @X_EXTRA_LIBS@ -lm
diff --git a/src/Fl.cxx b/src/Fl.cxx
new file mode 100644
index 000000000..06a0c62b1
--- /dev/null
+++ b/src/Fl.cxx
@@ -0,0 +1,566 @@
+// Fl.C
+
+// fltk (Fast Light Tool Kit) version 0.99
+// Copyright (C) 1998 Bill Spitzak
+
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library 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
+// Library General Public License for more details.
+
+// You should have received a copy of the GNU Library 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.
+
+// Written by Bill Spitzak spitzak@d2.com
+
+#include 
+#include 
+#include 
+#include 
+
+int Fl::damage_;
+Fl_Widget *Fl::belowmouse_;
+Fl_Widget *Fl::pushed_;
+Fl_Widget *Fl::focus_;
+Fl_Widget *Fl::selection_owner_;
+int Fl::e_x, Fl::e_y, Fl::e_x_root, Fl::e_y_root;
+int Fl::e_state;
+int Fl::e_clicks;
+int Fl::e_is_click;
+int Fl::e_keysym;
+char *Fl::e_text;
+int Fl::e_length;
+
+int Fl::event_inside(int x,int y,int w,int h) /*const*/ {
+  int mx = event_x();
+  int my = event_y();
+  return (mx >= x && mx < x+w && my >= y && my < y+h);
+}
+
+int Fl::event_inside(const Fl_Widget *o) /*const*/ {
+  return event_inside(o->x(),o->y(),o->w(),o->h());
+}
+
+// Timeouts are insert-sorted into order.  This works good if there
+// are only a small number:
+
+#define MAXTIMEOUT 8
+
+static struct {
+  double time;
+  void (*cb)(void*);
+  void* arg;
+} timeout[MAXTIMEOUT+1];
+static int numtimeouts;
+
+void Fl::add_timeout(double t, void (*cb)(void *), void *v) {
+  int i;
+  if (numtimeouts t) {
+      for (int j=numtimeouts-1; j>i; j--) timeout[j] = timeout[j-1];
+      break;
+    }
+  }
+  timeout[i].time = t;
+  timeout[i].cb = cb;
+  timeout[i].arg = v;
+}
+
+void Fl::remove_timeout(void (*cb)(void *), void *v) {
+  int i,j;
+  for (i=j=0; i 0) return;
+  struct {
+    void (*cb)(void *);
+    void *arg;
+  } temp[MAXTIMEOUT];
+  int i,j,k;
+  // copy all expired timeouts to temp array:
+  for (i=j=0; jnext) {
+      if (x->w->damage() && x->w->visible()) {
+	x->flush();
+	x->w->clear_damage();
+      }
+    }
+  }
+#ifndef WIN32
+  if (fl_display) XFlush(fl_display);
+#endif
+}
+
+extern double fl_wait(int timeout_flag, double timeout);
+extern int fl_ready();
+
+static int initclock; // if false we didn't call fl_elapsed() last time
+
+#ifndef WIN32
+#include 
+#endif
+
+// fl_elapsed must return the amount of time since the last time it was
+// called.  To reduce the number of system calls the to get the
+// current time, the "initclock" symbol is turned on by an indefinate
+// wait.  This should then reset the measured-from time and return zero
+static double fl_elapsed() {
+
+#ifdef WIN32
+
+  unsigned long newclock = fl_msg.time; // NOT YET IMPLEMENTED!
+  const int TICKS_PER_SECOND = 1000; // divisor of the value to get seconds
+  static unsigned long prevclock;
+  if (!initclock) {prevclock = newclock; initclock = 1; return 0.0;}
+  double t = double(newclock-prevclock)/TICKS_PER_SECOND;
+  prevclock = newclock;
+
+#else
+
+  static struct timeval prevclock;
+  struct timeval newclock;
+  gettimeofday(&newclock, 0);
+  if (!initclock) {
+    prevclock.tv_sec = newclock.tv_sec;
+    prevclock.tv_usec = newclock.tv_usec;
+    initclock = 1;
+    return 0.0;
+  }
+  double t = newclock.tv_sec - prevclock.tv_sec +
+    (newclock.tv_usec - prevclock.tv_usec)/1000000.0;
+  prevclock.tv_sec = newclock.tv_sec;
+  prevclock.tv_usec = newclock.tv_usec;
+
+#endif
+
+  // expire any timeouts:
+  if (t > 0.0) for (int i=0; inext)
+    if (window->xid == xid) {
+      if (window != Fl_X::first && !Fl::modal()) {
+	// make this window be first to speed up searches
+	// this is not done if modal is true to avoid messing up modal stack
+	*pp = window->next;
+	window->next = Fl_X::first;
+	Fl_X::first = window;
+      }
+      return window->w;
+    }
+  return 0;
+}
+
+void Fl::redraw() {
+  for (Fl_X* x = Fl_X::first; x; x = x->next) x->w->redraw();
+}
+
+Fl_Window* Fl::first_window() {Fl_X* x = Fl_X::first; return x ? x->w : 0;}
+
+Fl_Window* Fl::next_window(const Fl_Window* w) {
+  Fl_X* x = Fl_X::i(w)->next; return x ? x->w : 0;}
+
+////////////////////////////////////////////////////////////////
+// Event handlers:
+
+struct handler_link {
+  int (*handle)(int);
+  const handler_link *next;
+};
+
+static const handler_link *handlers = 0;
+
+void Fl::add_handler(int (*h)(int)) {
+  handler_link *l = new handler_link;
+  l->handle = h;
+  l->next = handlers;
+  handlers = l;
+}
+
+static int send_handlers(int event) {
+  for (const handler_link *h = handlers; h; h = h->next)
+    if (h->handle(event)) return 1;
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////
+
+Fl_Widget* fl_oldfocus; // kludge for Fl_Group...
+
+void Fl::focus(Fl_Widget *o) {
+  Fl_Widget *p = focus_;
+  if (o != p) {
+    focus_ = o;
+    fl_oldfocus = 0;
+    for (; p && !p->contains(o); p = p->parent()) {
+      p->handle(FL_UNFOCUS);
+      fl_oldfocus = p;
+    }
+  }
+}
+
+void Fl::belowmouse(Fl_Widget *o) {
+  Fl_Widget *p = belowmouse_;
+  if (o != p) {
+    event_is_click(0);
+    belowmouse_ = o;
+    for (; p && !p->contains(o); p = p->parent()) p->handle(FL_LEAVE);
+  }
+}
+
+// Because mouse events are posted to the outermost window we need to
+// adjust them for child windows if they are pushed().  This should also
+// be done for the focus() but that is nyi.
+static int mouse_dx;
+static int mouse_dy;
+
+void Fl::pushed(Fl_Widget *o) {
+  pushed_ = o;
+  mouse_dx = 0;
+  mouse_dy = 0;
+  if (o) for (Fl_Widget* w = o; w->parent(); w = w->parent()) {
+    if (w->type()>=FL_WINDOW) {mouse_dx -= w->x(); mouse_dy -= w->y();}
+  }
+}
+
+Fl_Window *fl_xfocus;	// which window X thinks has focus
+Fl_Window *fl_xmousewin; // which window X thinks has FL_ENTER
+Fl_Window *Fl::grab_;	// most recent Fl::grab()
+Fl_Window *Fl::modal_;
+
+// Update modal(), focus() and other state according to system state.
+// This is called whenever a window is added or hidden, and whenever
+// X says the focus or mouse window have changed, and when grab_ is
+// changed.
+void fl_fix_focus() {
+
+  // set Fl::modal() based on grab or any modal windows displayed:
+  if (Fl::grab_)
+    Fl::modal_ = Fl::grab_;
+  else {
+    Fl_Window* w = Fl::first_window();
+    while (w && w->parent()) w = Fl::next_window(w);
+    Fl::modal_ = w && w->modal() ? w : 0;
+  }
+
+  // set focus based on Fl::modal() and fl_xfocus
+  Fl_Window *w = fl_xfocus;
+  while (w && w->parent()) w = w->window();
+  if (w) {
+    if (Fl::modal()) w = Fl::modal();
+    if (!w->contains(Fl::focus()))
+      if (!w->take_focus()) Fl::focus(w);
+  } else
+    Fl::focus(0);
+
+  if (Fl::pushed()) {
+
+    // move pushed() to modal window (necessary for menus):
+    if (Fl::modal() && !Fl::modal()->contains(Fl::pushed()))
+      Fl::pushed_ = Fl::modal();
+
+  } else {    // set belowmouse only when pushed() is false
+
+    // set belowmouse based on Fl::modal() and fl_xmousewin:
+    w = fl_xmousewin;
+    if (w) {
+      if (Fl::modal()) w = Fl::modal();
+      if (!w->contains(Fl::belowmouse())) {
+	Fl::belowmouse(w); w->handle(FL_ENTER);}
+    } else
+      Fl::belowmouse(0);
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+int Fl::handle(int event, Fl_Window* window)
+{
+  Fl_Widget* w = window;
+
+  switch (event) {
+
+  case FL_CLOSE:
+    if (modal() && window != modal()) return 0;
+    w->do_callback();
+    return 1;
+
+  case FL_SHOW:
+    ((Fl_Widget*)w)->show();
+    return 1;
+
+  case FL_HIDE:
+    ((Fl_Widget*)w)->hide();
+    return 1;
+
+  case FL_PUSH:
+    if (Fl::grab()) w = Fl::grab();
+    else if (Fl::modal() && w != Fl::modal()) return 0;
+    Fl::pushed_ = w; mouse_dx = mouse_dy = 0;
+    if (w->handle(event)) return 1;
+    // raise windows that are clicked on:
+    window->show();
+    return 1;
+
+  case FL_MOVE:
+  case FL_DRAG:
+    if (window != fl_xmousewin) {
+      // this should not happen if enter/leave events were reported
+      // correctly by the system, but just in case...
+      fl_xmousewin = window; fl_fix_focus();
+    }
+    if (Fl::pushed()) {
+      Fl::e_x += mouse_dx;
+      Fl::e_y += mouse_dy;
+      event = FL_DRAG;
+      w = Fl::pushed();
+    } else if (Fl::grab())
+      w = Fl::grab();
+    else if (Fl::modal() && w != Fl::modal())
+      w = 0;
+    break;
+
+  case FL_RELEASE: {
+    if (Fl::pushed_) w = Fl::pushed_; Fl::pushed_ = 0;
+    int r = w->handle(event);
+    fl_fix_focus();
+    if (fl_xmousewin) fl_xmousewin->handle(FL_MOVE);
+    return r;}
+
+  case FL_UNFOCUS:
+    window = 0;
+  case FL_FOCUS:
+    fl_xfocus = window;
+    Fl::e_keysym = 0; // make sure it is not confused with navigation key
+    fl_fix_focus();
+    return 1;
+
+  case FL_KEYBOARD:
+    if (window != fl_xfocus) {
+      // this should not happen if enter/leave events were reported
+      // correctly by the system, but just in case...
+      fl_xfocus = window; fl_fix_focus();
+    }
+    // Try it as keystroke, sending it to focus and all parents:
+    for (w = Fl::focus(); w; w = w->parent())
+      if (w->handle(FL_KEYBOARD)) return 1;
+
+    // Try it as shortcut, sending to mouse widget and all parents:
+    w = Fl::belowmouse(); if (!w) {w = Fl::modal(); if (!w) w = window;}
+    for (; w; w = w->parent()) if (w->handle(FL_SHORTCUT)) return 1;
+
+    // try using add_handle() functions:
+    if (send_handlers(FL_SHORTCUT)) return 1;
+
+    // Try swapping the case of the text in the shortcut:
+    if (isalpha(Fl::event_text()[0])) {
+      *(char*)(Fl::event_text()) ^= ('A'^'a');
+      w = Fl::belowmouse(); if (!w) {w = Fl::modal(); if (!w) w = window;}
+      for (; w; w = w->parent()) if (w->handle(FL_SHORTCUT)) return 1;
+      if (send_handlers(FL_SHORTCUT)) return 1;
+    }
+
+    // make Escape key close windows:
+    if (Fl::event_key()==FL_Escape) {
+      window->do_callback();
+      return 1;
+    }
+
+    return 0;
+
+  case FL_ENTER:
+    fl_xmousewin = window; fl_fix_focus();
+    return 1;
+
+  case FL_LEAVE:
+    if (window == fl_xmousewin) {fl_xmousewin = 0; fl_fix_focus();}
+    return 1;
+
+  default:
+    break;
+  }
+  if (w && w->handle(event)) return 1;
+  return send_handlers(event);
+}
+
+////////////////////////////////////////////////////////////////
+// hide() destroys the X window, it does not do unmap!
+
+void fl_throw_focus(Fl_Widget*); // in Fl_x.C
+
+void Fl_Window::hide() {
+  if (!shown()) return;
+
+  // remove from the list of windows:
+  Fl_X* x = i;
+  Fl_X** pp = &Fl_X::first;
+  for (; *pp != x; pp = &(*pp)->next) if (!*pp) return;
+  *pp = x->next;
+  i = 0;
+
+  // recursively remove any subwindows:
+  for (Fl_X *w = Fl_X::first; w;) {
+    Fl_Window* W = w->w;
+    if (W->window() == this) {
+      W->hide();
+      W->set_visible();
+      w = Fl_X::first;
+    } else w = w->next;
+  }
+
+  // Make sure no events are sent to this window:
+  if (this == fl_xmousewin) fl_xmousewin = 0;
+  if (this == fl_xfocus) fl_xfocus = 0;
+  fl_throw_focus(this);
+  handle(FL_HIDE);
+
+#ifdef WIN32
+  if (x->private_dc) ReleaseDC(x->xid,x->private_dc);
+  if (x->xid == fl_window) fl_GetDC(0); // releases dc belonging to window
+#else
+  if (x->region) XDestroyRegion(x->region);
+#endif
+  XDestroyWindow(fl_display, x->xid);
+
+  delete x;
+}
+
+Fl_Window::~Fl_Window() {
+  hide();
+}
+
+// Child windows must respond to FL_SHOW and FL_HIDE by actually
+// doing unmap operations.  Outer windows assumme FL_SHOW & FL_HIDE
+// are messages from X:
+
+int Fl_Window::handle(int event) {
+  if (parent()) switch (event) {
+  case FL_SHOW:
+    if (!shown()) show();
+    else XMapWindow(fl_display, fl_xid(this));
+    break;
+  case FL_HIDE:
+    if (shown()) XUnmapWindow(fl_display, fl_xid(this));
+    break;
+  }
+  return Fl_Group::handle(event);
+}
+
+////////////////////////////////////////////////////////////////
+// ~Fl_Widget() calls this: this function must get rid of any
+// global pointers to the widget.  This is also called by hide()
+// and deactivate().
+
+// call this to free a selection (or change the owner):
+void Fl::selection_owner(Fl_Widget *owner) {
+  if (selection_owner_ && owner != selection_owner_)
+    selection_owner_->handle(FL_SELECTIONCLEAR);
+  selection_owner_ = owner;
+}
+
+#ifndef WIN32
+Fl_Widget *fl_selection_requestor; // from Fl_cutpaste.C
+#endif
+
+void fl_throw_focus(Fl_Widget *o) {
+  if (o->contains(Fl::pushed())) Fl::pushed(0);
+  if (o->contains(Fl::selection_owner())) Fl::selection_owner(0);
+#ifndef WIN32
+  if (o->contains(fl_selection_requestor)) fl_selection_requestor = 0;
+#endif
+  int fix = 0;
+  if (o->contains(Fl::belowmouse())) {Fl::belowmouse(0); fix = 1;}
+  if (o->contains(Fl::focus())) {Fl::focus(0); fix = 1;}
+  if (fix) fl_fix_focus();
+}
+
+// End of Fl.C //
diff --git a/src/Fl_Adjuster.cxx b/src/Fl_Adjuster.cxx
new file mode 100644
index 000000000..a9b39d7bf
--- /dev/null
+++ b/src/Fl_Adjuster.cxx
@@ -0,0 +1,105 @@
+// Fl_Adjuster.C
+
+// Fltk widget for drag-adjusting a floating point value.
+
+#include 
+#include 
+#include 
+#include 
+
+#include "fastarrow.h"
+static Fl_Bitmap fastarrow(fastarrow_bits, fastarrow_width, fastarrow_height);
+#include "mediumarrow.h"
+static Fl_Bitmap mediumarrow(mediumarrow_bits, mediumarrow_width, mediumarrow_height);
+#include "slowarrow.h"
+static Fl_Bitmap slowarrow(slowarrow_bits, slowarrow_width, slowarrow_height);
+
+// changing the value does not change the appearance:
+void Fl_Adjuster::value_damage() {}
+
+void Fl_Adjuster::draw() {
+  int dx, dy, W, H;
+  if (w()>=h()) {
+    dx = W = w()/3;
+    dy = 0; H = h();
+  } else {
+    dx = 0; W = w();
+    dy = H = h()/3;
+  }
+  draw_box(drag==1?FL_DOWN_BOX:box(), x(),  y()+2*dy, W, H, color());
+  draw_box(drag==2?FL_DOWN_BOX:box(), x()+dx, y()+dy, W, H, color());
+  draw_box(drag==3?FL_DOWN_BOX:box(), x()+2*dx,  y(), W, H, color());
+  fl_color(selection_color());
+  fastarrow.draw(x()+(W-fastarrow_width)/2,
+		 y()+2*dy+(H-fastarrow_height)/2, W, H);
+  mediumarrow.draw(x()+dx+(W-mediumarrow_width)/2,
+		   y()+dy+(H-mediumarrow_height)/2, W, H);
+  slowarrow.draw(x()+2*dx+(W-slowarrow_width)/2,
+		 y()+(H-slowarrow_width)/2, W, H);
+}
+
+int Fl_Adjuster::handle(int event) {
+  double v;
+  int delta;
+  int mx = Fl::event_x();
+  switch (event) {
+  case FL_PUSH:
+    ix = mx;
+    if (w()>=h())
+      drag = 3*(mx-x())/w() + 1;
+    else
+      drag = 3-3*(Fl::event_y()-y()-1)/h();
+    handle_push();
+    redraw();
+    return 1;
+  case FL_DRAG:
+    if (w() >= h()) {
+      delta = x()+(drag-1)*w()/3;	// left edge of button
+      if (mx < delta)
+	delta = mx-delta;
+      else if (mx > delta+w()/3) // right edge of button
+	delta = mx-delta-w()/3;
+      else
+	delta = 0;
+    } else {
+      if (mx < x())
+	delta = mx-x();
+      else if (mx > x()+w())
+	delta = mx-x()-w();
+      else
+	delta = 0;
+    }
+    switch (drag) {
+    case 3: v = increment(previous_value(), delta); break;
+    case 2: v = increment(previous_value(), delta*10); break;
+    default:v = increment(previous_value(), delta*100); break;
+    }
+    handle_drag(soft() ? softclamp(v) : clamp(v));
+    return 1;
+  case FL_RELEASE:
+    if (Fl::event_is_click()) { // detect click but no drag
+      if (Fl::event_state()&0xF0000) delta = -10;
+      else delta = 10;
+      switch (drag) {
+      case 3: v = increment(previous_value(), delta); break;
+      case 2: v = increment(previous_value(), delta*10); break;
+      default:v = increment(previous_value(), delta*100); break;
+      }
+      handle_drag(soft() ? softclamp(v) : clamp(v));
+    }
+    drag = 0;
+    redraw();
+    handle_release();
+    return 1;
+  }
+  return 0;
+}
+
+Fl_Adjuster::Fl_Adjuster(int x, int y, int w, int h, const char* l)
+  : Fl_Valuator(x, y, w, h, l) {
+  box(FL_UP_BOX);
+  step(1, 10000);
+  selection_color(FL_BLACK);
+  drag = 0;
+  soft_ = 1;
+}
diff --git a/src/Fl_Bitmap.cxx b/src/Fl_Bitmap.cxx
new file mode 100644
index 000000000..b0bb53ab8
--- /dev/null
+++ b/src/Fl_Bitmap.cxx
@@ -0,0 +1,109 @@
+/*	Fl_Bitmap.C
+
+	Draw a bitmap in a box.
+
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+void Fl_Bitmap::draw(int X, int Y, int W, int H, int cx,int cy) {
+  // clip the box down to the size of image, quit if empty:
+  if (cx < 0) {W += cx; X -= cx; cx = 0;}
+  if (cx+W > w) W = w-cx;
+  if (W <= 0) return;
+  if (cy < 0) {H += cy; Y -= cy; cy = 0;}
+  if (cy+H > h) H = h-cy;
+  if (H <= 0) return;
+#ifdef WIN32
+  if (!id) {
+    // we need to pad the lines out to words & swap the bits
+    // in each byte.
+    int w1 = (w+7)/8;
+    int w2 = ((w+15)/16)*2;
+    uchar* newarray = new uchar[w2*h];
+    const uchar* src = array;
+    uchar* dest = newarray;
+    for (int y=0; y < h; y++) {
+      for (int n = 0; n < w1; n++) {
+	*dest++ =
+	  ((*src&0x01) << 7) +
+	  ((*src&0x02) << 5) +
+	  ((*src&0x04) << 3) +
+	  ((*src&0x08) << 1) +
+	  ((*src&0x10) >> 1) +
+	  ((*src&0x20) >> 3) +
+	  ((*src&0x40) >> 5) +
+	  ((*src&0x80) >> 7);
+	src++;
+      }
+      dest += w2-w1;
+    }
+    id = (ulong)CreateBitmap(w, h, 1, 1, newarray);
+    array = newarray; // keep the pointer so I can free it later
+  }
+  HDC tempdc = CreateCompatibleDC(fl_gc);
+  SelectObject(tempdc, (HGDIOBJ)id);
+  SelectObject(fl_gc, fl_brush());
+  // secret bitblt code found in old MSWindows reference manual:
+  BitBlt(fl_gc, X, Y, W, H, tempdc, cx, cy, 0xE20746L);
+  DeleteDC(tempdc);
+#else
+  if (!id) id = XCreateBitmapFromData(fl_display, fl_window,
+				      (const char*)array, (w+7)&-8, h);
+  XSetStipple(fl_display, fl_gc, id);
+  int ox = X-cx; if (ox < 0) ox += w;
+  int oy = Y-cy; if (oy < 0) oy += h;
+  XSetTSOrigin(fl_display, fl_gc, ox, oy);
+  XSetFillStyle(fl_display, fl_gc, FillStippled);
+  XFillRectangle(fl_display, fl_window, fl_gc, X, Y, W, H);
+  XSetFillStyle(fl_display, fl_gc, FillSolid);
+#endif
+}
+
+Fl_Bitmap::~Fl_Bitmap() {
+#ifdef WIN32
+  if (id) {
+    DeleteObject((HGDIOBJ)id);
+    delete[] (uchar*)array;
+  }
+#else
+  if (id) fl_delete_offscreen((Fl_Offscreen)id);
+#endif
+}
+
+static void bitmap_labeltype(
+    const Fl_Label* o, int x, int y, int w, int h, Fl_Align a)
+{
+  Fl_Bitmap* b = (Fl_Bitmap*)(o->value);
+  int cx;
+  if (a & FL_ALIGN_LEFT) cx = 0;
+  else if (a & FL_ALIGN_RIGHT) cx = b->w-w;
+  else cx = (b->w-w)/2;
+  int cy;
+  if (a & FL_ALIGN_TOP) cy = 0;
+  else if (a & FL_ALIGN_BOTTOM) cy = b->h-h;
+  else cy = (b->h-h)/2;
+  fl_color((Fl_Color)o->color);
+  b->draw(x,y,w,h,cx,cy);
+}
+
+static void bitmap_measure(const Fl_Label* o, int& w, int& h) {
+  Fl_Bitmap* b = (Fl_Bitmap*)(o->value);
+  w = b->w;
+  h = b->h;
+}
+
+void Fl_Bitmap::label(Fl_Widget* o) {
+  Fl::set_labeltype(_FL_BITMAP_LABEL, bitmap_labeltype, bitmap_measure);
+  o->label(_FL_BITMAP_LABEL, (const char*)this);
+}
+
+void Fl_Bitmap::label(Fl_Menu_Item* o) {
+  Fl::set_labeltype(_FL_BITMAP_LABEL, bitmap_labeltype, bitmap_measure);
+  o->label(_FL_BITMAP_LABEL, (const char*)this);
+}
diff --git a/src/Fl_Box.cxx b/src/Fl_Box.cxx
new file mode 100644
index 000000000..48b968b39
--- /dev/null
+++ b/src/Fl_Box.cxx
@@ -0,0 +1,11 @@
+// Fl_Box.C
+
+// The box widget.  An almost non-functional subclass of Fl_Widget.
+
+#include 
+#include 
+
+void Fl_Box::draw() {
+  draw_box();
+  draw_label();
+}
diff --git a/src/Fl_Browser.cxx b/src/Fl_Browser.cxx
new file mode 100644
index 000000000..f58447386
--- /dev/null
+++ b/src/Fl_Browser.cxx
@@ -0,0 +1,421 @@
+// Fl_Browser.C
+
+// Forms-compatable browser.  Probably useful for other lists of
+// textual data.
+
+// I modified this from the original Forms data to use a linked list
+// so that the number of items in the browser and size of those items
+// is unlimited.  The only problem is that the old browser used an
+// index number to identify a line, and it is slow to convert from/to
+// a pointer.  I use a cache of the last match to try to speed this
+// up.
+
+// Also added the ability to "hide" a line.  This set's it's height to
+// zero, so the Fl_Browser_ cannot pick it.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include  // for default_font
+
+#define SELECTED 1
+#define NOTDISPLAYED 2
+
+struct FL_BLINE {	// data is in a linked list of these
+  FL_BLINE* prev;
+  FL_BLINE* next;
+  void* data;
+  short length;		// sizeof(txt)-1, may be longer than string
+  char flags;		// selected, displayed
+  char txt[1];		// start of allocated array
+};
+
+void* Fl_Browser::item_first() const {return first;}
+
+void* Fl_Browser::item_next(void* l) const {return ((FL_BLINE*)l)->next;}
+
+void* Fl_Browser::item_prev(void* l) const {return ((FL_BLINE*)l)->prev;}
+
+int Fl_Browser::item_selected(void* l) const {
+  return ((FL_BLINE*)l)->flags&SELECTED;}
+
+void Fl_Browser::item_select(void* l, int v) {
+  if (v) ((FL_BLINE*)l)->flags |= SELECTED;
+  else ((FL_BLINE*)l)->flags &= ~SELECTED;
+}
+
+FL_BLINE* Fl_Browser::find_line(int line) const {
+  int n; FL_BLINE* l;
+  if (line == cacheline) return cache;
+  if (cacheline && line > cacheline/2 && line < (cacheline+lines)/2) {
+    n = cacheline; l = cache;
+  } else if (line <= lines/2) {
+    n = 1; l = first;
+  } else {
+    n = lines; l = last;
+  }
+  for (; n < line && l; n++) l = l->next;
+  for (; n > line && l; n--) l = l->prev;
+  ((Fl_Browser*)this)->cacheline = line;
+  ((Fl_Browser*)this)->cache = l;
+  return l;
+}
+
+int Fl_Browser::lineno(void* v) const {
+  FL_BLINE* l = (FL_BLINE*)v;
+  if (!l) return 0;
+  if (l == cache) return cacheline;
+  if (l == first) return 1;
+  if (l == last) return lines;
+  if (!cache) {
+    ((Fl_Browser*)this)->cache = first;
+    ((Fl_Browser*)this)->cacheline = 1;
+  }
+  // assumme it is near cache, search both directions:
+  FL_BLINE* b = cache->prev;
+  int bnum = cacheline-1;
+  FL_BLINE* f = cache->next;
+  int fnum = cacheline+1;
+  int n = 0;
+  for (;;) {
+    if (b == l) {n = bnum; break;}
+    if (f == l) {n = fnum; break;}
+    if (b) {b = b->prev; bnum--;}
+    if (f) {f = f->next; fnum++;}
+  }
+  ((Fl_Browser*)this)->cache = l;
+  ((Fl_Browser*)this)->cacheline = n;
+  return n;
+}
+
+FL_BLINE* Fl_Browser::_remove(int line) {
+  FL_BLINE* ttt = find_line(line);
+  deleting(ttt);
+
+  cacheline = line-1;
+  cache = ttt->prev;
+  if (ttt->prev) ttt->prev->next = ttt->next;
+  else first = ttt->next;
+  if (ttt->next) ttt->next->prev = ttt->prev;
+  else last = ttt->prev;
+
+  lines--;
+  full_height_ -= item_height(ttt);
+  return(ttt);
+}
+
+void Fl_Browser::remove(int line) {
+  if (line < 1 || line > lines) return;
+  free(_remove(line));
+}
+
+void Fl_Browser::insert(int line, FL_BLINE* t) {
+  if (!first) {
+    t->prev = t->next = 0;
+    first = last = t;
+  } else if (line <= 1) {
+    inserting(first, t);
+    t->prev = 0;
+    t->next = first;
+    t->next->prev = t;
+    first = t;
+  } else if (line > lines) {
+    t->prev = last;
+    t->prev->next = t;
+    t->next = 0;
+    last = t;
+  } else {
+    FL_BLINE* n = find_line(line);
+    inserting(n, t);
+    t->next = n;
+    t->prev = n->prev;
+    t->prev->next = t;
+    n->prev = t;
+  }
+  cacheline = line;
+  cache = t;
+  lines++;
+  full_height_ += item_height(t);
+  redraw_line(t);
+}
+
+void Fl_Browser::insert(int line, const char* newtext, void* data) {
+  int l = strlen(newtext);
+  FL_BLINE* t = (FL_BLINE*)malloc(sizeof(FL_BLINE)+l);
+  t->length = l;
+  t->flags = 0;
+  strcpy(t->txt, newtext);
+  t->data = data;
+  insert(line, t);
+}
+
+void Fl_Browser::move(int to, int from) {
+  if (from < 1 || from > lines) return;
+  insert(to, _remove(from));
+}
+
+void Fl_Browser::text(int line, const char* newtext) {
+  if (line < 1 || line > lines) return;
+  FL_BLINE* t = find_line(line);
+  int l = strlen(newtext);
+  if (l > t->length) {
+    FL_BLINE* n = (FL_BLINE*)malloc(sizeof(FL_BLINE)+l);
+    replacing(t, n);
+    cache = n;
+    n->length = l;
+    n->flags = t->flags;
+    n->prev = t->prev;
+    if (n->prev) n->prev->next = n; else first = n;
+    n->next = t->next;
+    if (n->next) n->next->prev = n; else last = n;
+    free(t);
+    t = n;
+  }
+  strcpy(t->txt, newtext);
+  redraw_line(t);
+}
+
+void Fl_Browser::data(int line, void* data) {
+  if (line < 1 || line > lines) return;
+  find_line(line)->data = data;
+}
+
+int Fl_Browser::item_height(void* lv) const {
+  FL_BLINE* l = (FL_BLINE*)lv;
+  if (l->flags & NOTDISPLAYED) return 0;
+  char* str = l->txt;
+  int t = textsize()+2;
+  if (*str == format_char()) switch (*(str+1)) {
+  case 'l': case 'L': t = 26; break;
+  case 'm': case 'M': t = 20; break;
+  case 's': case 'S': t = 13; break;
+  }
+  return t + Fl_Input_::default_size();
+}
+
+int Fl_Browser::item_width(void* v) const {
+  char* str = ((FL_BLINE*)v)->txt;
+  const int* i = column_widths();
+  int w = 0;
+
+  while (*i) { // add up all tab-seperated fields
+    w += *i++;
+    char* e;
+    for (e = str; *e && *e != column_char(); e++);
+    if (!*e) return 0; // last one occupied by text
+    str = e+1;
+  }
+
+  // OK, we gotta parse the string and find the string width...
+  int size = textsize();
+  Fl_Font font = textfont();
+  int done = 0;
+
+  while (*str == format_char_ && *++str && *str != format_char_) {
+    switch (*str++) {
+    case 'l': case 'L': size = 24; break;
+    case 'm': case 'M': size = 18; break;
+    case 's': size = 11; break;
+    case 'b': font = (Fl_Font)(font|FL_BOLD); break;
+    case 'i': font = (Fl_Font)(font|FL_ITALIC); break;
+    case 'f': case 't': font = FL_COURIER; break;
+    case 'S':
+      size = strtol(str, &str, 10);
+      break;
+    case '.':
+      done = 1;
+    case '@':
+      str--;
+      done = 1;
+    }
+
+    if (done)
+      break;
+  }
+
+  fl_font(font, size, Fl_Input_::default_font(), Fl_Input_::default_size());
+  return w + int(fl_width(str)) + 6;
+}
+
+int Fl_Browser::full_height() const {
+  return full_height_;
+}
+
+int Fl_Browser::incr_height() const {
+  return textsize()+2;
+}
+
+void Fl_Browser::item_draw(void* v, int x, int y, int w, int h) const {
+  char* str = ((FL_BLINE*)v)->txt;
+  const int* i = column_widths();
+
+  while (w > 6) {	// do each tab-seperated field
+    int w1 = w;	// width for this field
+    char* e = 0; // pointer to end of field or null if none
+    if (*i) { // find end of field and temporarily replace with 0
+      for (e = str; *e && *e != column_char(); e++);
+      if (*e) {*e = 0; w1 = *i++;} else e = 0;
+    }
+    int size = textsize();
+    Fl_Font font = textfont();
+    Fl_Color lcol = textcolor();
+    Fl_Align align = FL_ALIGN_LEFT;
+    // check for all the @-lines recognized by XForms:
+    while (*str == format_char() && *++str && *str != format_char()) {
+      switch (*str++) {
+      case 'l': case 'L': size = 24; break;
+      case 'm': case 'M': size = 18; break;
+      case 's': size = 11; break;
+      case 'b': font = (Fl_Font)(font|FL_BOLD); break;
+      case 'i': font = (Fl_Font)(font|FL_ITALIC); break;
+      case 'f': case 't': font = FL_COURIER; break;
+      case 'c': align = FL_ALIGN_CENTER; break;
+      case 'r': align = FL_ALIGN_RIGHT; break;
+      case 'B': 
+	fl_color((Fl_Color)strtol(str, &str, 10));
+	fl_rectf(x, y, w1, h);
+        break;
+      case 'C':
+	lcol = (Fl_Color)strtol(str, &str, 10);
+	break;
+      case 'F':
+	font = (Fl_Font)strtol(str, &str, 10);
+	break;
+      case 'N':
+	lcol = FL_INACTIVE_COLOR;
+	break;
+      case 'S':
+	size = strtol(str, &str, 10);
+	break;
+      case '-':
+	fl_color(FL_DARK3);
+	fl_line(x+3, y+h/2, x+w1-3, y+h/2);
+	fl_color(FL_LIGHT3);
+	fl_line(x+3, y+h/2+1, x+w1-3, y+h/2+1);
+	break;
+      case 'u':
+      case '_':
+	fl_color(lcol);
+	fl_line(x+3, y+h-1, x+w1-3, y+h-1);
+	break;
+      case '.':
+	goto BREAK;
+      case '@':
+	str--; goto BREAK;
+      }
+    }
+  BREAK:
+    fl_font(font, size, Fl_Input_::default_font(), Fl_Input_::default_size());
+    if (!active_r()) lcol = inactive(lcol);
+    if (((FL_BLINE*)v)->flags & SELECTED)
+      lcol = contrast(lcol, selection_color());
+    fl_color(lcol);
+    fl_draw(str, x+3, y, w1-6, h, align);
+    if (!e) break; // no more fields...
+    *e = column_char(); // put the seperator back
+    x += w1;
+    w -= w1;
+    str = e+1;
+  }
+}
+
+static const int no_columns[1] = {0};
+
+Fl_Browser::Fl_Browser(int x, int y, int w, int h, const char*l)
+  : Fl_Browser_(x, y, w, h, l) {
+  column_widths_ = no_columns;
+  lines = 0;
+  full_height_ = 0;
+  cacheline = 0;
+  format_char_ = '@';
+  column_char_ = '\t';
+  first = last = cache = 0;
+}
+
+void Fl_Browser::topline(int line) {
+  if (line<1) line = 1;
+  if (line>lines) line = lines;
+  int p = 0;
+  for (FL_BLINE* l=first; l&& line>1; l = l->next) {
+    line--; p += item_height(l);
+  }
+  position(p);
+}
+
+int Fl_Browser::topline() const {
+  return lineno(top());
+}
+
+void Fl_Browser::clear() {
+  for (FL_BLINE* l = first; l;) {
+    FL_BLINE* h = l->next;
+    free(l);
+    l = h;
+  }
+  full_height_ = 0;
+  first = 0;
+  lines = 0;
+  new_list();
+}
+
+void Fl_Browser::add(const char* newtext, void* data) {
+  insert(lines+1, newtext, data);
+  Fl_Browser_::display(last);
+}
+
+const char* Fl_Browser::text(int line) const {
+  if (line < 1 || line > lines) return 0;
+  return find_line(line)->txt;
+}
+
+void* Fl_Browser::data(int line) const {
+  if (line < 1 || line > lines) return 0;
+  return find_line(line)->data;
+}
+
+int Fl_Browser::select(int line, int value) {
+  if (line < 1 || line > lines) return 0;
+  return Fl_Browser_::select(find_line(line), value);
+}
+
+int Fl_Browser::selected(int line) const {
+  if (line < 1 || line > lines) return 0;
+  return find_line(line)->flags & SELECTED;
+}
+
+void Fl_Browser::show(int line) {
+  FL_BLINE* t = find_line(line);
+  if (t->flags & NOTDISPLAYED) {
+    t->flags &= ~NOTDISPLAYED;
+    full_height_ += item_height(t);
+    if (Fl_Browser_::displayed(t)) redraw_lines();
+  }
+}
+
+void Fl_Browser::hide(int line) {
+  FL_BLINE* t = find_line(line);
+  if (!(t->flags & NOTDISPLAYED)) {
+    full_height_ -= item_height(t);
+    t->flags |= NOTDISPLAYED;
+    if (Fl_Browser_::displayed(t)) redraw_lines();
+  }
+}
+
+void Fl_Browser::display(int line, int value) {
+  if (line < 1 || line > lines) return;
+  if (value) show(line); else hide(line);
+}
+
+int Fl_Browser::visible(int line) const {
+  if (line < 1 || line > lines) return 0;
+  return !(find_line(line)->flags&NOTDISPLAYED);
+}
+
+int Fl_Browser::value() const {
+  return lineno(selection());
+}
+
+// end of Fl_Browser.C
diff --git a/src/Fl_Browser_.cxx b/src/Fl_Browser_.cxx
new file mode 100644
index 000000000..ae1908808
--- /dev/null
+++ b/src/Fl_Browser_.cxx
@@ -0,0 +1,606 @@
+// Fl_Browser_.C
+
+// This is the base class for browsers.  To be useful it must be
+// subclassed and several virtual functions defined.  The
+// Forms-compatable browser and the file chooser's browser are
+// subclassed off of this.
+
+// Yes, I know this should be a template...
+
+// This has been designed so that the subclass has complete control
+// over the storage of the data, although because next() and prev()
+// functions are used to index, it works best as a linked list or as a
+// large block of characters in which the line breaks must be searched
+// for.
+
+// A great deal of work has been done so that the "height" of a data
+// object does not need to be determined until it is drawn.  This was
+// done for the file chooser, because the height requires doing stat()
+// to see if the file is a directory, which can be annoyingly slow
+// over the network.
+
+#include 
+#include 
+#include 
+#include 
+#include  // for default_font
+
+/* redraw bits:
+   1 = redraw children (the scrollbar)
+   2 = redraw one or two items
+   4 = redraw all items
+*/
+
+static void scrollbar_callback(Fl_Widget* s, void*) {
+  ((Fl_Browser_*)(s->parent()))->position(int(((Fl_Scrollbar*)s)->value()));
+}
+
+static void hscrollbar_callback(Fl_Widget* s, void*) {
+  ((Fl_Browser_*)(s->parent()))->hposition(int(((Fl_Scrollbar*)s)->value()));
+}
+
+int Fl_Browser_::scrollbar_width_ = 17;
+
+// return where to draw the actual box:
+void Fl_Browser_::bbox(int& X, int& Y, int& W, int& H) const {
+  Fl_Boxtype b = box() ? box() : Fl_Input_::default_box();
+  X = x()+Fl::box_dx(b);
+  Y = y()+Fl::box_dy(b);
+  W = w()-Fl::box_dw(b);
+  H = h()-Fl::box_dh(b);
+  if (scrollbar.visible()) {
+    W -= scrollbar_width_;
+    if (scrollbar.align() & FL_ALIGN_LEFT) X += scrollbar_width_;
+  }
+  if (hscrollbar.visible()) {
+    H -= scrollbar_width_;
+    if (scrollbar.align() & FL_ALIGN_TOP) Y += scrollbar_width_;
+  }
+}
+
+int Fl_Browser_::leftedge() const {
+  int X, Y, W, H; bbox(X, Y, W, H);
+  return X;
+}
+
+// the scrollbars are resized & placed by draw(), since each one's size
+// depends on whether the other is visible or not.  This skips over
+// Fl_Group::resize since it moves the scrollbars uselessly.
+void Fl_Browser_::resize(int X, int Y, int W, int H) {
+  Fl_Widget::resize(X, Y, W, H);
+}
+
+// Cause minimal update to redraw the given item:
+void Fl_Browser_::redraw_line(void* l) {
+  if (!redraw1 || redraw1 == l) {redraw1 = l; damage(2);}
+  else if (!redraw2 || redraw2 == l) {redraw2 = l; damage(2);}
+  else damage(4);
+}
+
+// Figure out top() based on position():
+void Fl_Browser_::update_top() {
+  if (!top_) top_ = item_first();
+  if (position_ != real_position_) {
+    void* l;
+    int ly;
+    int y = position_;
+    // start from either head or current position, whichever is closer:
+    if (!top_ || y <= real_position_/2) {
+      l = item_first();
+      ly = 0;
+    } else {
+      l = top_;
+      ly = real_position_-offset_;
+    }
+    if (!l) {
+      top_ = 0;
+      offset_ = 0;
+      real_position_ = 0;
+    } else {
+      int h = item_quick_height(l);
+      // step through list until we find line containing this point:
+      while (ly > y) {
+	void* l1 = item_prev(l);
+	if (!l1) {ly = 0; break;} // hit the top
+	l = l1;
+	h = item_quick_height(l);
+	ly -= h;
+      }
+      while (ly+h <= y) {
+	void* l1 = item_next(l);
+	if (!l1) {y = ly+h-1; break;}
+	l = l1;
+	ly += h;
+	h = item_quick_height(l);
+      }
+      // top item must *really* be visible, use slow height:
+      for (;;) {
+	h = item_height(l);
+	if (ly+h > y) break; // it is big enough to see
+	// go up to top of previous item:
+	void* l1 = item_prev(l);
+	if (!l1) {ly = y = 0; break;} // hit the top
+	l = l1; y = position_ = ly = ly-item_quick_height(l);
+      }
+      // use it:
+      top_ = l;
+      offset_ = y-ly;
+      real_position_ = y;
+    }
+    damage(4);
+  }
+}
+
+// Change position(), top() will update when update_top() is called
+// (probably by draw() or handle()):
+void Fl_Browser_::position(int y) {
+  if (y < 0) y = 0;
+  if (y == position_) return;
+  position_ = y;
+  if (y != real_position_) redraw_lines();
+}
+
+void Fl_Browser_::hposition(int x) {
+  if (x < 0) x = 0;
+  if (x == hposition_) return;
+  hposition_ = x;
+  if (x != real_hposition_) redraw_lines();
+}
+
+// Tell whether item is currently displayed:
+int Fl_Browser_::displayed(void* x) const {
+  int X, Y, W, H; bbox(X, Y, W, H);
+  int yy = H+offset_;
+  for (void* l = top_; l && yy > 0; l = item_next(l)) {
+    if (l == x) return 1;
+    yy -= item_height(l);
+  }
+  return 0;
+}
+
+// Insure this item is displayed:
+// Messy because we have no idea if it is before top or after bottom:
+void Fl_Browser_::display(void* x) {
+  if (!top_) top_ = item_first();
+  if (x == item_first()) {position(0); return;}
+  int X, Y, W, H; bbox(X, Y, W, H);
+  void* l = top_;
+  Y = -offset_;
+  // see if it is at the top or just above it:
+  if (l == x) {position(real_position_+Y); return;} // scroll up a bit
+  void* lp = item_prev(l);
+  if (lp == x) {position(real_position_+Y-item_quick_height(lp)); return;}
+  // search forward for it:
+  for (; l; l = item_next(l)) {
+    int h1 = item_quick_height(l);
+    if (l == x) {
+      if (Y <= H) { // it is visible or right at bottom
+	Y = Y+h1-H; // find where bottom edge is
+	if (Y > 0) position(real_position_+Y); // scroll down a bit
+      } else {
+	position(real_position_+Y-(H-h1)/2); // center it
+      }
+      return;
+    }
+    Y += h1;
+  }
+  // search backward for it, if found center it:
+  l = lp;
+  Y = -offset_;
+  for (; l; l = item_prev(l)) {
+    int h1 = item_quick_height(l);
+    Y -= h1;
+    if (l == x) {
+      if (Y + h1 >= 0) position(real_position_+Y);
+      else position(real_position_+Y-(H-h1)/2);
+      return;
+    }
+  }
+}
+
+// redraw, has side effect of updating top and setting scrollbar:
+void Fl_Browser_::draw() {
+  int drawsquare = 0;
+  if (damage() & 128) { // redraw the box if full redraw
+    Fl_Boxtype b = box() ? box() : Fl_Input_::default_box();
+    draw_box(b, x(), y(), w(), h(), color());
+    drawsquare = 1;
+  }
+
+  update_top();
+  int full_width_ = full_width();
+  int full_height_ = full_height();
+  int X, Y, W, H; bbox(X, Y, W, H);
+J1:
+  // see if scrollbar needs to be switched on/off:
+  if ((has_scrollbar_ & VERTICAL) && (
+	(has_scrollbar_ & ALWAYS_ON) || position_ || full_height_ > H)) {
+    if (!scrollbar.visible()) {scrollbar.show(); drawsquare = 1;}
+  } else {
+    top_ = item_first(); real_position_ = offset_ = 0;
+    scrollbar.hide();
+  }
+
+  if ((has_scrollbar_ & HORIZONTAL) && (
+	(has_scrollbar_ & ALWAYS_ON) || hposition_ || full_width_ > W)) {
+    if (!hscrollbar.visible()) {hscrollbar.show(); drawsquare = 1;}
+  } else {
+    real_hposition_ = 0;
+    hscrollbar.hide();
+  }
+
+  bbox(X, Y, W, H);
+
+  fl_clip(X, Y, W, H);
+  // for each line, draw it if full redraw or scrolled.  Erase background
+  // if not a full redraw or if it is selected:
+  void* l = top();
+  int yy = -offset_;
+  for (; l && yy < H; l = item_next(l)) {
+    int hh = item_height(l);
+    if (hh <= 0) continue;
+    if ((damage()&4) || l == redraw1 || l == redraw2) {
+      if (item_selected(l)) {
+	fl_color(selection_color());
+	fl_rectf(X, yy+Y, W, hh);
+      } else if (!(damage()&128)) {
+	fl_color(color());
+	fl_rectf(X, yy+Y, W, hh);
+      }
+      if (type() == FL_MULTI_BROWSER && l == selection_) {
+	fl_color(textcolor());
+	fl_rect(X+1, yy+Y, W-2, hh);
+      }
+      item_draw(l, X-hposition_, yy+Y, W, hh);
+      int w = item_width(l);
+      if (w > max_width) {max_width = w; max_width_item = l;}
+    }
+    yy += hh;
+  }
+  // erase the area below last line:
+  if (!(damage()&128) && yy < H) {
+    fl_color(color());
+    fl_rectf(X, yy+Y, W, H-yy);
+  }
+  fl_pop_clip();
+  redraw1 = redraw2 = 0;
+
+  // see if changes to full_height caused by calls to slow_height
+  // caused scrollbar state to change, in which case we have to redraw:
+  full_height_ = full_height();
+  full_width_ = full_width();
+  if ((has_scrollbar_ & VERTICAL) && (
+      (has_scrollbar_ & ALWAYS_ON) || position_ || full_height_>H)) {
+    if (!scrollbar.visible()) goto J1;
+  } else {
+    if (scrollbar.visible()) goto J1;
+  }
+  if ((has_scrollbar_ & HORIZONTAL) && (
+      (has_scrollbar_ & ALWAYS_ON) || hposition_ || full_width_>W)) {
+    if (!hscrollbar.visible()) goto J1;
+  } else {
+    if (hscrollbar.visible()) goto J1;
+  }
+
+  // update the scrollbars and redraw them:
+  int dy = top_ ? item_quick_height(top_) : 0; if (dy < 10) dy = 10;
+  if (scrollbar.visible()) {
+    scrollbar.damage_resize(
+	scrollbar.align()&FL_ALIGN_LEFT ? X-scrollbar_width_ : X+W,
+	Y, scrollbar_width_, H);
+    scrollbar.value(position_, H, 0, full_height_);
+    scrollbar.linesize(dy);
+    if (drawsquare) draw_child(scrollbar);
+    else update_child(scrollbar);
+  }
+  if (hscrollbar.visible()) {
+    hscrollbar.damage_resize(
+	X, scrollbar.align()&FL_ALIGN_TOP ? Y-scrollbar_width_ : Y+H,
+	W, scrollbar_width_);
+    hscrollbar.value(hposition_, W, 0, full_width_);
+    hscrollbar.linesize(dy);
+    if (drawsquare) draw_child(hscrollbar);
+    else update_child(hscrollbar);
+  }
+
+  // draw that little square between the scrolbars:
+  if (drawsquare && scrollbar.visible() && hscrollbar.visible()) {
+    fl_color(parent()->color());
+    fl_rectf(scrollbar.x(), hscrollbar.y(), scrollbar_width_,scrollbar_width_);
+  }
+
+  real_hposition_ = hposition_;
+}
+
+// Quick way to delete and reset everything:
+void Fl_Browser_::new_list() {
+  top_ = 0;
+  position_ = real_position_ = 0;
+  hposition_ = real_hposition_ = 0;
+  selection_ = 0;
+  offset_ = 0;
+  max_width = 0;
+  max_width_item = 0;
+  redraw_lines();
+}
+
+// Tell it that this item is going away, and that this must remove
+// all pointers to it:
+void Fl_Browser_::deleting(void* l) {
+  if (displayed(l)) redraw_lines();
+  if (l == selection_) selection_ = 0;
+  if (l == top_) {
+    real_position_ -= offset_;
+    offset_ = 0;
+    top_ = item_next(l);
+    if (!top_) top_ = item_prev(l);
+  }
+  if (l == max_width_item) {max_width_item = 0; max_width = 0;}
+}
+
+void Fl_Browser_::replacing(void* a, void* b) {
+  redraw_line(a);
+  if (a == selection_) selection_ = b;
+  if (a == top_) top_ = b;
+  if (a == max_width_item) {max_width_item = 0; max_width = 0;}
+}
+
+void Fl_Browser_::inserting(void* a, void* b) {
+  if (displayed(a)) redraw_lines();
+  if (a == top_) top_ = b;
+}
+
+void* Fl_Browser_::find_item(int my) {
+  update_top();
+  int X, Y, W, H; bbox(X, Y, W, H);
+  void* l;
+  int yy = Y-offset_;
+  for (l = top_; l; l = item_next(l)) {
+    int hh = item_height(l); if (hh <= 0) continue;
+    yy += hh;
+    if (my <= yy || yy>=Y+H) return l;
+  }
+  return 0;
+}
+
+int Fl_Browser_::select(void* l, int i, int docallbacks) {
+  if (type() == FL_MULTI_BROWSER) {
+    if (selection_ != l) {
+      if (selection_) redraw_line(selection_);
+      selection_ = l;
+      redraw_line(l);
+    }
+    if ((!i)==(!item_selected(l))) return 0;
+    item_select(l, i);
+    redraw_line(l);
+  } else {
+    if (i && selection_ == l) return 0;
+    if (!i && selection_ != l) return 0;
+    if (selection_) {
+      item_select(selection_, 0);
+      redraw_line(selection_);
+      selection_ = 0;
+    }
+    if (i) {
+      item_select(l, 1);
+      selection_ = l;
+      redraw_line(l);
+      display(l);
+    }
+  }	    
+  Fl::event_clicks(0);
+  if (docallbacks) do_callback();
+  return 1;
+}
+
+int Fl_Browser_::deselect(int docallbacks) {
+  if (type() == FL_MULTI_BROWSER) {
+    int change = 0;
+    for (void* p = item_first(); p; p = item_next(p))
+      change |= select(p, 0, docallbacks);
+    return change;
+  } else {
+    if (!selection_) return 0;
+    item_select(selection_, 0);
+    redraw_line(selection_);
+    selection_ = 0;
+    return 1;
+  }
+}
+
+int Fl_Browser_::select_only(void* l, int docallbacks) {
+  if (!l) return deselect(docallbacks);
+  int change = 0;
+  if (type() == FL_MULTI_BROWSER) {
+    for (void* p = item_first(); p; p = item_next(p))
+      if (p != l) change |= select(p, 0, docallbacks);
+  }
+  change |= select(l, 1, docallbacks);
+  display(l);
+  return change;
+}
+
+int Fl_Browser_::handle(int event) {
+
+  // must do shortcuts first or the scrollbar will get them...
+  if (event == FL_SHORTCUT && type() >= FL_HOLD_BROWSER) {
+    void* l1 = selection_;
+    void* l = l1; if (!l) l = top_; if (!l) l = item_first();
+    if (l) {
+      if (type()==FL_HOLD_BROWSER) switch (Fl::event_key()) {
+      case FL_Down:
+	while ((l = item_next(l)))
+	  if (item_height(l)>0) {select_only(l, 1); break;}
+	return 1;
+      case FL_Up:
+	while ((l = item_prev(l))) if (item_height(l)>0) {
+	  select_only(l, 1); break;}
+	return 1;
+      } else switch (Fl::event_key()) {
+      case FL_Enter:
+	select_only(l, 1);
+	return 1;
+      case ' ':
+	selection_ = l;
+	select(l, !item_selected(l), 1);
+	return 1;
+      case FL_Down:
+	while ((l = item_next(l))) {
+	  if (Fl::event_state(FL_SHIFT|FL_CTRL))
+	    select(l, l1 ? item_selected(l1) : 1, 1);
+	  if (item_height(l)>0) goto J1;
+	}
+	return 1;
+      case FL_Up:
+	while ((l = item_prev(l))) {
+	  if (Fl::event_state(FL_SHIFT|FL_CTRL))
+	    select(l, l1 ? item_selected(l1) : 1, 1);
+	  if (item_height(l)>0) goto J1;
+	}
+	return 1;
+      J1:
+	if (selection_) redraw_line(selection_);
+	selection_ = l; redraw_line(l);
+	display(l);
+	return 1;
+      }
+    }
+  }
+
+  if (Fl_Group::handle(event)) return 1;
+  int X, Y, W, H; bbox(X, Y, W, H);
+  int my;
+  static char change;
+  static char whichway;
+  static int py;
+  switch (event) {
+  case FL_PUSH:
+    if (!Fl::event_inside(X, Y, W, H)) return 0;
+    if (type() == FL_SELECT_BROWSER) deselect();
+    my = py = Fl::event_y();
+    change = 0;
+    if (type() == FL_NORMAL_BROWSER || !top_)
+      ;
+    else if (type() == FL_MULTI_BROWSER) {
+      void* l = find_item(my);
+      whichway = 1;
+      if (Fl::event_state(FL_SHIFT|FL_CTRL)) { // toggle selection:
+	if (l) {
+	  whichway = !item_selected(l);
+	  change = select(l, whichway, when() & FL_WHEN_CHANGED);
+	}
+      } else {
+	change = select_only(l, when() & FL_WHEN_CHANGED);
+      }
+    } else {
+      change = select_only(find_item(my), when() & FL_WHEN_CHANGED);
+    }
+    return 1;
+  case FL_DRAG:
+    // do the scrolling first:
+    my = Fl::event_y();
+    if (my < Y && my < py) {
+      int p = real_position_+my-Y;
+      if (p<0) p = 0;
+      position(p);
+    } else if (my > Y+H && my > py) {
+      int p = real_position_+my-(Y+H);
+      int h = full_height()-H; if (p > h) p = h;
+      if (p<0) p = 0;
+      position(p);
+    }
+    if (type() == FL_NORMAL_BROWSER || !top_)
+      ;
+    else if (type() == FL_MULTI_BROWSER) {
+      void* l = find_item(my);
+      void* t; void* b; // this will be the range to change
+      if (my > py) { // go down
+	t = selection_ ? item_next(selection_) : 0;
+	b = l ? item_next(l) : 0;
+      } else {	// go up
+	t = l;
+	b = selection_;
+      }
+      for (; t && t != b; t = item_next(t))
+	change |= select(t, whichway, when() & FL_WHEN_CHANGED);
+      if (l) selection_ = l;
+    } else {
+      void* l1 = selection_;
+      void* l =
+	(Fl::event_x()x()+w()) ? selection_ :
+	find_item(my);
+      select_only(l, when() & FL_WHEN_CHANGED);
+      change = (l != l1);
+    }
+    py = my;
+    return 1;
+  case FL_RELEASE:
+    if (type() == FL_SELECT_BROWSER) {
+      void* t = selection_; deselect(); selection_ = t;
+    }
+    if (change) {
+      if (when() & FL_WHEN_RELEASE) do_callback();
+      else if (!(when()&FL_WHEN_CHANGED)) set_changed();
+    } else {
+      if (when() & FL_WHEN_NOT_CHANGED) do_callback();
+    }
+    return 1;
+  }
+
+  return 0;
+}
+
+Fl_Browser_::Fl_Browser_(int x, int y, int w, int h, const char* l)
+  : Fl_Group(x, y, w, h, l),
+    scrollbar(0, 0, 0, 0, 0), // they will be resized by draw()
+    hscrollbar(0, 0, 0, 0, 0)
+{
+  box(FL_NO_BOX);
+  align(FL_ALIGN_BOTTOM);
+  position_ = real_position_ = 0;
+  hposition_ = real_hposition_ = 0;
+  offset_ = 0;
+  top_ = 0;
+  when(FL_WHEN_RELEASE_ALWAYS);
+  selection_ = 0;
+  color(FL_WHITE);
+  selection_color(FL_SELECTION_COLOR);
+  scrollbar.callback(scrollbar_callback);
+//scrollbar.align(FL_ALIGN_LEFT|FL_ALIGN_BOTTOM); // back compatability?
+  hscrollbar.callback(hscrollbar_callback);
+  hscrollbar.type(FL_HORIZONTAL);
+  textfont_ = FL_HELVETICA;
+  textsize_ = FL_NORMAL_SIZE;
+  textcolor_ = FL_BLACK;
+  has_scrollbar_ = BOTH;
+  max_width = 0;
+  max_width_item = 0;
+  end();
+}
+
+// Default versions of some of the virtual functions:
+
+int Fl_Browser_::item_quick_height(void* l) const {
+  return item_height(l);
+}
+
+int Fl_Browser_::incr_height() const {
+  return item_quick_height(item_first());
+}
+
+int Fl_Browser_::full_height() const {
+  int t = 0;
+  for (void* p = item_first(); p; p = item_next(p))
+    t += item_quick_height(p);
+  return t;
+}
+
+int Fl_Browser_::full_width() const {
+  return max_width;
+}
+
+void Fl_Browser_::item_select(void*, int) {}
+
+int Fl_Browser_::item_selected(void* l) const {return l==selection_;}
+
+// end of Fl_Browser_.C
diff --git a/src/Fl_Browser_load.cxx b/src/Fl_Browser_load.cxx
new file mode 100644
index 000000000..8e1da435a
--- /dev/null
+++ b/src/Fl_Browser_load.cxx
@@ -0,0 +1,29 @@
+// Fl_Browser_load.C
+// this should be moved to another source file, since it links stdio?
+
+#include 
+#include 
+#include 
+
+int Fl_Browser::load(const char *filename) {
+#define MAXFL_BLINE 1024
+    char newtext[MAXFL_BLINE];
+    int c;
+    int i;
+    clear();
+    if (!filename || !(filename[0])) return 1;
+    FILE *fl = fopen(filename,"r");
+    if (!fl) return 0;
+    i = 0;
+    do {
+	c = getc(fl);
+	if (c == '\n' || c <= 0 || i>=MAXFL_BLINE-1) {
+	    newtext[i] = 0;
+	    add(newtext);
+	    i = 0;
+	} else
+	    newtext[i++] = c;
+    } while (c >= 0);
+    fclose(fl);
+    return 1;
+}
diff --git a/src/Fl_Button.cxx b/src/Fl_Button.cxx
new file mode 100644
index 000000000..86b563e78
--- /dev/null
+++ b/src/Fl_Button.cxx
@@ -0,0 +1,92 @@
+// Fl_Button.C
+
+// There are a lot of subclasses, named Fl_*_Button.  Some of
+// them are implemented by setting the type() value and testing it
+// here.  This includes Fl_Radio_Button and Fl_Toggle_Button
+
+#include 
+#include 
+#include 
+
+int Fl_Button::value(int v) {
+  v = v ? 1 : 0;
+  oldval = v;
+  clear_changed();
+  if (value_ != v) {value_ = v; redraw(); return 1;}
+  else return 0;
+}
+
+void Fl_Button::setonly() { // set this radio button on, turn others off
+  value(1);
+  Fl_Group* g = (Fl_Group*)parent();
+  Fl_Widget*const* a = g->array();
+  for (int i = g->children(); i--;) {
+    Fl_Widget* o = *a++;
+    if (o != this && o->type()==FL_RADIO_BUTTON) ((Fl_Button*)o)->value(0);
+  }
+}
+
+void Fl_Button::draw() {
+  if (type() == FL_HIDDEN_BUTTON) return;
+  Fl_Color col = value() ? selection_color() : color();
+//if (col == FL_GRAY && Fl::belowmouse()==this) col = FL_LIGHT1;
+  draw_box(value() ? (down_box()?down_box():down(box())) : box(), col);
+  draw_label();
+}
+int Fl_Button::handle(int event) {
+  int newval;
+  switch (event) {
+  case FL_ENTER:
+  case FL_LEAVE:
+//  if ((value_?selection_color():color())==FL_GRAY) redraw();
+    return 1;
+  case FL_PUSH:
+  case FL_DRAG:
+    if (Fl::event_inside(this)) {
+      if (type() == FL_RADIO_BUTTON) newval = 1;
+      else newval = !oldval;
+    } else
+      newval = oldval;
+    if (newval != value_) {
+      value_ = newval;
+      redraw();
+      if (when() & FL_WHEN_CHANGED) do_callback();
+    }
+    return 1;
+  case FL_RELEASE:
+    if (value_ == oldval) return 1;
+    if (type() == FL_RADIO_BUTTON)
+      setonly();
+    else if (type() == FL_TOGGLE_BUTTON)
+      oldval = value_;
+    else {
+      value(oldval);
+      if (when() & FL_WHEN_CHANGED) do_callback();
+    }
+    if (when() & FL_WHEN_RELEASE) do_callback(); else set_changed();
+    return 1;
+  case FL_SHORTCUT:
+    if (!(shortcut() ?
+	  Fl::test_shortcut(shortcut()) : test_shortcut())) return 0;
+    if (type() == FL_RADIO_BUTTON && !value_) {
+      setonly();
+      if (when() & FL_WHEN_CHANGED) do_callback();
+    } else if (type() == FL_TOGGLE_BUTTON) {
+      value(!value());
+      if (when() & FL_WHEN_CHANGED) do_callback();
+    }
+    if (when() & FL_WHEN_RELEASE) do_callback(); else set_changed();
+    return 1;
+  default:
+    return 0;
+  }
+}
+
+Fl_Button::Fl_Button(int x,int y,int w,int h, const char *l)
+: Fl_Widget(x,y,w,h,l) {
+  box(FL_UP_BOX);
+  down_box(FL_NO_BOX);
+  value_ = oldval = 0;
+  shortcut_ = 0;
+  set_flag(SHORTCUT_LABEL);
+}
diff --git a/src/Fl_Chart.cxx b/src/Fl_Chart.cxx
new file mode 100644
index 000000000..54c6913f9
--- /dev/null
+++ b/src/Fl_Chart.cxx
@@ -0,0 +1,344 @@
+// Fl_Chart.C
+
+// Emulation of the Forms Chart widget.
+// I did not try to improve this much, as I doubt it is used.
+
+// display code Written by: Mark Overmars
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ARCINC	(2.0*M_PI/360.0)
+
+// this function is in fl_boxtype.C:
+void fl_rectbound(int x,int y,int w,int h, Fl_Color color);
+
+/* Widget specific information */
+
+static void draw_barchart(int x,int y,int w,int h,
+			  int numb, FL_CHART_ENTRY entries[],
+			  double min, double max, int autosize, int maxnumb,
+			  Fl_Color textcolor)
+/* Draws a bar chart. x,y,w,h is the bounding box, entries the array of
+   numb entries and min and max the boundaries. */
+{
+  double incr = h/(max-min);
+  int zeroh;
+  double lh = fl_height();
+  if ( -min*incr < lh) {
+      incr = (h - lh + min*incr)/(max-min);
+      zeroh = int(y+h-lh);
+  } else {
+      zeroh = int(y+h+min * incr + .5);
+  }
+  int bwidth = int(w/double(autosize?numb:maxnumb)+.5);
+  /* Draw base line */
+  fl_color(textcolor);
+  fl_line(x, zeroh, x+w, zeroh);
+  if (min == 0.0 && max == 0.0) return; /* Nothing else to draw */
+  int i;
+  /* Draw the bars */
+  for (i=0; i 0)
+	fl_rectbound(x+i*bwidth,zeroh-h,bwidth+1,h+1,(Fl_Color)entries[i].col);
+  }
+  /* Draw the labels */
+  fl_color(textcolor);
+  for (i=0; i lw) lw = w1;
+  }
+  if (lw > 0.0) lw += 4.0;
+  double incr = w/(max-min);
+  int zeroh;
+  if ( -min*incr < lw) {
+      incr = (w - lw + min*incr)/(max-min);
+      zeroh = x+int(lw+.5);
+  } else {
+      zeroh = int(x-min * incr + .5);
+  }
+  int bwidth = int(h/double(autosize?numb:maxnumb)+.5);
+  /* Draw base line */
+  fl_color(textcolor);
+  fl_line(zeroh, y, zeroh, y+h);
+  if (min == 0.0 && max == 0.0) return; /* Nothing else to draw */
+  /* Draw the bars */
+  for (i=0; i 0)
+	fl_rectbound(zeroh,y+i*bwidth,w+1,bwidth+1, (Fl_Color)entries[i].col);
+      else if (w < 0)
+	fl_rectbound(zeroh+w,y+i*bwidth,-w+1,bwidth+1,(Fl_Color)entries[i].col);
+  }
+  /* Draw the labels */
+  for (i=0; i0.0)!=(entries[i].val>0.0)) {
+	      double ttt = entries[i-1].val/(entries[i-1].val-entries[i].val);
+	      int xt = x + int((i-.5+ttt)*bwidth+.5);
+	      fl_polygon(x0,zeroh, x0,y0, xt,zeroh);
+	      fl_polygon(xt,zeroh, x1,y1, x1,zeroh);
+	  } else {
+	      fl_polygon(x0,zeroh, x0,y0, x1,y1, x1,zeroh);
+	  }
+	  fl_color(textcolor);
+	  fl_line(x0,y0,x1,y1);
+      }
+  }
+  /* Draw base line */
+  fl_color(textcolor);
+  fl_line(x,zeroh,x+w,zeroh);
+  /* Draw the labels */
+  for (i=0; i=0 ? FL_ALIGN_BOTTOM : FL_ALIGN_TOP);
+}
+
+static void draw_piechart(int x,int y,int w,int h,
+			  int numb, FL_CHART_ENTRY entries[], int special,
+			  Fl_Color textcolor)
+/* Draws a pie chart. x,y,w,h is the bounding box, entries the array of
+   numb entries */
+{
+  int i;
+  double xc,yc,rad;	/* center and radius */
+  double tot;		/* sum of values */
+  double incr;		/* increment in angle */
+  double curang;		/* current angle we are drawing */
+  double txc,tyc;	/* temporary center */
+  double lh = fl_height();
+  /* compute center and radius */
+  xc = x+w/2.0; yc = y+h/2.0;
+  rad = h/2.0 - lh;
+  if (special) { yc += 0.1*rad; rad = 0.9*rad;}
+  /* compute sum of values */
+  tot = 0.0;
+  for (i=0; i 0.0) tot += entries[i].val;
+  if (tot == 0.0) return;
+  incr = 360.0/tot;
+  /* Draw the pie */
+  curang = 0.0;
+  for (i=0; i 0.0)
+    {
+      txc = xc; tyc = yc;
+      /* Correct for special pies */
+      if (special && i==0)
+      {
+        txc += 0.3*rad*cos(ARCINC*(curang+0.5*incr*entries[i].val));
+        tyc -= 0.3*rad*sin(ARCINC*(curang+0.5*incr*entries[i].val));
+      }
+      fl_color((Fl_Color)entries[i].col);
+      fl_begin_polygon(); fl_vertex(txc,tyc);
+      fl_arc(txc,tyc,rad,curang, curang+incr*entries[i].val);
+      fl_end_polygon();
+      fl_color(textcolor);
+      fl_begin_loop(); fl_vertex(txc,tyc);
+      fl_arc(txc,tyc,rad,curang, curang+incr*entries[i].val);
+      fl_end_loop();
+      curang += 0.5 * incr * entries[i].val;
+      /* draw the label */
+      double xl = txc + 1.1*rad*cos(ARCINC*curang);
+      fl_draw(entries[i].str,
+	      int(xl+.5),
+	      int(tyc - 1.1*rad*sin(ARCINC*curang)+.5),
+	      0, 0,
+	      xl= max) {
+	min = max = 0.0;
+	for (i=0; i max) max = entries[i].val;
+	}
+    }
+
+    draw_box();
+    fl_font(textfont(),textsize());
+
+    switch (type()) {
+    case FL_BAR_CHART:
+	draw_barchart(xx,yy,ww,hh, numb, entries, min, max,
+			autosize(), maxnumb, textcolor());
+	break;
+    case FL_HORBAR_CHART:
+	draw_horbarchart(xx,yy,ww,hh, numb, entries, min, max,
+			autosize(), maxnumb, textcolor());
+	break;
+    case FL_PIE_CHART:
+	draw_piechart(xx,yy,ww,hh,numb,entries,0, textcolor());
+	break;
+    case FL_SPECIALPIE_CHART:
+	draw_piechart(xx,yy,ww,hh,numb,entries,1,textcolor());
+	break;
+    default:
+	draw_linechart(type(),xx,yy,ww,hh, numb, entries, min, max,
+			autosize(), maxnumb, textcolor());
+	break;
+    }
+    draw_label();
+}
+
+/*------------------------------*/
+
+#define FL_CHART_BOXTYPE	FL_BORDER_BOX
+#define FL_CHART_COL1		FL_COL1
+#define FL_CHART_LCOL		FL_LCOL
+#define FL_CHART_ALIGN		FL_ALIGN_BOTTOM
+
+Fl_Chart::Fl_Chart(int x,int y,int w,int h,const char *l) :
+Fl_Widget(x,y,w,h,l) {
+    box(FL_BORDER_BOX);
+    align(FL_ALIGN_BOTTOM);
+    numb = 0;
+    maxnumb = FL_CHART_MAX;
+    autosize_ = 1;
+    min = max = 0;
+    textfont_ = FL_HELVETICA;
+    textsize_ = 10;
+    textcolor_ = FL_BLACK;
+}
+
+void Fl_Chart::clear() {
+    numb = 0;
+    redraw();
+}
+
+void Fl_Chart::add(double val, const char *str, uchar col) {
+  int i;
+  /* Shift entries if required */
+  if (numb >= maxnumb) {
+    for (i=0; i numb+1) return;
+    /* Shift entries */
+    for (i=numb; i >= index; i--) entries[i] = entries[i-1];
+    if (numb < maxnumb) numb++;
+    /* Fill in the new entry */
+    entries[index-1].val = float(val);
+    entries[index-1].col = col;
+    if (str) {
+	strncpy(entries[index-1].str,str,FL_CHART_LABEL_MAX+1);
+	entries[index-1].str[FL_CHART_LABEL_MAX] = 0;
+    } else {
+	entries[index-1].str[0] = 0;
+    }
+    redraw();
+}
+
+void Fl_Chart::replace(int index,double val, const char *str, uchar col) {
+    if (index < 1 || index > numb) return;
+    entries[index-1].val = float(val);
+    entries[index-1].col = col;
+    if (str) {
+	strncpy(entries[index-1].str,str,FL_CHART_LABEL_MAX+1);
+	entries[index-1].str[FL_CHART_LABEL_MAX] = 0;
+    } else {
+	entries[index-1].str[0] = 0;
+    }
+    redraw();
+}
+
+void Fl_Chart::bounds(double min, double max) {
+    this->min = min;
+    this->max = max;
+    redraw();
+}
+
+void Fl_Chart::maxsize(int m) {
+    int i;
+    /* Fill in the new number */
+    if (m < 0) return;
+    if (m > FL_CHART_MAX)
+	maxnumb = FL_CHART_MAX;
+    else
+	maxnumb = m;
+    /* Shift entries if required */
+    if (numb > maxnumb) {
+	for (i = 0; i
+#include 
+
+Fl_Check_Button::Fl_Check_Button(int x, int y, int w, int h, const char *l)
+: Fl_Light_Button(x, y, w, h, l) {
+  box(FL_NO_BOX);
+  down_box(FL_DIAMOND_DOWN_BOX);
+  selection_color(FL_RED);
+}
diff --git a/src/Fl_Choice.cxx b/src/Fl_Choice.cxx
new file mode 100644
index 000000000..de41d4ffc
--- /dev/null
+++ b/src/Fl_Choice.cxx
@@ -0,0 +1,63 @@
+// Fl_Choice.C
+
+// Emulates the Forms choice widget.  This is almost exactly the same
+// as an Fl_Menu_Button.  The only difference is the appearance of the
+// button: it draws the text of the current pick and a down-arrow.
+
+#include 
+#include 
+#include 
+
+extern char fl_draw_shortcut;
+
+void Fl_Choice::draw() {
+  draw_box();
+  if (box() == FL_FLAT_BOX) return; // for XForms compatability
+  int H = labelsize()/2+1;
+  draw_box(FL_THIN_UP_BOX,x()+w()-3*H,y()+(h()-H)/2,2*H,H,color());
+  fl_font(textfont(),textsize(),default_font(),default_size());
+  fl_color(active_r() ? textcolor() : inactive(textcolor()));
+  fl_draw_shortcut = 2; // hack value to make '&' disappear
+  fl_draw(text(),x()+6,y(),w()-6,h(),FL_ALIGN_LEFT);
+  fl_draw_shortcut = 0;
+  draw_label();
+}
+
+Fl_Choice::Fl_Choice(int x,int y,int w,int h, const char *l)
+: Fl_Menu_(x,y,w,h,l) {
+  align(FL_ALIGN_LEFT);
+  when(FL_WHEN_RELEASE);
+  textfont(FL_HELVETICA);
+  down_box(FL_NO_BOX);
+}
+
+int Fl_Choice::value(int v) {
+  if (!Fl_Menu_::value(v)) return 0;
+  redraw();
+  return 1;
+}
+
+int Fl_Choice::handle(int e) {
+  if (!menu() || !menu()->text) return 0;
+  const Fl_Menu_Item* v;
+  switch (e) {
+  case FL_PUSH:
+  J1:
+    v = menu()->pulldown(x(), y(), w(), h(), mvalue(), this);
+    if (!v || v->submenu()) return 1;
+    if (v != mvalue()) redraw();
+    picked(v);
+    return 1;
+  case FL_SHORTCUT:
+    if (Fl_Widget::test_shortcut()) goto J1;
+    v = menu()->test_shortcut();
+    if (!v) return 0;
+    if (v != mvalue()) redraw();
+    picked(v);
+    return 1;
+  default:
+    return 0;
+  }
+}
+
+// end of Fl_Choice.C
diff --git a/src/Fl_Clock.cxx b/src/Fl_Clock.cxx
new file mode 100644
index 000000000..852dcb476
--- /dev/null
+++ b/src/Fl_Clock.cxx
@@ -0,0 +1,136 @@
+// Fl_Clock.C
+
+// There really should be a way to make this display something other
+// than the current time...
+
+// Original clock display written by Paul Haeberli at SGI.
+// Modifications by Mark Overmars for Forms
+// Further changes by Bill Spitzak for fltk
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+const float hourhand[4][2] = {{-0.5f, 0}, {0, 1.5f}, {0.5f, 0}, {0, -7.0f}};
+const float  minhand[4][2] = {{-0.5f, 0}, {0, 1.5f}, {0.5f, 0}, {0, -11.5f}};
+const float  sechand[4][2] = {{-0.1f, 0}, {0, 2.0f}, {0.1f, 0}, {0, -11.5f}};
+
+static void drawhand(double ang,const float v[][2],Fl_Color fill,Fl_Color line)
+{
+  fl_push_matrix();
+  fl_rotate(ang);
+  fl_color(fill); fl_begin_polygon();
+  int i; for (i=0; i<4; i++) fl_vertex(v[i][0],v[i][1]); fl_end_polygon();
+  fl_color(line); fl_begin_loop();
+  for (i=0; i<4; i++) fl_vertex(v[i][0],v[i][1]); fl_end_loop();
+  fl_pop_matrix();
+}
+
+void Fl_Clock::drawhands(Fl_Color fill, Fl_Color line) {
+  drawhand(-360*(hour()+minute()/60.0)/12, hourhand, fill, line);
+  drawhand(-360*(minute()+second()/60.0)/60, minhand, fill, line);
+  drawhand(-360*(second()/60.0), sechand, fill, line);
+}
+
+static void rect(double x, double y, double w, double h) {
+  double r = x+w;
+  double t = y+h;
+  fl_begin_polygon();
+  fl_vertex(x, y);
+  fl_vertex(r, y);
+  fl_vertex(r, t);
+  fl_vertex(x, t);
+  fl_end_polygon();
+}
+
+void Fl_Clock::draw(int x, int y, int w, int h) {
+  draw_box(box(), x, y, w, h, type()==FL_ROUND_CLOCK ? FL_GRAY : color());
+  fl_push_matrix();
+  fl_translate(x+w/2.0-.5, y+h/2.0-.5);
+  fl_scale((w-1)/28.0, (h-1)/28.0);
+  if (type() == FL_ROUND_CLOCK) {
+    fl_color(color());
+    fl_begin_polygon(); fl_circle(0,0,14); fl_end_polygon();
+    fl_color(FL_BLACK);
+    fl_begin_loop(); fl_circle(0,0,14); fl_end_loop();
+  }
+  // draw the shadows:
+  fl_push_matrix();
+  fl_translate(0.60, 0.60);
+  drawhands(FL_DARK3, FL_DARK3);
+  fl_pop_matrix();
+  // draw the tick marks:
+  fl_push_matrix();
+  fl_color(FL_BLACK); // color was 52
+  for (int i=0; i<12; i++) {
+    if (i==6) rect(-0.5, 9, 1, 2);
+    else if (i==3 || i==0 || i== 9) rect(-0.5, 9.5, 1, 1);
+    else rect(-0.25, 9.5, .5, 1);
+    fl_rotate(-30);
+  }
+  fl_pop_matrix();
+  // draw the hands:
+  drawhands(selection_color(), FL_GRAY0); // color was 54
+  fl_pop_matrix();
+}
+
+void Fl_Clock::draw() {
+  draw(x(), y(), w(), h());
+  draw_label();
+}
+
+void Fl_Clock::value(int h, int m, int s) {
+  if (h!=hour_ || m!=minute_ || s!=second_) {
+    hour_ = h; minute_ = m; second_ = s;
+    redraw();
+  }
+}
+
+void Fl_Clock::value(ulong v) {
+  struct tm *timeofday;
+  timeofday = localtime((const time_t *)&v);
+  value(timeofday->tm_hour, timeofday->tm_min, timeofday->tm_sec);
+}
+
+static void tick(void *v) {
+  ((Fl_Clock*)v)->value(time(0));
+  Fl::add_timeout(1, tick, v);
+}
+
+void Fl_Clock::_Fl_Clock() {
+  selection_color(fl_gray_ramp(5));
+  align(FL_ALIGN_BOTTOM);
+  value(time(0));
+  //Fl::add_timeout(1, tick, this);
+}
+
+Fl_Clock::Fl_Clock(int x, int y, int w, int h, const char *l)
+: Fl_Widget(x, y, w, h, l) {
+  box(FL_UP_BOX);
+  _Fl_Clock();
+}
+
+Fl_Clock::Fl_Clock(uchar t, int x, int y, int w, int h, const char *l)
+: Fl_Widget(x, y, w, h, l) {
+  type(t);
+  box(t==FL_ROUND_CLOCK ? FL_NO_BOX : FL_UP_BOX);
+  _Fl_Clock();
+}
+
+Fl_Clock::~Fl_Clock() {
+  Fl::remove_timeout(tick, this);
+}
+
+int Fl_Clock::handle(int event) {
+  switch (event) {
+  case FL_HIDE:
+    Fl::remove_timeout(tick, this);
+    break;
+  case FL_SHOW:
+    Fl::remove_timeout(tick, this);
+    tick(this);
+  }
+  return 0;
+}
diff --git a/src/Fl_Color_Chooser.cxx b/src/Fl_Color_Chooser.cxx
new file mode 100644
index 000000000..e0e2d926a
--- /dev/null
+++ b/src/Fl_Color_Chooser.cxx
@@ -0,0 +1,397 @@
+// Fl_Color_Chooser.C
+
+// Besides being a useful object on it's own, the Fl_Color_Chooser was
+// an attempt to make a complex composite object that could be easily
+// imbedded into a user interface.  If you wish to make complex objects
+// of your own, be sure to read this code.
+
+// The function fl_color_chooser() creates a window containing a color
+// chooser and a few buttons and current-color indicators.  It is an
+// easier interface for simple programs that just need a color.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+// The "hue box" can be a circle or rectilinear.
+// You get a circle by defining this:
+// #define CIRCLE 1
+// And the "hue box" can auto-update when the value changes
+// you get this by defining this:
+#define UPDATE_HUE_BOX 1
+
+void Fl_Color_Chooser::hsv2rgb(
+	double H, double S, double V, double& r, double& g, double& b) {
+  if (S < 5.0e-6) {
+    r = g = b = V;
+  } else {
+    int i = (int)H;  
+    double f = H - (float)i;
+    double p1 = V*(1.0-S);
+    double p2 = V*(1.0-S*f);
+    double p3 = V*(1.0-S*(1.0-f));
+    switch (i) {
+    case 0: r = V;   g = p3;  b = p1;  break;
+    case 1: r = p2;  g = V;   b = p1;  break;
+    case 2: r = p1;  g = V;   b = p3;  break;
+    case 3: r = p1;  g = p2;  b = V;   break;
+    case 4: r = p3;  g = p1;  b = V;   break;
+    case 5: r = V;   g = p1;  b = p2;  break;
+    }
+  }
+}
+
+void Fl_Color_Chooser::rgb2hsv(
+	double r, double g, double b, double& H, double& S, double& V) {
+  double maxv = r > g ? r : g; if (b > maxv) maxv = b;
+  V = maxv;
+  if (maxv>0) {
+    double minv = r < g ? r : g; if (b < minv) minv = b;
+    S = 1.0 - double(minv)/maxv;
+    if (maxv > minv) {
+      if (maxv == r) {H = (g-b)/double(maxv-minv); if (H<0) H += 6.0;}
+      else if (maxv == g) H = 2.0+(b-r)/double(maxv-minv);
+      else H = 4.0+(r-g)/double(maxv-minv);
+    }
+  }
+}
+
+enum {M_RGB, M_BYTE, M_HEX, M_HSV}; // modes
+static Fl_Menu_Item mode_menu[] = {
+  {"rgb"},
+  {"byte"},
+  {"hex"},
+  {"hsv"},
+  {0}
+};
+
+int Flcc_Value_Input::format(char* buf) {
+  Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent();
+  if (c->mode() == M_HEX) return sprintf(buf,"0x%02X", int(value()));
+  else return Fl_Valuator::format(buf);
+}
+
+void Fl_Color_Chooser::set_valuators() {
+  switch (mode()) {
+  case M_RGB:
+    rvalue.range(0,1); rvalue.step(1,1000); rvalue.value(r_);
+    gvalue.range(0,1); gvalue.step(1,1000); gvalue.value(g_);
+    bvalue.range(0,1); bvalue.step(1,1000); bvalue.value(b_);
+    break;
+  case M_BYTE:
+  case M_HEX:
+    rvalue.range(0,255); rvalue.step(1); rvalue.value(int(255*r_+.5));
+    gvalue.range(0,255); gvalue.step(1); gvalue.value(int(255*g_+.5));
+    bvalue.range(0,255); bvalue.step(1); bvalue.value(int(255*b_+.5));
+    break;
+  case M_HSV:
+    rvalue.range(0,6); rvalue.step(1,1000); rvalue.value(hue_);
+    gvalue.range(0,1); gvalue.step(1,1000); gvalue.value(saturation_);
+    bvalue.range(0,1); bvalue.step(1,1000); bvalue.value(value_);
+    break;
+  }
+}
+
+int Fl_Color_Chooser::rgb(double r, double g, double b) {
+  if (r == r_ && g == g_ && b == b_) return 0;
+  r_ = r; g_ = g; b_ = b;
+  double ph = hue_;
+  double ps = saturation_;
+  double pv = value_;
+  rgb2hsv(r,g,b,hue_,saturation_,value_);
+  set_valuators();
+  if (value_ != pv) {
+#ifdef UPDATE_HUE_BOX
+    huebox.damage(6);
+#endif
+    valuebox.damage(2);}
+  if (hue_ != ph || saturation_ != ps) {huebox.damage(2); valuebox.damage(6);}
+  return 1;
+}
+
+int Fl_Color_Chooser::hsv(double h, double s, double v) {
+  h = fmod(h,6.0); if (h < 0.0) h += 6.0;
+  if (s < 0.0) s = 0.0; else if (s > 1.0) s = 1.0;
+  if (v < 0.0) v = 0.0; else if (v > 1.0) v = 1.0;
+  if (h == hue_ && s == saturation_ && v == value_) return 0;
+  double ph = hue_;
+  double ps = saturation_;
+  double pv = value_;
+  hue_ = h; saturation_ = s; value_ = v;
+  if (value_ != pv) {
+#ifdef UPDATE_HUE_BOX
+    huebox.damage(6);
+#endif
+    valuebox.damage(2);}
+  if (hue_ != ph || saturation_ != ps) {huebox.damage(2); valuebox.damage(6);}
+  hsv2rgb(h,s,v,r_,g_,b_);
+  set_valuators();
+  return 1;
+}
+
+////////////////////////////////////////////////////////////////
+
+static void tohs(double x, double y, double& h, double& s) {
+#ifdef CIRCLE
+  x = 2*x-1;
+  y = 1-2*y;
+  s = sqrt(x*x+y*y); if (s > 1.0) s = 1.0;
+  h = (3.0/M_PI)*atan2(y,x);
+  if (h<0) h += 6.0;
+#else
+  h = fmod(6.0*x,6.0); if (h < 0.0) h += 6.0;
+  s = 1.0-y; if (s < 0.0) s = 0.0; else if (s > 1.0) s = 1.0;
+#endif
+}
+
+int Flcc_HueBox::handle(int e) {
+  static double ih, is;
+  Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent();
+  switch (e) {
+  case FL_PUSH:
+    ih = c->hue();
+    is = c->saturation();
+  case FL_DRAG: {
+    double Xf, Yf, H, S;
+    Xf = (Fl::event_x()-x()-Fl::box_dx(box()))/double(w()-Fl::box_dw(box()));
+    Yf = (Fl::event_y()-y()-Fl::box_dy(box()))/double(h()-Fl::box_dh(box()));
+    tohs(Xf, Yf, H, S);
+    if (fabs(H-ih) < 3*6.0/w()) H = ih;
+    if (fabs(S-is) < 3*1.0/h()) S = is;
+    if (Fl::event_state(FL_CTRL)) H = ih;
+    if (c->hsv(H, S, c->value())) c->do_callback();
+    } return 1;
+  default:
+    return 0;
+  }
+}
+
+static void generate_image(void* vv, int X, int Y, int W, uchar* buf) {
+  Flcc_HueBox* v = (Flcc_HueBox*)vv;
+  int iw = v->w()-Fl::box_dw(v->box());
+  double Yf = double(Y)/(v->h()-Fl::box_dh(v->box()));
+#ifdef UPDATE_HUE_BOX
+  const double V = ((Fl_Color_Chooser*)(v->parent()))->value();
+#else
+  const double V = 1.0;
+#endif
+  for (int x = X; x < X+W; x++) {
+    double Xf = double(x)/iw;
+    double H,S; tohs(Xf,Yf,H,S);
+    double r,g,b;
+    Fl_Color_Chooser::hsv2rgb(H,S,V,r,g,b);
+    *buf++ = uchar(255*r+.5);
+    *buf++ = uchar(255*g+.5);
+    *buf++ = uchar(255*b+.5);
+  }
+}
+
+void Flcc_HueBox::draw() {
+  if (damage()&128) draw_box();
+  int x1 = x()+Fl::box_dx(box());
+  int y1 = y()+Fl::box_dy(box());
+  int w1 = w()-Fl::box_dw(box());
+  int h1 = h()-Fl::box_dh(box());
+  if (damage() == 2) fl_clip(x1+px,y1+py,6,6);
+  fl_draw_image(generate_image, this, x1, y1, w1, h1);
+  if (damage() == 2) fl_pop_clip();
+  Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent();
+#ifdef CIRCLE
+  int X = int(.5*(cos(c->hue()*(M_PI/3.0))*c->saturation()+1) * (w1-6));
+  int Y = int(.5*(1-sin(c->hue()*(M_PI/3.0))*c->saturation()) * (h1-6));
+#else
+  int X = int(c->hue()/6.0*(w1-6));
+  int Y = int((1-c->saturation())*(h1-6));
+#endif
+  if (X < 0) X = 0; else if (X > w1-6) X = w1-6;
+  if (Y < 0) Y = 0; else if (Y > h1-6) Y = h1-6;
+  //  fl_color(c->value()>.75 ? FL_BLACK : FL_WHITE);
+  draw_box(FL_UP_BOX,x1+X,y1+Y,6,6,FL_GRAY);
+  px = X; py = Y;
+}
+
+////////////////////////////////////////////////////////////////
+
+int Flcc_ValueBox::handle(int e) {
+  static double iv;
+  Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent();
+  switch (e) {
+  case FL_PUSH:
+    iv = c->value();
+  case FL_DRAG: {
+    double Yf;
+    Yf = 1-(Fl::event_y()-y()-Fl::box_dy(box()))/double(h()-Fl::box_dh(box()));
+    if (fabs(Yf-iv)<3*1.0/h()) Yf = iv;
+    if (c->hsv(c->hue(),c->saturation(),Yf)) c->do_callback();
+    } return 1;
+  default:
+    return 0;
+  }
+}
+
+static double tr, tg, tb;
+static void generate_vimage(void* vv, int X, int Y, int W, uchar* buf) {
+  Flcc_ValueBox* v = (Flcc_ValueBox*)vv;
+  double Yf = 255*(1.0-double(Y)/(v->h()-Fl::box_dh(v->box())));
+  uchar r = uchar(tr*Yf+.5);
+  uchar g = uchar(tg*Yf+.5);
+  uchar b = uchar(tb*Yf+.5);
+  for (int x = X; x < X+W; x++) {
+    *buf++ = r; *buf++ = g; *buf++ = b;
+  }
+}
+
+void Flcc_ValueBox::draw() {
+  if (damage()&128) draw_box();
+  Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent();
+  c->hsv2rgb(c->hue(),c->saturation(),1.0,tr,tg,tb);
+  int x1 = x()+Fl::box_dx(box());
+  int y1 = y()+Fl::box_dy(box());
+  int w1 = w()-Fl::box_dw(box());
+  int h1 = h()-Fl::box_dh(box());
+  if (damage() == 2) fl_clip(x1,y1+py,w1,6);
+  fl_draw_image(generate_vimage, this, x1, y1, w1, h1);
+  if (damage() == 2) fl_pop_clip();
+  int Y = int((1-c->value()) * (h1-6));
+  if (Y < 0) Y = 0; else if (Y > h1-6) Y = h1-6;
+  draw_box(FL_UP_BOX,x1,y1+Y,w1,6,FL_GRAY);
+  py = Y;
+}
+
+////////////////////////////////////////////////////////////////
+
+void Fl_Color_Chooser::rgb_cb(Fl_Widget* o, void*) {
+  Fl_Color_Chooser* c = (Fl_Color_Chooser*)(o->parent());
+  double r = c->rvalue.value();
+  double g = c->gvalue.value();
+  double b = c->bvalue.value();
+  if (c->mode() == M_HSV) {
+    if (c->hsv(r,g,b)) c->do_callback();
+    return;
+  }
+  if (c->mode() != M_RGB) {
+    r = r/255;
+    g = g/255;
+    b = b/255;
+  }
+  if (c->rgb(r,g,b)) c->do_callback();
+}
+
+void Fl_Color_Chooser::mode_cb(Fl_Widget* o, void*) {
+  Fl_Color_Chooser* c = (Fl_Color_Chooser*)(o->parent());
+  c->set_valuators();
+}
+
+////////////////////////////////////////////////////////////////
+
+Fl_Color_Chooser::Fl_Color_Chooser(int X, int Y, int W, int H, const char* L)
+  : Fl_Group(0,0,180,100,L),
+    huebox(0,0,100,100),
+    valuebox(100,0,20,100),
+    choice(120,0,60,20),
+    rvalue(120,20,60,25),
+    gvalue(120,45,60,25),
+    bvalue(120,70,60,25),
+    resize_box(0,95,100,5)
+{
+  end();
+  resizable(resize_box);
+  resize(X,Y,W,H);
+  r_ = g_ = b_ = 0;
+  hue_ = 0.0;
+  saturation_ = 0.0;
+  value_ = 0.0;
+  huebox.box(FL_DOWN_FRAME);
+  valuebox.box(FL_DOWN_FRAME);
+  choice.menu(mode_menu);
+  set_valuators();
+  rvalue.callback(rgb_cb);
+  gvalue.callback(rgb_cb);
+  bvalue.callback(rgb_cb);
+  choice.callback(mode_cb);
+  choice.box(FL_THIN_UP_BOX);
+  choice.textfont(FL_HELVETICA_BOLD_ITALIC);
+}
+
+////////////////////////////////////////////////////////////////
+// fl_color_chooser():
+
+#include 
+#include 
+#include 
+
+class ColorChip : public Fl_Widget {
+  void draw();
+public:
+  uchar r,g,b;
+  ColorChip(int X, int Y, int W, int H) : Fl_Widget(X,Y,W,H) {
+    box(FL_ENGRAVED_FRAME);}
+};
+
+void ColorChip::draw() {
+  if (damage()&128) draw_box();
+  fl_rectf(x()+Fl::box_dx(box()),
+	   y()+Fl::box_dy(box()),
+	   w()-Fl::box_dw(box()),
+	   h()-Fl::box_dh(box()),r,g,b);
+}
+
+static void chooser_cb(Fl_Object* o, void* vv) {
+  Fl_Color_Chooser* c = (Fl_Color_Chooser*)o;
+  ColorChip* v = (ColorChip*)vv;
+  v->r = uchar(255*c->r()+.5);
+  v->g = uchar(255*c->g()+.5);
+  v->b = uchar(255*c->b()+.5);
+  v->damage(2);
+}
+
+extern const char* fl_ok;
+extern const char* fl_cancel;
+
+int fl_color_chooser(const char* name, double& r, double& g, double& b) {
+  Fl_Window window(210,165,name);
+  Fl_Color_Chooser chooser(5, 5, 200, 95);
+  ColorChip ok_color(5, 105, 95, 30);
+  Fl_Return_Button ok_button(5, 135, 95, 25, fl_ok);
+  ColorChip cancel_color(110, 105, 95, 30);
+  cancel_color.r = uchar(255*r+.5); ok_color.r = cancel_color.r;
+  ok_color.g = cancel_color.g = uchar(255*g+.5);
+  ok_color.b = cancel_color.b = uchar(255*b+.5);
+  Fl_Button cancel_button(110, 135, 95, 25, fl_cancel);
+  window.resizable(chooser);
+  chooser.rgb(r,g,b);
+  chooser.callback(chooser_cb, &ok_color);
+  window.end();
+  window.set_modal();
+  window.hotspot(window);
+  window.show();
+  while (window.shown()) {
+    Fl::wait();
+    Fl_Widget* o;
+    while ((o = Fl::readqueue())) {
+      if (o == &ok_button) {
+	r = chooser.r();
+	g = chooser.g();
+	b = chooser.b();
+	return 1;
+      }
+      if (o == &window || o == &cancel_button) return 0;
+    }
+  }
+  return 0;
+}
+
+int fl_color_chooser(const char* name, uchar& r, uchar& g, uchar& b) {
+  double dr = r/255.0;
+  double dg = g/255.0;
+  double db = b/255.0;
+  if (fl_color_chooser(name,dr,dg,db)) {
+    r = uchar(255*dr+.5);
+    g = uchar(255*dg+.5);
+    b = uchar(255*db+.5);
+    return 1;
+  }
+  return 0;
+}
diff --git a/src/Fl_Counter.cxx b/src/Fl_Counter.cxx
new file mode 100644
index 000000000..6064f99b6
--- /dev/null
+++ b/src/Fl_Counter.cxx
@@ -0,0 +1,140 @@
+// Fl_Counter.H
+
+// A numerical value with up/down step buttons.  From Forms.
+
+#include 
+#include 
+#include 
+#include  // for default_font
+
+void Fl_Counter::draw() {
+  int i; Fl_Boxtype boxtype[5];
+
+  boxtype[0] = box();
+  if (boxtype[0] == FL_UP_BOX) boxtype[0] = Fl_Input::default_box();
+  for (i=1; i<5; i++)
+    if (mouseobj == i)
+      boxtype[i] = down(box());
+    else
+      boxtype[i] = box();
+
+  int xx[5], ww[5];
+  if (type() == FL_NORMAL_COUNTER) {
+    int W = w()*15/100;
+    xx[1] = x();	 ww[1] = W;
+    xx[2] = x()+1*W;     ww[2] = W;
+    xx[0] = x()+2*W;     ww[0] = w()-4*W;
+    xx[3] = x()+w()-2*W; ww[3] = W;
+    xx[4] = x()+w()-1*W; ww[4] = W;
+  } else {
+    int W = w()*20/100;
+    xx[2] = x();	 ww[2] = W;
+    xx[0] = x()+W;	 ww[0] = w()-2*W;
+    xx[3] = x()+w()-1*W; ww[3] = W;
+  }
+
+  draw_box(boxtype[0], xx[0], y(), ww[0], h(), FL_WHITE);
+  fl_font(textfont(), textsize(),
+	  Fl_Input::default_font(), Fl_Input::default_size());
+  fl_color(active_r() ? textcolor() : inactive(textcolor()));
+  char str[128]; format(str);
+  fl_draw(str, xx[0], y(), ww[0], h(), FL_ALIGN_CENTER);
+  if (!(damage()&128)) return; // only need to redraw text
+
+  if (type() == FL_NORMAL_COUNTER) {
+    draw_box(boxtype[1], xx[1], y(), ww[1], h(), color());
+    fl_draw_symbol("@-4<<", xx[1], y(), ww[1], h(), selection_color());
+  }
+  draw_box(boxtype[2], xx[2], y(), ww[2], h(), color());
+  fl_draw_symbol("@-4<",  xx[2], y(), ww[2], h(), selection_color());
+  draw_box(boxtype[3], xx[3], y(), ww[3], h(), color());
+  fl_draw_symbol("@-4>",  xx[3], y(), ww[3], h(), selection_color());
+  if (type() == FL_NORMAL_COUNTER) {
+    draw_box(boxtype[4], xx[4], y(), ww[4], h(), color());
+    fl_draw_symbol("@-4>>", xx[4], y(), ww[4], h(), selection_color());
+  }
+}
+
+void Fl_Counter::increment_cb() {
+  if (!mouseobj) return;
+  double v = value();
+  switch (mouseobj) {
+  case 1: v -= lstep_; break;
+  case 2: v = increment(v, -1); break;
+  case 3: v = increment(v, 1); break;
+  case 4: v += lstep_; break;
+  }
+  handle_drag(clamp(round(v)));
+}
+
+#define INITIALREPEAT .5
+#define REPEAT .1
+
+void Fl_Counter::repeat_callback(void* v) {
+  Fl_Counter* b = (Fl_Counter*)v;
+  if (b->mouseobj) {
+    Fl::add_timeout(REPEAT, repeat_callback, b);
+    b->increment_cb();
+  }
+}
+
+int Fl_Counter::calc_mouseobj() {
+  if (type() == FL_NORMAL_COUNTER) {
+    int W = w()*15/100;
+    if (Fl::event_inside(x(), y(), W, h())) return 1;
+    if (Fl::event_inside(x()+W, y(), W, h())) return 2;
+    if (Fl::event_inside(x()+w()-2*W, y(), W, h())) return 3;
+    if (Fl::event_inside(x()+w()-W, y(), W, h())) return 4;
+  } else {
+    int W = w()*20/100;
+    if (Fl::event_inside(x(), y(), W, h())) return 2;
+    if (Fl::event_inside(x()+w()-W, y(), W, h())) return 3;
+  }
+  return -1;
+}
+
+int Fl_Counter::handle(int event) {
+  int i;
+  switch (event) {
+  case FL_RELEASE:
+    if (mouseobj) {
+      Fl::remove_timeout(repeat_callback, this);
+      mouseobj = 0;
+      redraw();
+    }
+    handle_release();
+    return 1;
+  case FL_PUSH:
+    handle_push();
+  case FL_DRAG:
+    i = calc_mouseobj();
+    if (i != mouseobj) {
+      Fl::remove_timeout(repeat_callback, this);
+      mouseobj = i;
+      if (i) Fl::add_timeout(INITIALREPEAT, repeat_callback, this);
+      increment_cb();
+      redraw();
+    }
+    return 1;
+  default:
+    return 0;
+  }
+}
+
+Fl_Counter::~Fl_Counter() {
+  Fl::remove_timeout(repeat_callback, this);
+}
+
+Fl_Counter::Fl_Counter(int x, int y, int w, int h, const char* l)
+  : Fl_Valuator(x, y, w, h, l) {
+  box(FL_UP_BOX);
+  selection_color(FL_INACTIVE_COLOR); // was FL_BLUE
+  align(FL_ALIGN_BOTTOM);
+  bounds(-1000000.0, 1000000.0);
+  Fl_Valuator::step(1, 10);
+  lstep_ = 1.0;
+  mouseobj = 0;
+  textfont_ = FL_HELVETICA;
+  textsize_ = FL_NORMAL_SIZE;
+  textcolor_ = FL_BLACK;
+}
diff --git a/src/Fl_Dial.cxx b/src/Fl_Dial.cxx
new file mode 100644
index 000000000..66b207180
--- /dev/null
+++ b/src/Fl_Dial.cxx
@@ -0,0 +1,113 @@
+// Fl_Dial.C
+
+// A circular dial control, like xv uses.  From Forms.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+void Fl_Dial::draw(int x, int y, int w, int h) {
+  if (damage()&128) draw_box(box(), x, y, w, h, color());
+  x += Fl::box_dx(box());
+  y += Fl::box_dy(box());
+  w -= Fl::box_dw(box());
+  h -= Fl::box_dh(box());
+  double angle = 270.0*(value()-minimum())/(maximum()-minimum());
+  if (type() == FL_FILL_DIAL) {
+    double a = angle; if (a < 0) a = 0;
+    // foo: draw this nicely in certain round box types
+    int foo = (box() > _FL_ROUND_UP_BOX && Fl::box_dx(box()));
+    if (foo) {x--; y--; w+=2; h+=2;}
+    fl_color(color());
+    fl_pie(x, y, w-1, h-1, 225, 225+360-a);
+    fl_color(selection_color());
+    fl_pie(x, y, w-1, h-1, 225-a, 225);
+    if (foo) {
+      fl_color(FL_BLACK);
+      fl_arc(x, y, w, h, 0, 360);
+    }
+    return;
+  }
+  if (!(damage()&128)) {
+    fl_color(color());
+    fl_pie(x+1, y+1, w-2, h-2, 0, 360);
+  }
+  fl_push_matrix();
+  fl_translate(x+w/2-.5, y+h/2-.5);
+  fl_scale(w-1, h-1);
+  if (type() == FL_FILL_DIAL) {
+    fl_rotate(225);
+    fl_begin_line(); fl_vertex(0, 0); fl_vertex(.5, 0); fl_end_line();
+  }
+  fl_rotate(-angle);
+  fl_color(selection_color());
+  if (type() == FL_LINE_DIAL) {
+    fl_begin_polygon();
+    fl_vertex(0.0,   0.0);
+    fl_vertex(-0.04, 0.0);
+    fl_vertex(-0.25, 0.25);
+    fl_vertex(0.0,   0.04);
+    fl_end_polygon();
+    fl_color(FL_BLACK);
+    fl_begin_loop();
+    fl_vertex(0.0,   0.0);
+    fl_vertex(-0.04, 0.0);
+    fl_vertex(-0.25, 0.25);
+    fl_vertex(0.0,   0.04);
+    fl_end_loop();
+  } else {
+    fl_begin_polygon(); fl_circle(-0.20, 0.20, 0.07); fl_end_polygon();
+    fl_color(FL_BLACK);
+    fl_begin_loop(); fl_circle(-0.20, 0.20, 0.07); fl_end_loop();
+  }
+  fl_pop_matrix();
+}
+
+void Fl_Dial::draw() {
+  draw(x(), y(), w(), h());
+  draw_label();
+}
+
+int Fl_Dial::handle(int event, int x, int y, int w, int h) {
+  switch (event) {
+  case FL_PUSH:
+    handle_push();
+  case FL_DRAG: {
+    double angle;
+    double val = value();
+    int mx = Fl::event_x()-x-w/2;
+    int my = Fl::event_y()-y-h/2;
+    if (!mx && !my) return 1;
+    if (abs(mx) > abs(my)) {
+      angle = atan(-(double)my/mx);
+      if (mx>0) angle = 1.25*M_PI - angle;
+      else angle = 0.25*M_PI - angle;
+    } else {
+      angle = atan(-(double)mx/my);
+      if (my<0) angle = 0.75*M_PI + angle;
+      else angle = -0.25*M_PI + angle;
+    }
+    if (angle<-0.25*M_PI) angle += 2.0*M_PI;
+    val = minimum() + (maximum()-minimum())*angle/(1.5*M_PI);
+    if (fabs(val-value()) < (maximum()-minimum())/2.0)
+      handle_drag(clamp(round(val)));
+    } return 1;
+  case FL_RELEASE:
+    handle_release();
+    return 1;
+  default:
+    return 0;
+  }
+}
+
+int Fl_Dial::handle(int e) {
+  return handle(e, x(), y(), w(), h());
+}
+
+Fl_Dial::Fl_Dial(int x, int y, int w, int h, const char* l)
+  : Fl_Valuator(x, y, w, h, l) {
+  box(FL_OVAL_BOX);
+  selection_color(FL_INACTIVE_COLOR); // was 37
+}
diff --git a/src/Fl_Double_Window.cxx b/src/Fl_Double_Window.cxx
new file mode 100644
index 000000000..aa285a5d2
--- /dev/null
+++ b/src/Fl_Double_Window.cxx
@@ -0,0 +1,157 @@
+// Fl_Double_Window.C
+
+// A double-buffered window.  This is achieved by using the Xdbe extension,
+// or a pixmap if that is not available.
+
+// On systems that support double buffering "naturally" the base
+// Fl_Window class will probably do double-buffer and this subclass
+// does nothing.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if USE_XDBE
+
+#include 
+
+static int use_xdbe;
+
+static int can_xdbe() {
+  static int tried;
+  if (!tried) {
+    tried = 1;
+    int event_base, error_base;
+    if (!XdbeQueryExtension(fl_display, &event_base, &error_base)) return 0;
+    Drawable root = RootWindow(fl_display,fl_screen);
+    int numscreens = 1;
+    XdbeScreenVisualInfo *a = XdbeGetVisualInfo(fl_display,&root,&numscreens);
+    if (!a) return 0;
+    for (int j = 0; j < a->count; j++)
+      if (a->visinfo[j].visual == fl_visual->visualid
+	  /*&& a->visinfo[j].perflevel > 0*/) {use_xdbe = 1; break;}
+    XdbeFreeVisualInfo(a);
+  }
+  return use_xdbe;
+}
+#endif
+
+void Fl_Double_Window::show() {
+#ifndef WIN32
+  if (!shown()) { // don't set the background pixel
+    fl_open_display();
+    Fl_X::make_xid(this);
+    return;
+  }
+#endif
+  Fl_Window::show();
+}
+
+#ifdef WIN32
+
+// Code to switch output to an off-screen window:
+// this is lame, I allow two to exist...
+
+static HDC blt_gc[2];
+
+void fl_switch_offscreen(HBITMAP bitmap) {
+  if (!blt_gc[0]) for (int i = 0; i < 2; i++) {
+    blt_gc[i] = CreateCompatibleDC(fl_gc);
+    SetTextAlign(blt_gc[i], TA_BASELINE|TA_LEFT);
+    SetBkMode(blt_gc[i], TRANSPARENT);
+#if USE_COLORMAP
+    if (fl_palette) SelectPalette(blt_gc[i], fl_palette, FALSE);
+#endif
+  }
+  int which = 0; if (fl_gc == blt_gc[0]) which = 1;
+  SelectObject(blt_gc[which], bitmap);
+  fl_gc = blt_gc[which];
+}
+
+void fl_copy_offscreen(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) {
+  int which = 0; if (fl_gc == blt_gc[0]) which = 1;
+  SelectObject(blt_gc[which], bitmap);
+  BitBlt(fl_gc, x, y, w, h, blt_gc[which], srcx, srcy, SRCCOPY);
+}
+
+#endif
+
+// protected method used by Fl_Overlay_Window to fake overlay:
+void Fl_Double_Window::_flush(int eraseoverlay) {
+  make_current(); // make sure fl_gc is non-zero
+  Fl_X *i = Fl_X::i(this);
+  if (!i->other_xid) {
+#if USE_XDBE
+    if (can_xdbe()) i->other_xid =
+      XdbeAllocateBackBufferName(fl_display, fl_xid(this), XdbeCopied);
+    else
+#endif
+      i->other_xid = fl_create_offscreen(w(), h());
+    clear_damage(~0);
+  }
+  XRectangle rect = {0,0,w(),h()};
+  if (damage()) {
+    if (i->region && !eraseoverlay) XClipBox(i->region, &rect);
+    if (	// don't draw if back buffer is ok
+#if USE_XDBE
+	use_xdbe ||
+#endif
+	damage() != 2) {
+#ifdef WIN32
+      fl_begin_offscreen(i->other_xid);
+      fl_clip_region(i->region); i->region = 0;
+      draw();
+      fl_end_offscreen();
+#else
+      fl_window = i->other_xid;
+      fl_clip_region(i->region); i->region = 0;
+      draw();
+      fl_window = i->xid;
+#endif
+    }
+  }
+  fl_clip_region(0);
+#if USE_XDBE
+  if (use_xdbe) {
+    XdbeSwapInfo s;
+    s.swap_window = fl_xid(this);
+    s.swap_action = XdbeCopied;
+    XdbeSwapBuffers(fl_display,&s,1);
+  } else
+#endif
+    fl_copy_offscreen(rect.x, rect.y, rect.width, rect.height,
+		      i->other_xid, rect.x, rect.y);
+}
+
+void Fl_Double_Window::flush() {_flush(0);}
+
+void Fl_Double_Window::resize(int X,int Y,int W,int H) {
+  int ow = w();
+  int oh = h();
+  Fl_Window::resize(X,Y,W,H);
+#if USE_XDBE
+  if (use_xdbe) return;
+#endif
+  Fl_X* i = Fl_X::i(this);
+  if (i && i->other_xid && (ow != w() || oh != h())) {
+    fl_delete_offscreen(i->other_xid);
+    i->other_xid = 0;
+  }
+}
+
+void Fl_Double_Window::hide() {
+  Fl_X* i = Fl_X::i(this);
+  if (i && i->other_xid) {
+#if USE_XDBE
+    if (!use_xdbe)
+#endif
+      fl_delete_offscreen(i->other_xid);
+  }
+  Fl_Window::hide();
+}
+
+Fl_Double_Window::~Fl_Double_Window() {
+  hide();
+}
diff --git a/src/Fl_Font.H b/src/Fl_Font.H
new file mode 100644
index 000000000..5296b9e2e
--- /dev/null
+++ b/src/Fl_Font.H
@@ -0,0 +1,63 @@
+// Fl_Font.H
+
+// Two internal fltk data structures:
+
+// Fl_Fontdesc: an entry into the fl_font() table.  This entry may contain
+// several "fonts" according to the system, for instance under X all the
+// sizes are different X fonts, but only one fl_font.
+
+// Fl_XFont: a structure for an actual system font, with junk to help
+// choose it and info on character sizes.  Each Fl_Font has a linked
+// list of these.  These are created the first time each system font
+// is used.
+
+#ifndef FL_FONT_
+#define FL_FONT_
+
+class Fl_XFont {
+public:
+  Fl_XFont *next;	// linked list of sizes of this style
+#ifndef WIN32
+  XFontStruct* font;	// X font information, 0 for display list
+  XCharStruct* per_char;// modified from XFontStruct to have 0x20-0xff in it
+  XCharStruct* free_this; // pointer saved for delete[]
+  Fl_XFont(const char*, int);
+#else
+  HFONT fid;
+  int width[256];
+  TEXTMETRIC metr;
+  Fl_XFont(const char*, int, int);
+#endif
+  int number;		// which slot in FL's font table
+  int minsize;		// smallest point size that should use this
+  int maxsize;		// largest point size that should use this
+#if HAVE_GL
+  unsigned int listbase;// base of display list, 0 = none
+#endif
+  ~Fl_XFont();
+};
+
+extern Fl_XFont *fl_current_xfont;
+extern Fl_XFont *fl_fixed_xfont;
+
+struct Fl_Fontdesc {
+  const char *name;
+  Fl_XFont *first;	// linked list of sizes of this style
+#ifndef WIN32
+  char **xlist;		// matched X font names
+  int n;		// size of xlist, negative = don't free xlist!
+#endif
+};
+
+extern Fl_Fontdesc *fl_fonts; // the table
+
+#ifndef WIN32
+// functions for parsing X font names:
+const char* fl_font_word(const char *p, int n);
+char *fl_find_fontsize(char *name);
+#endif
+
+void fl_draw(const char *, int x, int y, int w, int h, Fl_Align,
+	     void (*callthis)(const char *, int n, int x, int y));
+
+#endif
diff --git a/src/Fl_Gl_Choice.H b/src/Fl_Gl_Choice.H
new file mode 100644
index 000000000..c112559a9
--- /dev/null
+++ b/src/Fl_Gl_Choice.H
@@ -0,0 +1,57 @@
+// Internal interface to set up OpenGL.
+
+// A "Fl_Gl_Choice" is used to cache results of calling the
+// OpenGL code for system-specific information needed to
+// implement a "mode".
+// For X this is a visual, and this must be called *before*
+// the X window is created.
+// For win32 this can be delayed to a more convienent time,
+// as it only returns information for modifying a device
+// context.
+// This is used by Fl_Gl_Window, gl_start(), and gl_visual()
+
+#ifndef Fl_Gl_Choice_H
+#define Fl_Gl_Choice_H
+
+#ifdef WIN32
+# include 
+# include 
+# define GLXContext HGLRC
+# define GLX_BUFFER_SIZE      1
+# define GLX_RGBA	      2
+# define GLX_GREEN_SIZE	      3
+# define GLX_ALPHA_SIZE	      4
+# define GLX_ACCUM_GREEN_SIZE 5
+# define GLX_ACCUM_ALPHA_SIZE 6
+# define GLX_DOUBLEBUFFER     7
+# define GLX_DEPTH_SIZE	      8
+# define GLX_STENCIL_SIZE     9
+#else
+# include 
+#endif
+
+// one of these structures is returned:
+class Fl_Gl_Choice {
+  int mode;
+  const int *alist;
+  Fl_Gl_Choice *next;
+public:
+#ifdef WIN32
+  PIXELFORMATDESCRIPTOR pfd;
+#else
+  XVisualInfo *vis;	// the visual to use
+  Colormap colormap;	// a colormap to use
+#endif
+  uchar r,d,o;		// rgb mode, double buffered, overlay flags
+  // either use mode flags from gl_draw.H or a literal glX int list.
+  // one of the two arguments must be zero!
+  static Fl_Gl_Choice *find(int mode, const int *);
+};
+
+#ifdef WIN32
+// function to create and init the dc needed to draw OpenGL:
+class Fl_Window;
+HDC fl_private_dc(Fl_Window*, int, Fl_Gl_Choice **gp);
+#endif
+
+#endif
diff --git a/src/Fl_Gl_Choice.cxx b/src/Fl_Gl_Choice.cxx
new file mode 100644
index 000000000..cd5c497d7
--- /dev/null
+++ b/src/Fl_Gl_Choice.cxx
@@ -0,0 +1,157 @@
+// Internal interface to select glX visuals
+// Called by Fl_Gl_Window.C and by gl_visual() (in gl_start.C)
+
+#include 
+#if HAVE_GL
+
+#include 
+#include 
+#include 
+
+#include "Fl_Gl_Choice.H"
+
+static Fl_Gl_Choice *first;
+GLXContext fl_first_context;
+
+// this assummes one of the two arguments is zero:
+// We keep the list system in Win32 to stay compatible and interpret
+// the list later...
+Fl_Gl_Choice *Fl_Gl_Choice::find(int mode, const int *alist) {
+  Fl_Gl_Choice *g;
+  
+  for (g = first; g; g = g->next)
+    if (g->mode == mode && g->alist == alist) 
+      return g;
+
+#ifndef WIN32    
+  const int *blist;
+  int list[32];
+    
+  if (alist)
+    blist = alist;
+  else {
+    int n = 0;
+    if (mode & FL_INDEX) {
+      list[n++] = GLX_BUFFER_SIZE;
+      list[n++] = 8; // glut tries many sizes, but this should work...
+    } else {
+      list[n++] = GLX_RGBA;
+      list[n++] = GLX_GREEN_SIZE;
+      list[n++] = (mode & FL_RGB8) ? 8 : 1;
+      if (mode & FL_ALPHA) {
+	list[n++] = GLX_ALPHA_SIZE;
+	list[n++] = 1;
+      }
+      if (mode & FL_ACCUM) {
+	list[n++] = GLX_ACCUM_GREEN_SIZE;
+	list[n++] = 1;
+	if (mode & FL_ALPHA) {
+	  list[n++] = GLX_ACCUM_ALPHA_SIZE;
+	  list[n++] = 1;
+	}
+      }
+    }
+    if (mode & FL_DOUBLE) {
+      list[n++] = GLX_DOUBLEBUFFER;
+    }
+    if (mode & FL_DEPTH) {
+      list[n++] = GLX_DEPTH_SIZE; list[n++] = 1;
+    }
+    if (mode & FL_STENCIL) {
+      list[n++] = GLX_STENCIL_SIZE; list[n++] = 1;
+    }
+#if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
+    if (mode & FL_MULTISAMPLE) {
+      list[n++] = GLX_SAMPLES_SGIS;
+      list[n++] = 4; // value Glut uses
+    }
+#endif
+    list[n] = 0;
+    blist = list;
+  }
+    
+  fl_open_display();
+  XVisualInfo *vis = glXChooseVisual(fl_display, fl_screen, (int *)blist);
+  if (!vis) {
+# if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
+    if (mode&FL_MULTISAMPLE) return find(mode&~FL_MULTISAMPLE,0);
+# endif
+    return 0;
+  }
+
+#else
+
+  PIXELFORMATDESCRIPTOR pfd = { 
+    sizeof(PIXELFORMATDESCRIPTOR), 1, 
+    PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL /*| PFD_DEPTH_DONTCARE*/,
+    PFD_TYPE_RGBA, 24 };
+
+  if (mode & FL_INDEX) {
+    pfd.iPixelType = PFD_TYPE_COLORINDEX;
+    pfd.cColorBits = 8;
+  } else {
+    if (mode & FL_ALPHA) pfd.cAlphaBits = 8;
+    if (mode & FL_ACCUM) {
+      pfd.cAccumBits = 6;	// Wonko: I didn't find any documentation on those bits
+      pfd.cAccumGreenBits = 1;// Wonko: They don't seem to get anny support yet (4/98)
+      if (mode & FL_ALPHA) pfd.cAccumAlphaBits = 1;
+    }
+  }
+  if (mode & FL_DOUBLE) pfd.dwFlags |= PFD_DOUBLEBUFFER;
+  // if (!(mode & FL_DEPTH)) pfd.dwFlags = PFD_DEPTH_DONTCARE;
+  if (mode & FL_STENCIL) pfd.cStencilBits = 1;
+  pfd.bReserved = 1; // always ask for overlay
+
+#endif
+
+  g = new Fl_Gl_Choice;
+  g->mode = mode;
+  g->alist = alist;
+  g->next = first;
+  first = g;
+
+#ifdef WIN32
+  memcpy(&g->pfd, &pfd, sizeof(PIXELFORMATDESCRIPTOR));
+  g->d = ((mode&FL_DOUBLE) != 0);
+  g->r = (mode & FL_INDEX);
+  g->o = 0; // not an overlay
+#else
+  g->vis = vis;
+  g->colormap = 0;
+  int i;
+  glXGetConfig(fl_display, vis, GLX_DOUBLEBUFFER, &i); g->d = i;
+  glXGetConfig(fl_display, vis, GLX_RGBA, &i); g->r = i;
+  glXGetConfig(fl_display, vis, GLX_LEVEL, &i); g->o = i;
+
+  if (/*MaxCmapsOfScreen(ScreenOfDisplay(fl_display,fl_screen))==1 && */
+      vis->visualid == fl_visual->visualid &&
+      !getenv("MESA_PRIVATE_CMAP"))
+    g->colormap = fl_colormap;
+  else
+    g->colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen),
+				  vis->visual, AllocNone);
+#endif
+
+  return g;
+}
+
+#ifdef WIN32
+
+HDC fl_private_dc(Fl_Window* w, int mode, Fl_Gl_Choice **gp) {
+  Fl_X* i = Fl_X::i(w);
+  if (!i->private_dc) {
+    i->private_dc = GetDCEx(i->xid, 0, DCX_CACHE);
+    Fl_Gl_Choice *g = Fl_Gl_Choice::find(mode, 0);
+	if (gp) *gp = g;
+    int pixelFormat = ChoosePixelFormat(i->private_dc, &g->pfd);
+    if (!pixelFormat) {Fl::error("Insufficient GL support"); return NULL;}
+    SetPixelFormat(i->private_dc, pixelFormat, &g->pfd);
+#if USE_COLORMAP
+    if (fl_palette) SelectPalette(i->private_dc, fl_palette, FALSE);
+#endif
+  }
+  return i->private_dc;
+}
+#endif
+
+#endif
diff --git a/src/Fl_Gl_Overlay.cxx b/src/Fl_Gl_Overlay.cxx
new file mode 100644
index 000000000..cdc9583bc
--- /dev/null
+++ b/src/Fl_Gl_Overlay.cxx
@@ -0,0 +1,175 @@
+// Fl_Gl_Overlay.C
+
+// Methods on Fl_Gl_Window that create an overlay window.  Because
+// many programs don't need the overlay, this is seperated into this
+// source file so it is not linked in if not used.
+
+// Under X this is done by creating another window, of class _Fl_Gl_Overlay
+// which is a subclass of Fl_Gl_Window except it uses the overlay planes.
+// A pointer to this is stored in the "overlay" pointer of the Fl_Gl_Window.
+
+// Under win32 another GLX context is created to draw into the overlay
+// and it is stored in into the "overlay" pointer.
+
+// In both cases if overlay hardware is unavailable, the overlay is
+// "faked" by drawing into the main layers.  This is indicated by
+// setting overlay == this.
+
+#include 
+#if HAVE_GL
+
+#include 
+#include 
+#include 
+#include "Fl_Gl_Choice.H"
+#include 
+
+#if HAVE_GL_OVERLAY
+
+#ifndef WIN32
+
+extern XVisualInfo *fl_find_overlay_visual();
+extern XVisualInfo *fl_overlay_visual;
+extern Colormap fl_overlay_colormap;
+extern unsigned long fl_transparent_pixel;
+static Fl_Gl_Choice overlay_choice;
+extern uchar fl_overlay;
+
+class _Fl_Gl_Overlay : public Fl_Gl_Window {
+  void draw();
+public:
+  void show();
+  _Fl_Gl_Overlay(int x, int y, int w, int h) :
+    Fl_Gl_Window(x,y,w,h) {
+    overlay_choice.vis = fl_overlay_visual;
+    overlay_choice.colormap = fl_overlay_colormap;
+    overlay_choice.r = 0;
+    overlay_choice.d = 0;
+    overlay_choice.o = 1;
+    g = &overlay_choice;
+    deactivate();
+  }
+};
+
+void _Fl_Gl_Overlay::draw() {
+  if (damage() != 2) glClear(GL_COLOR_BUFFER_BIT);
+  Fl_Gl_Window *w = (Fl_Gl_Window *)parent();
+  uchar save_valid = w->valid_;
+  w->valid_ = valid_;
+  fl_overlay = 1;
+  w->draw_overlay();
+  fl_overlay = 0;
+  valid_ = w->valid_;
+  w->valid_ = save_valid;
+}
+
+void _Fl_Gl_Overlay::show() {
+  if (shown()) {Fl_Gl_Window::show(); return;}
+  fl_background_pixel = int(fl_transparent_pixel);
+  Fl_Gl_Window::show();
+  fl_background_pixel = -1;
+  // find the outermost window to tell wm about the colormap:
+  Fl_Window *w = window();
+  for (;;) {Fl_Window *w1 = w->window(); if (!w1) break; w = w1;}
+  XSetWMColormapWindows(fl_display, fl_xid(w), &(Fl_X::i(this)->xid), 1);
+}
+
+int Fl_Gl_Window::can_do_overlay() {
+  return fl_find_overlay_visual() != 0;
+}
+
+#else // WIN32:
+
+static int no_overlay_hardware;
+int Fl_Gl_Window::can_do_overlay() {
+  if (no_overlay_hardware) return 0;
+  // need to write a test here...
+  return 1;
+}
+
+extern GLXContext fl_first_context;
+
+#endif
+
+#else
+
+int Fl_Gl_Window::can_do_overlay() {return 0;}
+
+#endif
+
+void Fl_Gl_Window::make_overlay() {
+  if (!overlay) {
+#if HAVE_GL_OVERLAY
+#ifdef WIN32
+    if (!no_overlay_hardware) {
+      HDC hdc = fl_private_dc(this, mode_,&g);
+      GLXContext context = wglCreateLayerContext(hdc, 1);
+      if (!context) { // no overlay hardware
+	no_overlay_hardware = 1;
+      } else {
+	// copy all colors except #0 into the overlay palette:
+	COLORREF pcr[256];
+	for (int i = 0; i < 256; i++) {
+	  uchar r,g,b; Fl::get_color((Fl_Color)i,r,g,b);
+	  pcr[i] = RGB(r,g,b);
+	}
+	wglSetLayerPaletteEntries(hdc, 1, 1, 255, pcr+1);
+	wglRealizeLayerPalette(hdc, 1, TRUE);
+	if (fl_first_context) wglShareLists(fl_first_context, context);
+	else fl_first_context = context;
+	overlay = context;
+	valid(0);
+	return;
+      }
+    }
+#else
+    if (can_do_overlay()) {
+      _Fl_Gl_Overlay* o = new _Fl_Gl_Overlay(0,0,w(),h());
+      overlay = o;
+      add_resizable(*o);
+      o->show();
+      return;
+    }
+#endif
+#endif
+    overlay = this; // fake the overlay
+  }
+}
+
+void Fl_Gl_Window::redraw_overlay() {
+  if (!shown()) return;
+  make_overlay();
+#ifndef WIN32
+  if (overlay != this)
+    ((Fl_Gl_Window*)overlay)->redraw();
+  else
+#endif
+    damage(8);
+}
+
+void Fl_Gl_Window::make_overlay_current() {
+  make_overlay();
+#if HAVE_GL_OVERLAY
+  if (overlay != this) {
+#ifdef WIN32
+    wglMakeCurrent(Fl_X::i(this)->private_dc, (GLXContext)overlay);
+#else
+    Fl_Gl_Window* w = (Fl_Gl_Window*)overlay;
+    w->make_current();
+#endif
+  } else
+#endif
+    glDrawBuffer(GL_FRONT);
+}
+
+void Fl_Gl_Window::hide_overlay() {
+#if HAVE_GL_OVERLAY
+#ifdef WIN32
+  // nothing needs to be done?  Or should it be erased?
+#else
+  if (overlay && overlay!=this) ((Fl_Gl_Window*)overlay)->hide();
+#endif
+#endif
+}
+
+#endif
diff --git a/src/Fl_Gl_Window.cxx b/src/Fl_Gl_Window.cxx
new file mode 100644
index 000000000..acd08e6f3
--- /dev/null
+++ b/src/Fl_Gl_Window.cxx
@@ -0,0 +1,287 @@
+// Fl_Gl_Window.C
+
+#include 
+#if HAVE_GL
+
+#include 
+#include 
+#include 
+#include "Fl_Gl_Choice.H"
+
+////////////////////////////////////////////////////////////////
+
+// The symbol SWAP_TYPE defines what is in the back buffer after doing
+// a glXSwapBuffers().
+
+// The OpenGl documentation says that the contents of the backbuffer
+// are "undefined" after glXSwapBuffers().  However, if we know what
+// is in the backbuffers then we can save a good deal of time.  For
+// this reason you can define some symbols to describe what is left in
+// the back buffer.
+
+// The default of SWAP_SWAP works on an SGI, and will also work (but
+// is sub-optimal) on machines that should be SWAP_COPY or SWAP_NODAMAGE.
+// The win32 emulation of OpenGL can use COPY, but some (all?) OpenGL
+// cards use SWAP.
+
+// contents of back buffer after glXSwapBuffers():
+#define UNDEFINED 0 	// unknown
+#define SWAP 1		// former front buffer
+#define COPY 2		// unchanged
+#define NODAMAGE 3	// unchanged even by X expose() events
+
+#ifdef MESA
+#define SWAP_TYPE NODAMAGE
+#else
+#define SWAP_TYPE SWAP
+#endif
+
+////////////////////////////////////////////////////////////////
+
+int Fl_Gl_Window::can_do(int a, const int *b) {
+#ifdef WIN32
+  Fl_Gl_Choice *g = Fl_Gl_Choice::find(a,b);
+  HWND w = GetDesktopWindow();
+  HDC dc = GetDC(w);
+  int r = ChoosePixelFormat(dc, &g->pfd);
+  ReleaseDC(w,dc);
+  return r != 0;
+#else
+  return Fl_Gl_Choice::find(a,b) != 0;
+#endif
+}
+
+void Fl_Gl_Window::show() {
+#ifndef WIN32
+  if (!shown()) {
+    if (!g) {
+      g = Fl_Gl_Choice::find(mode_,alist);
+      if (!g) {Fl::error("Insufficient GL support"); return;}
+    }
+    Fl_X::make_xid(this, g->vis, g->colormap);
+    if (overlay && overlay != this) ((Fl_Gl_Window*)overlay)->show();
+  }
+#endif
+  Fl_Window::show();
+}
+
+void Fl_Gl_Window::invalidate() {
+  valid(0);
+#ifndef WIN32
+  if (overlay) ((Fl_Gl_Window*)overlay)->valid(0);
+#endif
+}
+
+extern GLXContext fl_first_context; // in Fl_Gl_Choice.C
+
+int Fl_Gl_Window::mode(int m, const int *a) {
+  if (m == mode_ && a == alist) return 0;
+  mode_ = m; alist = a;
+#ifdef WIN32
+  // destroy context and g:
+  if (shown()) {hide(); show();}
+#else
+  // under X, if the visual changes we must make a new X window (!):
+  if (shown()) {
+    Fl_Gl_Choice *g1 = g;
+    g = Fl_Gl_Choice::find(mode_,alist);
+    if (!g || g->vis->visualid != g1->vis->visualid || g->d != g1->d) {
+      hide(); show();
+    }
+  }
+#endif
+  return 1;
+}
+
+#ifdef WIN32
+extern char fl_direct_paint; // true when responding to WM_PAINT
+#endif
+
+void Fl_Gl_Window::make_current() {
+#ifdef WIN32
+  HDC hdc = fl_private_dc(this, mode_,&g);
+  if (!context) {
+    context = wglCreateContext(hdc);
+    if (fl_first_context) wglShareLists(fl_first_context, (GLXContext)context);
+    else fl_first_context = (GLXContext)context;
+    valid(0);
+  }
+  wglMakeCurrent(hdc, (GLXContext)context);
+#else
+  if (!context) {
+    context = glXCreateContext(fl_display, g->vis, fl_first_context, 1);
+    if (!fl_first_context) fl_first_context = (GLXContext)context;
+    valid(0);
+  }
+  glXMakeCurrent(fl_display, fl_xid(this), (GLXContext)context);
+#endif
+  glDrawBuffer(GL_BACK);
+}
+
+void Fl_Gl_Window::ortho() {
+  glLoadIdentity();
+  glViewport(0, 0, w(), h());
+  glOrtho(0, w(), 0, h(), -1, 1);
+}
+
+void Fl_Gl_Window::swap_buffers() {
+#ifdef WIN32
+  SwapBuffers(Fl_X::i(this)->private_dc);
+#else
+  glXSwapBuffers(fl_display, fl_xid(this));
+#endif
+}
+
+#if HAVE_GL_OVERLAY
+#if WIN32
+uchar fl_overlay; // changes how fl_color() works
+#endif
+#endif
+
+void Fl_Gl_Window::flush() {
+  make_current();
+
+#if HAVE_GL_OVERLAY
+#ifdef WIN32
+  uchar save_valid = valid_;
+  if (overlay && overlay!= this && damage() == 8) goto DRAW_OVERLAY_ONLY;
+#endif
+#endif
+
+  if (g->d) {
+
+#if SWAP_TYPE == NODAMAGE
+
+    // don't draw if only overlay damage or expose events:
+    if ((damage()&~0xA0) || !valid()) draw();
+    swap_buffers();
+
+#elif SWAP_TYPE == COPY
+
+    // don't draw if only the overlay is damaged:
+    if (damage() != 8 || !valid()) draw();
+    swap_buffers();
+
+#else // SWAP_TYPE == SWAP || SWAP_TYPE == UNDEFINED
+
+    if (overlay == this) { // Use CopyPixels to act like SWAP_TYPE == COPY
+
+      // don't draw if only the overlay is damaged:
+      if (damage1_ || damage() != 8 || !valid()) draw();
+      // we use a seperate context for the copy because rasterpos must be 0
+      // and depth test needs to be off:
+      static GLXContext ortho_context;
+      int init = !ortho_context;
+#ifdef WIN32
+      if (init) ortho_context = wglCreateContext(Fl_X::i(this)->private_dc);
+      wglMakeCurrent(Fl_X::i(this)->private_dc, ortho_context);
+#else
+      if (init)
+	ortho_context = glXCreateContext(fl_display,g->vis,fl_first_context,1);
+      glXMakeCurrent(fl_display, fl_xid(this), ortho_context);
+#endif
+      if (init) {
+	glDisable(GL_DEPTH_TEST);
+	glReadBuffer(GL_BACK);
+	glDrawBuffer(GL_FRONT);
+      }
+      glCopyPixels(0,0,w(),h(),GL_COLOR);
+      make_current(); // set current context back to draw overlay
+      damage1_ = 0;
+
+    } else {
+
+#if SWAP_TYPE == SWAP
+      uchar old_damage = damage();
+      clear_damage(damage1_|old_damage); draw();
+      swap_buffers();
+      damage1_ = old_damage;
+#else // SWAP_TYPE == UNDEFINED
+      clear_damage(~0); draw();
+      swap_buffers();
+      damage1_ = ~0;
+#endif
+
+    }
+#endif
+
+    if (overlay==this) { // fake overlay in front buffer
+      glDrawBuffer(GL_FRONT);
+      draw_overlay();
+      glDrawBuffer(GL_BACK);
+      glFlush();
+    }
+
+  } else {	// single-buffered context is simpler:
+
+    // this faking of the overlay is incorrect but worked good for
+    // one in-house program:
+    if (overlay != this || damage()!=8 || !Fl::pushed()) draw();
+    if (overlay == this) draw_overlay();
+    glFlush();
+
+  }
+
+#if HAVE_GL_OVERLAY
+#ifdef WIN32
+  if (overlay && overlay != this) {
+  DRAW_OVERLAY_ONLY:
+    valid_ = save_valid;
+    wglMakeCurrent(Fl_X::i(this)->private_dc, (GLXContext)overlay);
+    glDisable(GL_SCISSOR_TEST);
+    fl_overlay = 1;
+    glClear(GL_COLOR_BUFFER_BIT);
+    draw_overlay();
+    wglSwapLayerBuffers(Fl_X::i(this)->private_dc,WGL_SWAP_OVERLAY1);
+    fl_overlay = 0;
+  }
+#endif
+#endif
+
+  valid(1);
+}
+
+void Fl_Gl_Window::resize(int X,int Y,int W,int H) {
+  if (W != w() || H != h()) valid(0);
+  Fl_Window::resize(X,Y,W,H);
+}
+
+void Fl_Gl_Window::hide() {
+  if (context) {
+#ifdef WIN32
+    wglMakeCurrent(0, 0);
+    if (context && context != fl_first_context)
+      wglDeleteContext((GLXContext)context);
+    g = 0;
+#else
+    glXMakeCurrent(fl_display, 0, 0);
+    if (context != fl_first_context)
+      glXDestroyContext(fl_display, (GLXContext)context);
+#ifdef GLX_MESA_release_buffers
+    glXReleaseBuffersMESA(fl_display, fl_xid(this));
+#endif
+#endif
+    context = 0;
+  }
+  Fl_Window::hide();
+}
+
+Fl_Gl_Window::~Fl_Gl_Window() {
+  hide();
+//  delete overlay; this is done by ~Fl_Group
+}
+
+void Fl_Gl_Window::init() {
+  end(); // we probably don't want any children
+  box(FL_NO_BOX);
+  mode_ = FL_RGB | FL_DEPTH | FL_DOUBLE;
+  alist = 0;
+  context = 0;
+  g = 0;
+  overlay = 0;
+  damage1_ = 0;
+}
+
+void Fl_Gl_Window::draw_overlay() {}
+
+#endif
diff --git a/src/Fl_Group.cxx b/src/Fl_Group.cxx
new file mode 100644
index 000000000..e1a0b43ad
--- /dev/null
+++ b/src/Fl_Group.cxx
@@ -0,0 +1,443 @@
+// Fl_Group.C
+
+// The Fl_Group is the only defined container type in fltk.
+
+// Fl_Window itself is a subclass of this, and most of the event
+// handling is designed so windows themselves work correctly.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+Fl_Group* Fl_Group::current_;
+
+// Hack: A single child is stored in the pointer to the array, while
+// multiple children are stored in an allocated array:
+Fl_Widget*const* Fl_Group::array() const {
+  return children_ <= 1 ? (Fl_Widget**)(&array_) : array_;
+}
+
+int Fl_Group::find(const Fl_Widget* o) const {
+  Fl_Widget*const* a = array();
+  int i; for (i=0; i < children_; i++) if (*a++ == o) break;
+  return i;
+}
+
+extern Fl_Widget* fl_oldfocus; // set by Fl::focus
+
+// For back-compatability, we must adjust all events sent to child
+// windows so they are relative to that window.
+
+static int send(Fl_Widget* o, int event) {
+  if (o->type() < FL_WINDOW) return o->handle(event);
+  int save_x = Fl::e_x; Fl::e_x -= o->x();
+  int save_y = Fl::e_y; Fl::e_y -= o->y();
+  int ret = o->handle(event);
+  Fl::e_y = save_y;
+  Fl::e_x = save_x;
+  return ret;
+}
+
+int Fl_Group::handle(int event) {
+
+  Fl_Widget*const* a = array();
+  int i;
+  Fl_Widget* o;
+
+  switch (event) {
+
+  case FL_FOCUS:
+    if (savedfocus_ && savedfocus_->take_focus()) return 1;
+    for (i = children(); i--;) if ((*a++)->take_focus()) return 1;
+    return 0;
+
+  case FL_UNFOCUS:
+    savedfocus_ = fl_oldfocus;
+    return 0;
+
+  case FL_KEYBOARD:
+    return navigation();
+
+  case FL_SHORTCUT:
+    for (i = children(); i--;) {
+      o = a[i];
+      if (o->takesevents() && Fl::event_inside(o) && send(o,FL_SHORTCUT))
+	return 1;
+    }
+    for (i = children(); i--;) {
+      o = a[i];
+      if (o->takesevents() && !Fl::event_inside(o) && send(o,FL_SHORTCUT))
+	return 1;
+    }
+    if (Fl::event_key() == FL_Enter) return navigation(FL_Down);
+    return 0;
+
+  case FL_ENTER:
+  case FL_MOVE:
+    for (i = children(); i--;) {
+      o = a[i];
+      if (o->takesevents() && Fl::event_inside(o)) {
+	if (o->contains(Fl::belowmouse())) {
+	  return send(o,FL_MOVE);
+	} else if (send(o,FL_ENTER)) {
+	  if (!o->contains(Fl::belowmouse())) Fl::belowmouse(o);
+	  return 1;
+	}
+      }
+    }
+    Fl::belowmouse(this);
+    return 1;
+
+  case FL_PUSH:
+    for (i = children(); i--;) {
+      o = a[i];
+      if (o->takesevents() && Fl::event_inside(o)) {
+	if (send(o,FL_PUSH)) {
+	  if (Fl::pushed() && !o->contains(Fl::pushed())) Fl::pushed(o);
+	  return 1;
+	}
+      }
+    }
+    return 0;
+
+  case FL_DEACTIVATE:
+  case FL_ACTIVATE:
+    for (i = children(); i--;) {
+      o = *a++;
+      if (o->active()) o->handle(event);
+    }
+    return 1;
+
+  case FL_SHOW:
+  case FL_HIDE:
+    for (i = children(); i--;) {
+      o = *a++;
+      if (o->visible()) o->handle(event);
+    }
+    return 1;
+
+  default:
+    return 0;
+
+  }
+}
+
+// translate the current keystroke into up/down/left/right for navigation:
+#define ctrl(x) (x^0x40)
+int navkey() {
+  switch (Fl::event_key()) {
+  case FL_Tab:
+    return (Fl::event_state(FL_SHIFT) ? FL_Left : FL_Right);
+  case FL_Right:
+    return FL_Right;
+  case FL_Left:
+    return FL_Left;
+  case FL_Up:
+    return FL_Up;
+  case FL_Down:
+    return FL_Down;
+  default:
+    switch (Fl::event_text()[0]) {
+    case ctrl('N') : return FL_Down;
+    case ctrl('P') : return FL_Up;
+    case ctrl('F') : return FL_Right;
+    case ctrl('B') : return FL_Left;
+    }
+  }
+  return 0;
+}
+
+//void Fl_Group::focus(Fl_Widget *o) {Fl::focus(o); o->handle(FL_FOCUS);}
+
+#if 0
+const char *nameof(Fl_Widget *o) {
+  if (!o) return "NULL";
+  if (!o->label()) return "";
+  return o->label();
+}
+#endif
+
+// try to move the focus in response to a keystroke:
+int Fl_Group::navigation(int key) {
+  if (children() <= 1) return 0;
+  if (!key) {key = navkey(); if (!key) return 0;}
+  Fl_Widget *focus_ = Fl::focus();
+  int old_i;
+  for (old_i=0;;old_i++) {
+    if (old_i >= children_) return 0;
+    if (array_[old_i]->contains(focus_)) break;
+  }
+  int i = old_i;
+
+  for (;;) {
+    switch (key) {
+    case FL_Right:
+    case FL_Down:
+      i++; if (i >= children_) i = 0;
+      break;
+    case FL_Left:
+    case FL_Up:
+      if (i) i--; else i = children_-1;
+      break;
+    default:
+      return 0;
+    }
+    if (i == old_i) return 0;
+    Fl_Widget* o = array_[i];
+    switch (key) {
+    case FL_Down:
+    case FL_Up:
+      if (o->x() >= focus_->x()+focus_->w() ||
+	  o->x()+o->w() <= focus_->x()) continue;
+    }
+    if (o->take_focus()) return 1;
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+Fl_Group::Fl_Group(int X,int Y,int W,int H,const char *l)
+: Fl_Widget(X,Y,W,H,l) {
+  align(FL_ALIGN_TOP);
+  children_ = 0;
+  array_ = 0;
+  savedfocus_ = 0;
+  resizable_ = this;
+  sizes_ = 0; // this is allocated when first resize() is done
+  // Subclasses may want to construct child objects as part of their
+  // constructor, so make sure they are add()'d to this object.
+  // But you must end() the object!
+  begin();
+}
+
+void Fl_Group::clear() {
+  Fl_Widget*const* a = array();
+  for (int i=children(); i--;) {
+    Fl_Widget* o = *a++;
+    // test the parent to see if child already destructed:
+    if (o->parent() == this) delete o;
+  }
+  if (children() > 1) free((void*)array_);
+  children_ = 0;
+  array_ = 0;
+  savedfocus_ = 0;
+  resizable_ = this;
+  init_sizes();
+}
+
+Fl_Group::~Fl_Group() {clear();}
+
+void Fl_Group::insert(Fl_Widget &o, int i) {
+  if (o.parent()) ((Fl_Group*)(o.parent()))->remove(o);
+  o.parent_ = this;
+  if (children_ == 0) { // use array pointer to point at single child
+    array_ = (Fl_Widget**)&o;
+  } else if (children_ == 1) { // go from 1 to 2 children
+    Fl_Widget* t = (Fl_Widget*)array_;
+    array_ = (Fl_Widget**)malloc(2*sizeof(Fl_Widget*));
+    array_[!i] = t; array_[i] = &o;
+  } else {
+    if (!(children_ & (children_-1))) // double number of children
+      array_ = (Fl_Widget**)realloc((void*)array_,
+				    2*children_*sizeof(Fl_Widget*));
+    for (int j = children_; j > i; j--) array_[j] = array_[j-1];
+    array_[i] = &o;
+  }
+  children_++;
+  init_sizes();
+}
+
+void Fl_Group::add(Fl_Widget &o) {insert(o, children_);}
+
+void Fl_Group::remove(Fl_Widget &o) {
+  int i = find(o);
+  if (i >= children_) return;
+  if (&o == savedfocus_) savedfocus_ = 0;
+  o.parent_ = 0;
+  children_--;
+  if (children_ == 1) { // go from 2 to 1 child
+    Fl_Widget *t = array_[!i];
+    free((void*)array_);
+    array_ = (Fl_Widget**)t;
+  } else if (children_ > 1) { // delete from array
+    for (; i < children_; i++) array_[i] = array_[i+1];
+  }
+  init_sizes();
+}
+
+////////////////////////////////////////////////////////////////
+
+// Rather lame kludge here, I need to detect windows and ignore the
+// changes to X,Y, since all children are relative to X,Y.  That
+// is why I check type():
+
+// sizes array stores the initial positions of widgets as
+// left,right,top,bottom quads.  The first quad is the group, the
+// second is the resizable (clipped to the group), and the
+// rest are the children.  This is a convienent order for the
+// algorithim.  If you change this be sure to fix Fl_Tile which
+// also uses this array!
+
+void Fl_Group::init_sizes() {
+  delete[] sizes_; sizes_ = 0;
+}
+
+short* Fl_Group::sizes() {
+  if (!sizes_) {
+    short* p = sizes_ = new short[4*(children_+2)];
+    // first thing in sizes array is the group's size:
+    if (type() < FL_WINDOW) {p[0] = x(); p[2] = y();} else {p[0] = p[2] = 0;}
+    p[1] = p[0]+w(); p[3] = p[2]+h();
+    // next is the resizable's size:
+    p[4] = p[0]; // init to the group's size
+    p[5] = p[1];
+    p[6] = p[2];
+    p[7] = p[3];
+    Fl_Widget* r = resizable();
+    if (r && r != this) { // then clip the resizable to it
+      int t;
+      t = r->x(); if (t > p[0]) p[4] = t;
+      t +=r->w(); if (t < p[1]) p[5] = t;
+      t = r->y(); if (t > p[2]) p[6] = t;
+      t +=r->h(); if (t < p[3]) p[7] = t;
+    }
+    // next is all the children's sizes:
+    p += 8;
+    Fl_Widget*const* a = array();
+    for (int i=children_; i--;) {
+      Fl_Widget* o = *a++;
+      *p++ = o->x();
+      *p++ = o->x()+o->w();
+      *p++ = o->y();
+      *p++ = o->y()+o->h();
+    }
+  }
+  return sizes_;
+}
+
+void Fl_Group::resize(int X, int Y, int W, int H) {
+
+  if (!resizable() || W==w() && H==h()) {
+
+    if (type() < FL_WINDOW) {
+      int dx = X-x();
+      int dy = Y-y();
+      Fl_Widget*const* a = array();
+      for (int i=children_; i--;) {
+	Fl_Widget* o = *a++;
+	o->resize(o->x()+dx, o->y()+dy, o->w(), o->h());
+      }
+    }
+
+  } else if (children_) {
+
+    short* p = sizes();
+
+    // get changes in size/position from the initial size:
+    int dx = X - p[0];
+    int dw = W - (p[1]-p[0]);
+    int dy = Y - p[2];
+    int dh = H - (p[3]-p[2]);
+    if (type() >= FL_WINDOW) dx = dy = 0;
+    p += 4;
+
+    // get initial size of resizable():
+    int IX = *p++;
+    int IR = *p++;
+    int IY = *p++;
+    int IB = *p++;
+
+    Fl_Widget*const* a = array();
+    for (int i=children_; i--;) {
+      Fl_Widget* o = *a++;
+
+      int X = *p++;
+      if (X >= IR) X += dw;
+      else if (X > IX) X = IX+((X-IX)*(IR+dw-IX)+(IR-IX)/2)/(IR-IX);
+      int R = *p++;
+      if (R >= IR) R += dw;
+      else if (R > IX) R = IX+((R-IX)*(IR+dw-IX)+(IR-IX)/2)/(IR-IX);
+
+      int Y = *p++;
+      if (Y >= IB) Y += dh;
+      else if (Y > IY) Y = IY+((Y-IY)*(IB+dh-IY)+(IB-IY)/2)/(IB-IY);
+      int B = *p++;
+      if (B >= IB) B += dh;
+      else if (B > IY) B = IY+((B-IY)*(IB+dh-IY)+(IB-IY)/2)/(IB-IY);
+
+      o->resize(X+dx, Y+dy, R-X, B-Y);
+    }
+  }
+
+  Fl_Widget::resize(X,Y,W,H);
+}
+
+void Fl_Group::draw() {
+  Fl_Widget*const* a = array();
+  if (damage() & ~1) { // redraw the entire thing:
+    draw_box();
+    draw_label();
+    for (int i=children_; i--;) {
+      Fl_Widget& o = **a++;
+      draw_child(o);
+      draw_outside_label(o);
+    }
+  } else {	// only redraw the children that need it:
+    for (int i=children_; i--;) update_child(**a++);
+  }
+}
+
+// Draw a child only if it needs it:
+void Fl_Group::update_child(Fl_Widget& w) const {
+  if (w.damage() && w.visible() && w.type() < FL_WINDOW &&
+      fl_not_clipped(w.x(), w.y(), w.w(), w.h())) {
+    w.draw();	
+    w.clear_damage();
+  }
+}
+
+// Force a child to redraw:
+void Fl_Group::draw_child(Fl_Widget& w) const {
+  if (w.visible() && w.type() < FL_WINDOW &&
+      fl_not_clipped(w.x(), w.y(), w.w(), w.h())) {
+    w.clear_damage(~0);
+    w.draw();
+    w.clear_damage();
+  }
+}
+
+extern char fl_draw_shortcut;
+
+// Parents normally call this to draw outside labels:
+void Fl_Group::draw_outside_label(const Fl_Widget& w) const {
+  if (!w.visible()) return;
+  // skip any labels that are inside the widget:
+  if (!(w.align()&15) || (w.align() & FL_ALIGN_INSIDE)) return;
+  // invent a box that is outside the widget:
+  int align = w.align();
+  int X = w.x();
+  int Y = w.y();
+  int W = w.w();
+  int H = w.h();
+  if (align & FL_ALIGN_TOP) {
+    align ^= (FL_ALIGN_BOTTOM|FL_ALIGN_TOP);
+    Y = y();
+    H = w.y()-Y;
+  } else if (align & FL_ALIGN_BOTTOM) {
+    align ^= (FL_ALIGN_BOTTOM|FL_ALIGN_TOP);
+    Y = Y+H;
+    H = y()+h()-Y;
+  } else if (align & FL_ALIGN_LEFT) {
+    align ^= (FL_ALIGN_LEFT|FL_ALIGN_RIGHT);
+    X = x();
+    W = w.x()-X-3;
+  } else if (align & FL_ALIGN_RIGHT) {
+    align ^= (FL_ALIGN_LEFT|FL_ALIGN_RIGHT);
+    X = X+W+3;
+    W = x()+this->w()-X;
+  }
+  w.draw_label(X,Y,W,H,(Fl_Align)align);
+}
+
diff --git a/src/Fl_Image.cxx b/src/Fl_Image.cxx
new file mode 100644
index 000000000..1aac860d4
--- /dev/null
+++ b/src/Fl_Image.cxx
@@ -0,0 +1,62 @@
+// Fl_Image.C
+
+// Draw a image in a box.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+void Fl_Image::draw(int X, int Y, int W, int H, int cx,int cy) {
+  // clip the box down to the size of image, quit if empty:
+  if (cx < 0) {W += cx; X -= cx; cx = 0;}
+  if (cx+W > w) W = w-cx;
+  if (W <= 0) return;
+  if (cy < 0) {H += cy; Y -= cy; cy = 0;}
+  if (cy+H > h) H = h-cy;
+  if (H <= 0) return;
+  if (!id) {
+    id = (ulong)fl_create_offscreen(w, h);
+    fl_begin_offscreen((Fl_Offscreen)id);
+    fl_draw_image(array, 0, 0, w, h, d, ld);
+    fl_end_offscreen();
+  }
+  fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy);
+}
+
+Fl_Image::~Fl_Image() {
+  if (id) fl_delete_offscreen((Fl_Offscreen)id);
+}
+
+static void image_labeltype(
+    const Fl_Label* o, int x, int y, int w, int h, Fl_Align a)
+{
+  Fl_Image* b = (Fl_Image*)(o->value);
+  int cx;
+  if (a & FL_ALIGN_LEFT) cx = 0;
+  else if (a & FL_ALIGN_RIGHT) cx = b->w-w;
+  else cx = (b->w-w)/2;
+  int cy;
+  if (a & FL_ALIGN_TOP) cy = 0;
+  else if (a & FL_ALIGN_BOTTOM) cy = b->h-h;
+  else cy = (b->h-h)/2;
+  b->draw(x,y,w,h,cx,cy);
+}
+
+static void image_measure(const Fl_Label* o, int& w, int& h) {
+  Fl_Image* b = (Fl_Image*)(o->value);
+  w = b->w;
+  h = b->h;
+}
+
+void Fl_Image::label(Fl_Widget* o) {
+  Fl::set_labeltype(_FL_IMAGE_LABEL, image_labeltype, image_measure);
+  o->label(_FL_IMAGE_LABEL, (const char*)this);
+}
+
+void Fl_Image::label(Fl_Menu_Item* o) {
+  Fl::set_labeltype(_FL_IMAGE_LABEL, image_labeltype, image_measure);
+  o->label(_FL_IMAGE_LABEL, (const char*)this);
+}
diff --git a/src/Fl_Input.cxx b/src/Fl_Input.cxx
new file mode 100644
index 000000000..34dfce1b9
--- /dev/null
+++ b/src/Fl_Input.cxx
@@ -0,0 +1,299 @@
+// Fl_Input.C
+
+// This is the "user interface", it decodes user actions into what to
+// do to the text.  See also Fl_Input_.C, where the text is actually
+// manipulated (and some ui, in particular the mouse, is done...).
+// In theory you can replace this code with another subclass to change
+// the keybindings.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+void Fl_Input::draw() {
+  if (type() == FL_HIDDEN_INPUT) return;
+  Fl_Boxtype b = box() ? box() : default_box();
+  if (damage() & 128) draw_box(b, color());
+  Fl_Input_::drawtext(x()+Fl::box_dx(b)+3, y()+Fl::box_dy(b),
+		      w()-Fl::box_dw(b)-6, h()-Fl::box_dh(b));
+}
+
+// kludge so shift causes selection to extend:
+int Fl_Input::shift_position(int p) {
+  return position(p, Fl::event_state(FL_SHIFT) ? mark() : p);
+}
+int Fl_Input::shift_up_down_position(int p) {
+  return up_down_position(p, Fl::event_state(FL_SHIFT));
+}
+
+////////////////////////////////////////////////////////////////
+// Fltk "compose"
+// I tried to do compose characters "correctly" with much more user
+// feedback.  They can see the character they will get, rather than
+// the "dead key" effect.  Notice that I completely ignore that horrid
+// XIM extension!
+// Although the current scheme only works for Latin-NR1 character sets
+// the intention is to expand this to UTF-8 someday, to allow you to
+// compose all characters in all languages with no stupid "locale"
+// setting.
+// To use, you call "fl_compose()" for each keystroke.  You pass it
+// the characters it displayed last time plus the new character.  It
+// returns a new set of characters to replace the old one with.  If
+// it returns zero length you should leave the old set unchanged and
+// treat the new key normally.
+// Pressing any function keys or moving the cursor should set the
+// compose state back to zero.
+
+// This string lists a pair for each possible foreign letter in Latin-NR1
+// starting at code 0xa0 (nbsp).  If the second character is a space then
+// only the first character needs to by typed:
+static const char* const compose_pairs =
+"  ! % # $ y=| & : c a <<~ - r _ * +-2 3 ' u p . , 1 o >>141234? "
+"A`A'A^A~A:A*AEC,E`E'E^E:I`I'I^I:D-N~O`O'O^O~O:x O/U`U'U^U:Y'DDss"
+"a`a'a^a~a:a*aec,e`e'e^e:i`i'i^i:d-n~o`o'o^o~o:-:o/u`u'u^u:y'ddy:";
+
+int fl_compose(int state, char c, int& del, char* buffer, int& ins) {
+  del = 0; ins = 1; buffer[0] = c;
+
+  if (c == '"') c = ':';
+
+  if (!state) {	// first character
+    if (c == ' ') {buffer[0]=char(0xA0);return 0x100;} // space turns into nbsp
+    // see if it is either character of any pair:
+    state = 0;
+    for (const char *p = compose_pairs; *p; p += 2) 
+      if (p[0] == c || p[1] == c) {
+	if (p[1] == ' ') buffer[0] = (p-compose_pairs)/2+0xA0;
+	state = c;
+      }
+    return state;
+
+  } else if (state == 0x100) { // third character
+    return 0;
+
+  } else { // second character
+    char c1 = char(state); // first character
+    // now search for the pair in either order:
+    for (const char *p = compose_pairs; *p; p += 2) {
+      if (p[0] == c && p[1] == c1 || p[1] == c && p[0] == c1) {
+	buffer[0] = (p-compose_pairs)/2+0xA0;
+	ins = del = 1;
+	return 0x100;
+      }
+    }
+    return 0;
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+static int compose; // compose state (# of characters so far + 1)
+
+// If you define this symbol as zero you will get the peculiar fltk
+// behavior where moving off the end of an input field will move the
+// cursor into the next field:
+// define it as 1 to prevent cursor movement from going to next field:
+#define NORMAL_INPUT_MOVE 0
+
+#define ctrl(x) (x^0x40)
+
+int Fl_Input::handle_key() {
+  int i;
+
+  int pcompose = compose; compose = 0;
+  char key = Fl::event_text()[0];
+
+  if (pcompose && Fl::event_length()) {
+    char buf[20]; int ins; int del;
+    compose = fl_compose(pcompose-1, key, del, buf, ins);
+    if (compose) {
+      replace(position(), del ? position()-del : mark(), buf, ins);
+      compose++; // store value+1 so 1 can initialize compose state
+      return 1;
+    } else {
+      if (pcompose==1)	// compose also acts as quote-next:
+	return replace(position(),mark(),Fl::event_text(),Fl::event_length());
+    }
+  }
+
+  if (Fl::event_state(FL_ALT|FL_META)) { // reserved for shortcuts
+    compose = pcompose;
+    return 0;
+  }
+
+  switch (Fl::event_key()) {
+  case FL_Left:
+    key = ctrl('B'); break;
+  case FL_Right:
+    key = ctrl('F'); break;
+  case FL_Up:
+    key = ctrl('P'); break;
+  case FL_Down:
+    key = ctrl('N'); break;
+  case FL_Delete:
+    key = ctrl('D'); break;
+  case FL_Home:
+    key = ctrl('A'); break;
+  case FL_End:
+    key = ctrl('E'); break;
+  case FL_BackSpace:
+    if (mark() != position()) cut();
+    else cut(-1);
+    return 1;
+  case FL_Enter:
+  case FL_KP_Enter:
+    if (when() & FL_WHEN_ENTER_KEY) {
+      position(size(), 0);
+      maybe_do_callback();
+      return 1;
+    } else if (type() == FL_MULTILINE_INPUT)
+      return replace(position(), mark(), "\n", 1);
+    else 
+      return 0;	// reserved for shortcuts
+  case FL_Tab:
+    if (Fl::event_state(FL_CTRL) || type()!=FL_MULTILINE_INPUT) return 0;
+    break;
+  case FL_Escape:
+    return 0;	// reserved for shortcuts (Forms cleared field)
+  case FL_Control_R:
+  case 0xff20: // Multi-Key
+    compose = 1;
+    return 1;
+  }
+
+  switch(key) {
+  case 0:	// key did not translate to any text
+    compose = pcompose; // allow user to hit shift keys after ^Q
+    return 0;
+  case ctrl('A'):
+    if (type() == FL_MULTILINE_INPUT)
+      for (i=position(); i && index(i-1)!='\n'; i--) ;
+    else
+      i = 0;
+    return shift_position(i) + NORMAL_INPUT_MOVE;
+  case ctrl('B'):
+    return shift_position(position()-1) + NORMAL_INPUT_MOVE;
+  case ctrl('C'): // copy
+    return copy();
+  case ctrl('D'):
+    if (mark() != position()) return cut();
+    else return cut(1);
+  case ctrl('E'):
+    if (type() == FL_MULTILINE_INPUT)
+      for (i=position(); index(i) && index(i)!='\n'; i++) ;
+    else
+      i = size();
+    return shift_position(i) + NORMAL_INPUT_MOVE;
+  case ctrl('F'):
+    return shift_position(position()+1) + NORMAL_INPUT_MOVE;
+  case ctrl('K'):
+    if (position()>=size()) return 0;
+    if (type() == FL_MULTILINE_INPUT) {
+      if (index(position()) == '\n')
+	i = position() + 1;
+      else 
+	for (i=position()+1; index(i) && index(i) != '\n'; i++);
+    } else
+      i = size();
+    cut(position(), i);
+    return copy_cuts();
+  case ctrl('N'):
+    if (type()!=FL_MULTILINE_INPUT) return 0;
+    for (i=position(); index(i)!='\n'; i++)
+      if (!index(i)) return NORMAL_INPUT_MOVE;
+    shift_up_down_position(i+1);
+    return 1;
+  case ctrl('P'):
+    if (type()!=FL_MULTILINE_INPUT) return 0;
+    for (i = position(); i > 0 && index(i-1) != '\n'; i--) ;
+    if (!i) return NORMAL_INPUT_MOVE;
+    shift_up_down_position(i-1);
+    return 1;
+  case ctrl('Q'):
+    compose = 1;
+    return 1;
+  case ctrl('U'):
+    return cut(0, size());
+  case ctrl('V'):
+  case ctrl('Y'):
+    Fl::paste(*this);
+    return 1;
+  case ctrl('X'):
+  case ctrl('W'):
+    copy();
+    return cut();
+  case ctrl('Z'):
+  case ctrl('_'):
+    return undo();
+  }
+
+  // skip all illegal characters
+  // this could be improved to make sure characters are inserted at
+  // legal positions...
+  if (type() == FL_FLOAT_INPUT) {
+    if (!strchr("0123456789.eE+-", key)) return 0;
+  } else if (type() == FL_INT_INPUT) {
+    if (!strchr("0123456789+-", key)) return 0;
+  }
+
+  return replace(position(), mark(), Fl::event_text(), Fl::event_length());
+}
+
+int Fl_Input::handle(int event) {
+  switch (event) {
+
+  case FL_FOCUS:
+    switch (Fl::event_key()) {
+    case FL_Right:
+      position(0);
+      break;
+    case FL_Left:
+      position(size());
+      break;
+    case FL_Down:
+      up_down_position(0);
+      break;
+    case FL_Up:
+      up_down_position(size());
+      break;
+    case FL_Tab:
+      position(size(),0);
+      break;
+    }
+    break;
+
+  case FL_UNFOCUS:
+    compose = 0;
+    break;
+
+  case FL_KEYBOARD:
+    return handle_key();
+
+  case FL_PUSH:
+    compose = 0;
+    if (Fl::event_button() == 2) {
+      Fl::paste(*this);
+      if (Fl::focus()==this) return 1; // remove line for Motif behavior
+    }
+    if (Fl::focus() != this) {
+      Fl::focus(this);
+      handle(FL_FOCUS); // cause minimal update
+    }
+    break;
+
+  case FL_DRAG:
+  case FL_RELEASE:
+    if (Fl::event_button() == 2) return 0;
+    break;
+  }
+  Fl_Boxtype b = box() ? box() : default_box();
+  return Fl_Input_::handletext(event,
+	x()+Fl::box_dx(b)+3, y()+Fl::box_dy(b),
+	w()-Fl::box_dw(b)-6, h()-Fl::box_dh(b));
+}
+
+Fl_Input::Fl_Input(int x, int y, int w, int h, const char *l)
+: Fl_Input_(x, y, w, h, l) {}
diff --git a/src/Fl_Input_.cxx b/src/Fl_Input_.cxx
new file mode 100644
index 000000000..a04d3cef2
--- /dev/null
+++ b/src/Fl_Input_.cxx
@@ -0,0 +1,704 @@
+// Fl_Input_.C
+
+// This is the base class for Fl_Input.  You can use it directly
+// if you are one of those people who like to define their own
+// set of editing keys.  It may also be useful for adding scrollbars
+// to the input field.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MAXBUF 1024
+
+////////////////////////////////////////////////////////////////
+
+// Copy string p..e to the buffer, replacing characters with ^X and \nnn
+// as necessary.  Truncate if necessary so the resulting string and
+// null terminator fits in a buffer of size n.  Return new end pointer.
+const char* Fl_Input_::expand(const char* p, char* buf) const {
+  char* o = buf;
+  char* e = buf+(MAXBUF-4);
+  if (type()==FL_SECRET_INPUT) {
+    while (o= value_+size_) break;
+    int c = *p++ & 255;
+    if (c < ' ' || c == 127) {
+      if (c=='\n' && type()==FL_MULTILINE_INPUT) {p--; break;}
+      if (c == '\t' && type()==FL_MULTILINE_INPUT) {
+	for (c = (o-buf)%8; c<8 && o= 128 && c < 0xA0) {
+      *o++ = '\\';
+      *o++ = (c>>6)+'0';
+      *o++ = ((c>>3)&7)+'0';
+      *o++ = (c&7)+'0';
+    } else if (c == 0xA0) { // nbsp
+      *o++ = ' ';
+    } else {
+      *o++ = c;
+    }
+  }
+  *o = 0;
+  return p;
+}
+
+// After filling in such a buffer, find the width to e
+double Fl_Input_::expandpos(
+  const char* p,	// real string
+  const char* e,	// pointer into real string
+  const char* buf,	// conversion of real string by expand()
+  int* returnn		// return offset into buf here
+) const {
+  int n = 0;
+  if (type()==FL_SECRET_INPUT) n = e-p;
+  else while (p= 128 && c < 0xA0) {
+      n += 4;
+    } else {
+      n++;
+    }
+  }
+  if (returnn) *returnn = n;
+  return fl_width(buf, n);
+}
+
+////////////////////////////////////////////////////////////////
+
+// minimal update:
+// Characters from mu_p to end of widget are redrawn.
+// If erase_cursor_only, small part at mu_p is redrawn.
+// Right now minimal update just keeps unchanged characters from
+// being erased, so they don't blink.
+
+void Fl_Input_::minimal_update(int p) {
+  if (damage() & 128) return; // don't waste time if it won't be done
+  if (damage() & 2) {
+    if (p < mu_p) mu_p = p;
+  } else {
+    mu_p = p;
+  }
+  damage(2);
+  erase_cursor_only = 0;
+}
+
+void Fl_Input_::minimal_update(int p, int q) {
+  if (q < p) p = q;
+  minimal_update(p);
+}
+
+////////////////////////////////////////////////////////////////
+
+static double up_down_pos;
+static int was_up_down;
+
+void Fl_Input_::setfont() const {
+ fl_font(textfont(), textsize(), default_font(), default_size());
+}
+
+void Fl_Input_::drawtext(int X, int Y, int W, int H) {
+
+  int do_mu = !(damage()&128);
+  if (Fl::focus()!=this && !size()) {
+    if (do_mu) { // we have to erase it if cursor was there
+      fl_color(color());
+      fl_rectf(X, Y, W, H);
+    }
+    return;
+  }
+
+  int selstart, selend;
+  if (Fl::focus()!=this && Fl::selection_owner()!=this && Fl::pushed()!=this)
+    selstart = selend = 0;
+  else if (position() <= mark()) {
+    selstart = position(); selend = mark();
+  } else {
+    selend = position(); selstart = mark();
+  }
+
+  setfont();
+
+#if 0	// patch to do auto-wrap written by Ian West
+  if ((type()==FL_MULTILINE_INPUT) && (value_==buffer) && (bufsize>=size_)) {
+    int wwidth = W-10;
+    int strtofln=0,lastsp=0,idx=0,lastbr=0;
+    while(idx <= size_){
+      if((buffer[idx] <= ' ') || (idx == size_)) {
+	if(buffer[idx] == '\n') lastbr=idx;
+	buffer[idx]=' ';
+	int twidth=(int)fl_width(&buffer[strtofln],idx-strtofln);
+	if ((twidth >= wwidth) && (lastsp > strtofln)) {
+//	printf(stderr,"Line break, lastsp=%d, idx=%d, strtofln=%d, lastbr=%d\n",lastsp,idx,strtofln,lastbr);
+	  buffer[lastsp]='\n';
+	  if (lastsp != lastbr) {
+	    if (lastsp < mu_p){
+	      mu_p=lastsp;
+	      erase_cursor_only = 0;
+	    }
+	  }
+	  strtofln=lastsp+1; 
+	} else {
+	  lastsp=idx;
+	}
+      }
+      idx++;
+    }
+//  fprintf(stderr,"Line length %d %d %d\n",(int)fl_width(buffer),size_, mu_p);
+//  if(xscroll_ > 0) {xscroll_=0; mu_p=0;}
+    buffer[size_] = 0;
+  }
+#endif
+
+  const char *p, *e;
+  char buf[MAXBUF];
+
+  // count how many lines and put the last one into the buffer:
+  // And figure out where the cursor is:
+  int height = fl_height();
+  int lines;
+  int curx, cury;
+  for (p=value(), curx=cury=lines=0; ;) {
+    e = expand(p, buf);
+    if (position() >= p-value() && position() <= e-value()) {
+      curx = int(expandpos(p, value()+position(), buf, 0)+.5);
+      if (Fl::focus()==this && !was_up_down) up_down_pos = curx;
+      cury = lines*height;
+      if (Fl::focus()==this) {
+	int fullw = int(expandpos(p, e, buf, 0));
+	if (curx > xscroll_+W-20) {
+	  xscroll_ = curx+20-W;
+	  if (xscroll_ > fullw-W+2) xscroll_ = fullw-W+2;
+	  mu_p = 0; erase_cursor_only = 0;
+	}
+	if (curx < xscroll_+20 && xscroll_) {
+	  if (fullw > W-2) xscroll_ = curx-20;
+	  else xscroll_ = 0;
+	  mu_p = 0; erase_cursor_only = 0;
+	}
+	if (xscroll_ < 0) xscroll_ = 0;
+      }
+    }
+    lines++;
+    if (e >= value_+size_) break;
+    if (*e == '\n') e++;
+    p = e;
+  }
+
+  // adjust the scrolling:
+  if (type()==FL_MULTILINE_INPUT) {
+    int newy = yscroll_;
+    if (cury < newy) newy = cury;
+    if (cury > newy+H-height) newy = cury-H+height;
+    if (newy < -1) newy = -1;
+    if (newy != yscroll_) {yscroll_ = newy; mu_p = 0; erase_cursor_only = 0;}
+  } else {
+    yscroll_ = -(H-height)/2;
+  }
+
+  fl_clip(X, Y, W, H);
+  Fl_Color color = active_r() ? textcolor() : inactive(textcolor());
+
+  p = value();
+  // visit each line and draw it:
+  int desc = height-fl_descent();
+  int ypos = -yscroll_;
+  for (; ypos < H;) {
+
+    // re-expand line unless it is the last one calculated above:
+    if (lines>1) e = expand(p, buf);
+
+    if (ypos <= -height) goto CONTINUE; // clipped off top
+
+    if (do_mu) {	// for minimal update:
+      const char* pp = value()+mu_p; // pointer to where minimal update starts
+      if (e >= pp && (!erase_cursor_only || p <= pp)) { // we must erase this
+	// calculate area to erase:
+	int x1 = -xscroll_;
+	if (p < pp) x1 += int(expandpos(p, pp, buf, 0));
+	// erase it:
+	fl_color(this->color());
+	fl_rectf(X+x1, Y+ypos, erase_cursor_only?2:W-x1, height);
+	// it now draws entire line over it
+	// this should not draw letters to left of erased area, but
+	// that is nyi.
+      }
+    }
+
+    // Draw selection area if required:
+    if (selstart < selend && selstart <= e-value() && selend > p-value()) {
+      const char* pp = value()+selstart;
+      int x1 = -xscroll_;
+      int offset1 = 0;
+      if (pp > p) {
+	fl_color(color);
+	x1 += int(expandpos(p, pp, buf, &offset1));
+	fl_draw(buf, offset1, X-xscroll_, Y+ypos+desc);
+      }
+      pp = value()+selend;
+      int x2 = W;
+      int offset2;
+      if (pp <= e) x2 = int(expandpos(p, pp, buf, &offset2))-xscroll_;
+      else offset2 = strlen(buf);
+      fl_color(selection_color());
+      fl_rectf(X+int(x1+.5), Y+ypos, int(x2-x1), height);
+      fl_color(contrast(textcolor(), selection_color()));
+      fl_draw(buf+offset1, offset2-offset1, X+x1, Y+ypos+desc);
+      if (pp < e) {
+	fl_color(color);
+	fl_draw(buf+offset2, X+x2, Y+ypos+desc);
+      }
+    } else {
+      // draw the cursor:
+      if (Fl::focus() == this && selstart == selend &&
+	  position() >= p-value() && position() <= e-value()) {
+	fl_color(cursor_color());
+	fl_rectf(X+curx-xscroll_, Y+ypos, 2, height);
+      }
+      fl_color(color);
+      fl_draw(buf, X-xscroll_, Y+ypos+desc);
+    }
+  CONTINUE:
+    ypos += height;
+    if (e >= value_+size_) break;
+    if (*e == '\n') e++;
+    p = e;
+  }
+
+  // for minimal update, erase all lines below last one if necessary:
+  if (type()==FL_MULTILINE_INPUT && do_mu && yposcolor());
+    fl_rectf(X, Y+ypos, W, H-ypos);
+  }
+
+  fl_pop_clip();
+}
+
+static int isword(char c) {
+  return (c&128 || isalnum(c) || strchr("#%&-/@\\_~", c));
+}
+
+int Fl_Input_::wordboundary(int i) const {
+  if (i<=0 || i>=size()) return 1;
+  return isword(index(i-1)) != isword(index(i));
+}
+
+int Fl_Input_::lineboundary(int i) const {
+  if (i<=0 || i>=size()) return 1;
+  if (type() != FL_MULTILINE_INPUT) return 0;
+  return index(i-1) == '\n' || index(i) == '\n';
+}
+
+void Fl_Input_::handle_mouse(int X, int Y, int /*W*/, int /*H*/, int drag) {
+  was_up_down = 0;
+  if (!size()) return;
+  setfont();
+
+  const char *p, *e;
+  char buf[MAXBUF];
+
+  int theline = (type()==FL_MULTILINE_INPUT) ?
+    (Fl::event_y()-Y+yscroll_)/fl_height() : 0;
+
+  int newpos = 0;
+  for (p=value();; ) {
+    e = expand(p, buf);
+    theline--; if (theline < 0) break;
+    if (*e == '\n') e++;
+    p = e;
+    if (e >= value_+size_) break;
+  }
+  const char *l, *r, *t;
+  for (l = p, r = e; l= newmark) {
+      if (newpos == newmark) {
+	if (newpos < size()) newpos++;
+	else newmark--;
+      }
+      if (Fl::event_clicks()>1) {
+	while (!lineboundary(newpos)) newpos++;
+	while (!lineboundary(newmark)) newmark--;
+      } else {
+	while (!wordboundary(newpos)) newpos++;
+	while (!wordboundary(newmark)) newmark--;
+      }
+    } else {
+      if (Fl::event_clicks()>1) {
+	while (!lineboundary(newpos)) newpos--;
+      } else {
+	while (!wordboundary(newpos)) newpos--;
+      }
+    }
+  }
+  position(newpos, newmark);
+}
+
+int Fl_Input_::position(int p, int m) {
+  was_up_down = 0;
+  if (p<0) p = 0;
+  if (p>size()) p = size();
+  if (m<0) m = 0;
+  if (m>size()) m = size();
+  if (p == position_ && m == mark_) return 0;
+  if (Fl::selection_owner() == this) Fl::selection_owner(0);
+  if (p != m) {
+    // new position is a selection
+    if (Fl::focus()==this || Fl::pushed()==this) {
+      if (p != position_) minimal_update(position_, p);
+      if (m != mark_) minimal_update(mark_, m);
+    }
+  } else if (Fl::focus() == this) {
+    // new position is a cursor
+    if (position_ == mark_) {
+      // old position was just a cursor
+      if (!(damage()&2)) {
+	minimal_update(position_); erase_cursor_only = 1;
+      }
+    } else { // old position was a selection
+      minimal_update(position_, mark_);
+    }
+  }
+  position_ = p;
+  mark_ = m;
+  return 1;
+}
+
+int Fl_Input_::up_down_position(int i, int keepmark) {
+  while (i > 0 && index(i-1) != '\n') i--;	// go to start of line
+  double oldwid = 0.0;
+  setfont();
+  while (index(i) && index(i)!='\n') {
+    double tt = oldwid + fl_width(index(i));
+    if ((oldwid+tt)/2 >= up_down_pos) break;
+    oldwid = tt;
+    i++;
+  }
+  int j = position(i, keepmark ? mark_ : i);
+  was_up_down = 1;
+  return j;
+}
+
+int Fl_Input_::copy() {
+  if (mark() != position()) {
+    int b, e; if (position() < mark()) {
+      b = position(); e = mark();
+    } else {
+      e = position(); b = mark();
+    }
+    if (type()!=FL_SECRET_INPUT) Fl::selection(*this, value()+b, e-b);
+    return 1;
+  }
+  return 0;
+}
+
+#define MAXFLOATSIZE 40
+
+static char* undobuffer;
+static int undobufferlength;
+static Fl_Input_* undowidget;
+static int undoat;	// points after insertion
+static int undocut;	// number of characters deleted there
+static int undoinsert;	// number of characters inserted
+static int yankcut;	// length of valid contents of buffer, even if undocut=0
+
+static void undobuffersize(int n) {
+  if (n > undobufferlength) {
+    if (undobuffer) {
+      do {undobufferlength *= 2;} while (undobufferlength < n);
+      undobuffer = (char*)realloc(undobuffer, undobufferlength);
+    } else {
+      undobufferlength = n+9;
+      undobuffer = (char*)malloc(undobufferlength);
+    }
+  }
+}
+
+// all changes go through here, delete characters b-e and insert text:
+int Fl_Input_::replace(int b, int e, const char* text, int ilen) {
+
+  was_up_down = 0;
+
+  if (b<0) b = 0;
+  if (e<0) e = 0;
+  if (b>size_) b = size_;
+  if (e>size_) e = size_;
+  if (e maximum_size_) {
+    ilen = maximum_size_-size_+(e-b);
+    if (ilen < 0) ilen = 0;
+  }
+
+  put_in_buffer(size_+ilen);
+
+  if (e>b) {
+    if (undowidget == this && b == undoat) {
+      undobuffersize(undocut+(e-b));
+      memcpy(undobuffer+undocut, value_+b, e-b);
+      undocut += e-b;
+    } else if (undowidget == this && e == undoat && !undoinsert) {
+      undobuffersize(undocut+(e-b));
+      memmove(undobuffer+(e-b), undobuffer, undocut);
+      memcpy(undobuffer, value_+b, e-b);
+      undocut += e-b;
+    } else if (undowidget == this && e == undoat && (e-b)b; i--) buffer[i] = buffer[i-ilen];
+    for (i=0; ib; i--) buffer[i] = buffer[i-ilen];
+    for (i=0; i t && *(uchar*)(e-1) <= ' ') e--;
+    return replace(position(), mark(), t, e-t);}
+
+  default:
+    return 0;
+  }
+}
+
+/*------------------------------*/
+
+Fl_Input_::Fl_Input_(int x, int y, int w, int h, const char* l)
+: Fl_Widget(x, y, w, h, l) {
+  box(FL_NO_BOX);
+  color(FL_WHITE, FL_SELECTION_COLOR);
+  align(FL_ALIGN_LEFT);
+  textsize_ = FL_NORMAL_SIZE;
+  textfont_ = FL_HELVETICA;
+  textcolor_ = FL_BLACK;
+  cursor_color_ = FL_BLACK; // was FL_BLUE
+  mark_ = position_ = size_ = 0;
+  bufsize = 0;
+  value_ = "";
+  xscroll_ = yscroll_ = 0;
+  maximum_size_ = 32767;
+}
+
+void Fl_Input_::put_in_buffer(int len) {
+  if (value_ == buffer && bufsize > len) return;
+  if (!bufsize) {
+    if (len > size_) len += 9; // let a few characters insert before realloc
+    bufsize = len+1; 
+    buffer = (char*)malloc(bufsize);
+  } else if (bufsize <= len) {
+    // we may need to move old value in case it points into buffer:
+    int moveit = (value_ >= buffer && value_ < buffer+bufsize);
+    // enlarge current buffer
+    if (len > size_) {
+      do {bufsize *= 2;} while (bufsize <= len);
+    } else {
+      bufsize = len+1;
+    }
+    char* nbuffer = (char*)realloc(buffer, bufsize);
+    if (moveit) value_ += (nbuffer-buffer);
+    buffer = nbuffer;
+  }
+  memmove(buffer, value_, size_); buffer[size_] = 0;
+  value_ = buffer;
+}
+
+int Fl_Input_::static_value(const char* str, int len) {
+  clear_changed();
+  if (undowidget == this) undowidget = 0;
+  if (str == value_ && len == size_) return 0;
+  if (len) { // non-empty new value:
+    if (xscroll_ || yscroll_) {
+      xscroll_ = yscroll_ = 0;
+      minimal_update(0);
+    } else {
+      int i = 0;
+      // find first different character:
+      if (value_) {
+	for (; i
+#include 
+#include 
+
+void Fl_Light_Button::draw() {
+  if (box()) draw_box(this==Fl::pushed() ? down(box()) : box(), color());
+  Fl_Color col = value() ? selection_color() : color();
+  int d = h()/6;
+  int W = w()
+#include 
+#include 
+#include 
+
+int Fl_Menu_Item::size() const {
+  const Fl_Menu_Item* m = this;
+  int nest = 0;
+  for (;;) {
+    if (!m->text) {
+      if (!nest) return (m-this+1);
+      nest--;
+    } else if (m->flags & FL_SUBMENU) {
+      nest++;
+    }
+    m++;
+  }
+}
+
+const Fl_Menu_Item* Fl_Menu_Item::next(int n) const {
+  if (n < 0) return 0; // this is so selected==-1 returns NULL
+  const Fl_Menu_Item* m = this;
+  int nest = 0;
+  while (n>0) {
+    if (!m->text) {
+      if (!nest) return m;
+      nest--;
+    } else if (m->flags&FL_SUBMENU) {
+      nest++;
+    }
+    m++;
+    if (!nest && m->visible()) n--;
+  }
+  return m;
+}
+
+// appearance of current menus are pulled from this parent widget:
+static const Fl_Menu_* button;
+
+////////////////////////////////////////////////////////////////
+
+// tiny window for title of menu:
+class menutitle : public Fl_Menu_Window {
+  void draw();
+public:
+  const Fl_Menu_Item* menu;
+  menutitle(int X, int Y, int W, int H, const Fl_Menu_Item*);
+};
+
+// each vertical menu has one of these:
+class menuwindow : public Fl_Menu_Window {
+  void draw();
+  void drawentry(const Fl_Menu_Item*, int i, int erase);
+public:
+  menutitle* title;
+  int handle(int);
+  int itemheight;	// zero == menubar
+  int numitems;
+  int selected;
+  int drawn_selected;	// last redraw has this selected
+  const Fl_Menu_Item* menu;
+  menuwindow(const Fl_Menu_Item* m, int X, int Y, int W, int H,
+	     const Fl_Menu_Item* picked, const Fl_Menu_Item* title,
+	     int menubar = 0);
+  ~menuwindow();
+  void set_selected(int);
+  int find_selected(int mx, int my);
+  int titlex(int);
+  void autoscroll(int);
+  void position(int x, int y);
+};
+
+#define BW	3 // border thickness
+#define LEFT	6 // between left edge of item and edge of box
+#define RIGHT	8 // between right edge of item and edge of box
+#define BOTTOM	4 // between bottom item and bottom of box
+#define LEADING 4 // extra vertical leading
+#define TOP	5 // between top item and top of box
+
+extern char fl_draw_shortcut;
+
+// width of label, including effect of & characters:
+int Fl_Menu_Item::measure(int* hp, const Fl_Menu_* m) const {
+  Fl_Label l;
+  l.value = text;
+  l.type = labeltype_;
+  l.font = labelsize_ ? labelfont_ : uchar(m ? m->textfont() : FL_HELVETICA);
+  if (l.font < 4) l.font = (Fl_Font)(l.font | Fl_Menu_::default_font());
+  l.size = labelsize_ ? labelsize_ : m ? m->textsize() : FL_NORMAL_SIZE;
+  l.size += Fl_Menu_::default_size();
+  l.color = labelcolor_;
+  fl_draw_shortcut = 1;
+  int w = 0; int h = 0; l.measure(w, hp ? *hp : h);
+  fl_draw_shortcut = 0;
+  if (flags & (FL_MENU_TOGGLE|FL_MENU_RADIO)) w += 14;
+  return w;
+}
+
+void Fl_Menu_Item::draw(int x, int y, int w, int h, const Fl_Menu_* m,
+			int selected) const {
+  Fl_Label l;
+  l.value = text;
+  l.type = labeltype_;
+  l.font = labelsize_ ? labelfont_ : uchar(m ? m->textfont() : FL_HELVETICA);
+  if (l.font < 4) l.font = (Fl_Font)(l.font | Fl_Menu_::default_font());
+  l.size = labelsize_ ? labelsize_ : m ? m->textsize() : FL_NORMAL_SIZE;
+  l.size += Fl_Menu_::default_size();
+  l.color = !active() ? (labelcolor_|8) : labelcolor_;
+  Fl_Color color = m ? m->color() : FL_GRAY;
+  if (selected) {
+    Fl_Color r = m ? m->selection_color() : FL_SELECTION_COLOR;
+    Fl_Boxtype b = m && m->down_box() ? m->down_box() : FL_FLAT_BOX;
+    if (contrast(r,color)!=r) { // back compatability boxtypes
+      if (selected == 2) { // menu title
+	r = color;
+	b = m ? m->box() : FL_UP_BOX;
+      } else {
+	r = (Fl_Color)(FL_COLOR_CUBE-1); // white
+	b = FL_THIN_UP_BOX;
+      }
+    } else {
+      l.color = contrast((Fl_Color)labelcolor_, r);
+    }
+    if (selected == 2) {
+      fl_draw_box(b, x, y, w, h, r);
+      x += LEFT;
+      w -= LEFT+RIGHT;
+    } else {
+      fl_draw_box(b, x-2, y-1, w+7, h+2, r);
+    }
+  }
+
+  if (flags & (FL_MENU_TOGGLE|FL_MENU_RADIO)) {
+    int y1 = y+(h-14)/2;
+    fl_color(FL_DARK3);
+    if (flags & FL_MENU_RADIO) {
+      fl_line(x-1, y1+7, x+5, y1+1, x+11, y1+7);
+      if (selected) {
+	fl_color(color); 
+	fl_polygon(x, y1+7, x+5, y1+2, x+10, y1+7, x+5, y1+12);
+      }
+      fl_color(FL_LIGHT3); fl_line(x+11, y1+7, x+5, y1+13, x-1, y1+7);
+      if (value()) {
+	fl_color(FL_BLACK); 
+	fl_polygon(x+1, y1+7, x+5, y1+3, x+9, y1+7, x+5, y1+11);
+      }
+    } else {
+      fl_yxline(x, y1+11, y1+2, x+9);
+      if (selected) {fl_color(color); fl_rectf(x+1, y1+3, 9, 9);}
+      fl_color(FL_LIGHT3); fl_xyline(x+1, y1+12, x+10, y1+3);
+      if (value()) {fl_color(FL_BLACK); fl_rectf(x+2, y1+4, 7, 7);}
+    }
+    x += 14; w -= 14;
+  }
+
+  fl_draw_shortcut = 1;
+  l.draw(x, y, w, h, FL_ALIGN_LEFT);
+  fl_draw_shortcut = 0;
+}
+
+menutitle::menutitle(int X, int Y, int W, int H, const Fl_Menu_Item* L) :
+  Fl_Menu_Window(X, Y, W, H, 0) {
+  end();
+  set_modal();
+  clear_border();
+  menu = L;
+  if (L->labelcolor_) clear_overlay();
+  box(FL_NO_BOX);
+}
+
+menuwindow::menuwindow(const Fl_Menu_Item* m, int X, int Y, int Wp, int Hp,
+		       const Fl_Menu_Item* picked, const Fl_Menu_Item* t, 
+		       int menubar)
+  : Fl_Menu_Window(X, Y, Wp, Hp, 0)
+{
+  end();
+  set_modal();
+  clear_border();
+  menu = m;
+  drawn_selected = -1;
+  box(FL_NO_BOX);
+  selected = -1;
+  {int i = 0;
+  if (m) for (const Fl_Menu_Item* m1=m; ; m1 = m1->next(), i++) {
+    if (picked) {
+      if (m1 == picked) {selected = i; picked = 0;}
+      else if (m1 > picked) {selected = i-1; picked = 0; Wp = Hp = 0;}
+    }
+    if (!m1->text) break;
+  }
+  numitems = i;}
+
+  if (menubar) {
+    itemheight = 0;
+    title = 0;
+    return;
+  }
+
+  itemheight = 1;
+
+  int hotKeysw = 0;
+  int Wtitle = 0;
+  int Htitle = 0;
+  if (t) Wtitle = t->measure(&Htitle, button);
+  int W = Wtitle;
+  if (m) for (; m->text; m = m->next()) {
+    int h; int w1 = m->measure(&h, button);
+    if (h+LEADING>itemheight) itemheight = h+LEADING;
+    if (m->flags&(FL_SUBMENU|FL_SUBMENU_POINTER)) w1 += 14;
+    if (w1 > W) W = w1;
+    if (m->shortcut_) {
+      w1 = int(fl_width(fl_shortcut_label(m->shortcut_))) + 8;
+      if (w1 > hotKeysw) hotKeysw = w1;
+    }
+    if (m->labelcolor_) clear_overlay();
+  }
+  if (selected >= 0 && !Wp) X -= W/2;
+  W += hotKeysw+LEFT+RIGHT; if (Wp > W) W = Wp;
+
+  if (!Wp) {if (X < 0) X = 0; if (X > Fl::w()-W) X= Fl::w()-W;}
+  x(X); w(W);
+  h((numitems ? itemheight*numitems-LEADING : 0)+TOP+BOTTOM+1);
+  if (selected >= 0)
+    Y = Y+(Hp-itemheight)/2-selected*itemheight-2;
+  else
+    Y = Y+Hp;
+  if (m) y(Y-1); else {y(Y-3); w(1); h(1);}
+
+  if (t) {
+    int ht = button && button->h() <= 50 ? button->h()-6
+      : Htitle+TOP+BOTTOM-1;
+    title = new menutitle(X, Y-ht-3, Wtitle+LEFT+RIGHT, ht, t);
+  } else
+    title = 0;
+}
+
+menuwindow::~menuwindow() {
+  delete title;
+}
+
+void menuwindow::position(int X, int Y) {
+  if (title) {title->position(X, title->y()+Y-y());}
+  Fl_Menu_Window::position(X, Y);
+  x(X); y(Y); // don't wait for response from X
+}
+
+// scroll so item i is visible on screen
+void menuwindow::autoscroll(int i) {
+  int Y = y()+h()-(BOTTOM + (numitems-i)*itemheight - LEADING + 1);
+  if (Y <= 0) Y = -Y+10;
+  else {
+    Y = Y+itemheight-Fl::h();
+    if (Y <= 0) return;
+    Y = -Y-10;
+  }
+  Fl_Menu_Window::position(x(), y()+Y);
+  y(y()+Y); // don't wait for response from X
+}
+
+////////////////////////////////////////////////////////////////
+
+void menuwindow::drawentry(const Fl_Menu_Item* m, int i, int erase) {
+  if (!m) return; // this happens if -1 is selected item and redrawn
+
+  int x = LEFT-3;
+  int W = this->w();
+  int w = W-(LEFT+RIGHT-6);
+  int y = h()-(BOTTOM + (numitems-i)*itemheight - LEADING + 1);
+  int h = itemheight - LEADING;
+
+  if (erase && i != selected) {
+    fl_color(button ? button->color() : FL_GRAY);
+    fl_rectf(x+1, y-1, w+1, h+2);
+  }
+
+  m->draw(x+3, y, w-6, h, button, i==selected);
+
+  // the shortcuts and arrows assumme fl_color() was left set by draw():
+  if (m->submenu()) {
+    int y1 = y+(h-14)/2;
+    fl_polygon(x+w-10, y1+2, x+w-10, y1+2+10, x+w, y1+2+5);
+  } else if (m->shortcut_) {
+    Fl_Font f = button ? button->textfont() : FL_HELVETICA;
+    fl_font(f, button ? button->textsize() : FL_NORMAL_SIZE,
+	    Fl_Menu_::default_font(), Fl_Menu_::default_size());
+    fl_draw(fl_shortcut_label(m->shortcut_), x, y, w-3, h, FL_ALIGN_RIGHT);
+  }
+
+  if (m->flags & FL_MENU_DIVIDER) {
+    fl_color(FL_DARK3);
+    fl_xyline(BW-1, y+h+1, W-BW);
+    fl_color(FL_LIGHT3);
+    fl_xyline(BW, y+h+2, W-BW);
+  }
+
+}
+
+void menutitle::draw() {
+  menu->draw(0, 0, w(), h(), button, 2);
+}
+
+void menuwindow::draw() {
+
+  if (damage() != 1) {	// complete redraw
+    if (menu) {
+      fl_draw_box(button&&button->box() ? button->box() : FL_UP_BOX,
+		  0, 0, w(), h(),
+		  button ? button->color() : FL_GRAY);
+      const Fl_Menu_Item* m; int i;
+      for (m=menu, i=0; m->text; i++, m = m->next()) drawentry(m, i, 0);
+    }
+  } else {
+    if (damage() & 1 && selected!=drawn_selected) { // change selection
+      drawentry(menu->next(drawn_selected), drawn_selected, 1);
+      drawentry(menu->next(selected), selected, 1);
+    }
+  }	    
+  drawn_selected = selected;
+}
+
+void menuwindow::set_selected(int i) {
+  if (i != selected) {selected = i; damage(1);}
+}
+
+////////////////////////////////////////////////////////////////
+
+int menuwindow::find_selected(int mx, int my) {
+  if (!menu || !menu->text) return -1;
+  mx -= x();
+  my -= y();
+  if (my <= 0 || my >= h()) return -1;
+  if (!itemheight) { // menubar
+    int x = BW; int i = 0;
+    const Fl_Menu_Item* m = menu;
+    for (; ; m = m->next(), i++) {
+      if (!m->text) return -1;
+      x += m->measure(0, button) + 16;
+      if (x > mx) break;
+    }
+    return i;
+  }
+  if (mx <= 0 || mx >= w()) return -1;
+  my -= h()-(BOTTOM + numitems*itemheight - LEADING + 2);
+  if (my <= 0) return -1;
+  int i = my/itemheight;
+  if (i>=numitems) i = numitems-1;
+  return i;
+}
+
+// return horizontal position for item i in a menubar:
+int menuwindow::titlex(int i) {
+  const Fl_Menu_Item* m;
+  int x = BW;
+  for (m=menu; i--; m = m->next()) x += m->measure(0, button) + 16;
+  return x;
+}
+
+// match shortcuts & label shortcuts, don't search submenus:
+// returns menu item and index
+const Fl_Menu_Item* Fl_Menu_Item::find_shortcut(int* ip) const {
+  const Fl_Menu_Item* m1 = this;
+  for (int ii = 0; m1 && m1->text; m1 = m1->next(1), ii++) {
+    if (m1->activevisible() &&
+	(Fl::test_shortcut(m1->shortcut_)
+	 || Fl_Widget::test_shortcut(m1->text))) {if (ip) *ip=ii; return m1;}
+  }
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////
+// Fl_Menu_Item::popup(...)
+
+// Because Fl::grab() is done, all events go to one of the menu windows.
+// But the handle method needs to look at all of them to find out
+// what item the user is pointing at.  And it needs a whole lot
+// of other state variables to determine what is going on with
+// the currently displayed menus.
+// So the main loop (handlemenu()) puts all the state in a structure
+// and puts a pointer to it in a static location, so the handle()
+// on menus can refer to it and alter it.  The handle() method
+// changes variables in this state to indicate what item is
+// picked, but does not actually alter the display, instead the
+// main loop does that.  This is because the X mapping and unmapping
+// of windows is slow, and we don't want to fall behind the events.
+
+struct menustate {
+  const Fl_Menu_Item* current_item; // what mouse is pointing at
+  int menu_number; // which menu it is in
+  int item_number; // which item in that menu
+  menuwindow* p[20]; // pointers to menus
+  int nummenus;
+  int menubar; // if true p[0] is a menubar
+  int state; // 0 at first, 1 after push, 2 when done
+};
+static menustate* p;
+
+static inline void setitem(const Fl_Menu_Item* i, int m, int n) {
+  p->current_item = i;
+  p->menu_number = m;
+  p->item_number = n;
+}
+
+static void setitem(int m, int n) {
+  menustate &p = *(::p);
+  p.current_item = (m >= 0 && n >= 0) ?
+    p.current_item = p.p[m]->menu->next(n) : 0;
+  p.menu_number = m;
+  p.item_number = n;
+}
+
+static int forward(int menu) { // go to next item in menu menu if possible
+  menustate &p = *(::p);
+  menuwindow &m = *(p.p[menu]);
+  int item = (menu == p.menu_number) ? p.item_number : m.selected;
+  while (++item < m.numitems) {
+    const Fl_Menu_Item* m1 = m.menu->next(item);
+    if (m1->activevisible()) {setitem(m1, menu, item); return 1;}
+  }
+  return 0;
+}
+
+static int backward(int menu) { // previous item in menu menu if possible
+  menustate &p = *(::p);
+  menuwindow &m = *(p.p[menu]);
+  int item = (menu == p.menu_number) ? p.item_number : m.selected;
+  while (--item >= 0) {
+    const Fl_Menu_Item* m1 = m.menu->next(item);
+    if (m1->activevisible()) {setitem(m1, menu, item); return 1;}
+  }
+  return 0;
+}
+
+int menuwindow::handle(int e) {
+  menustate &p = *(::p);
+  switch (e) {
+  case FL_KEYBOARD:
+    switch (Fl::event_key()) {
+    case FL_Up:
+      if (p.menu_number < 0) setitem(0, 0);
+      if (p.menubar && p.menu_number == 0) ;
+      else if (backward(p.menu_number));
+      else if (p.menubar && p.menu_number==1) setitem(0, p.p[0]->selected);
+      return 1;
+    case FL_Down:
+      if (p.menu_number < 0) setitem(0, 0);
+      else if (p.menu_number || !p.menubar) forward(p.menu_number);
+      else if (p.menu_number < p.nummenus-1) forward(p.menu_number+1);
+      return 1;
+    case FL_Right:
+      if (p.menubar && (p.menu_number<=0 || p.menu_number==1 && p.nummenus==2))
+	forward(0);
+      else if (p.menu_number < p.nummenus-1) forward(p.menu_number+1);
+      return 1;
+    case FL_Left:
+      if (p.menubar && p.menu_number<=1) backward(0);
+      else if (p.menu_number>0)
+	setitem(p.menu_number-1, p.p[p.menu_number-1]->selected);
+      return 1;
+    case FL_Enter:
+      p.state = 2;
+      return 1;
+    case FL_Escape:
+      setitem(0, -1, 0);
+      p.state = 2;
+      return 1;
+    }
+    break;
+  case FL_SHORTCUT: {
+    for (int menu = p.nummenus; menu--;) {
+      menuwindow &mw = *(p.p[menu]);
+      int item; const Fl_Menu_Item* m = mw.menu->find_shortcut(&item);
+      if (m) {
+	setitem(m, menu, item);
+	if (!m->submenu()) p.state = 2;
+	return 1;
+      }
+    }} break;
+  case FL_PUSH:
+  //case FL_MOVE:
+  case FL_DRAG: {
+    int mx = Fl::event_x_root();
+    int my = Fl::event_y_root();
+    int item=0; int menu;
+    for (menu = p.nummenus-1; menu >= 0; menu--) {
+      item = p.p[menu]->find_selected(mx, my);
+      if (item >= 0) break;
+    }
+    setitem(menu, item);
+    if (e == FL_PUSH) {
+      // detect second click on a menu title:
+      if (p.current_item && item == p.p[menu]->selected) p.state = 3;
+      else p.state = 1;
+    }
+    } return 1;
+  case FL_RELEASE:
+    if (!p.current_item) {
+      if (p.state || !Fl::event_is_click()) p.state = 2;
+    } else {
+      if (p.state == 3 && Fl::event_is_click()) p.state = 2;
+      else if (p.current_item->activevisible() && !p.current_item->submenu())
+	p.state = 2;
+    }
+    return 1;
+  }
+  return Fl_Window::handle(e);
+}
+
+const Fl_Menu_Item* Fl_Menu_Item::pulldown(
+    int X, int Y, int W, int H,
+    const Fl_Menu_Item* initial_item,
+    const Fl_Menu_* pbutton,
+    const Fl_Menu_Item* t,
+    int menubar) const
+{
+  Fl_Group::current(0); // fix possible user error...
+
+  button = pbutton;
+  if (pbutton) {
+    for (Fl_Window* w = pbutton->window(); w; w = w->window()) {
+      X += w->x();
+      Y += w->y();
+    }
+  } else {
+    X += Fl::event_x_root()-Fl::event_x();
+    Y += Fl::event_y_root()-Fl::event_y();
+  }
+  menuwindow mw(this, X, Y, W, H, initial_item, t, menubar);
+  Fl::grab(mw);
+  menustate p; ::p = &p;
+  p.p[0] = &mw;
+  p.nummenus = 1;
+  p.menubar = menubar;
+  p.state = 0;
+
+  menuwindow* fakemenu = 0; // kludge for buttons in menubar
+
+  // preselected item, pop up submenus if necessary:
+  if (initial_item && mw.selected >= 0) {
+    setitem(0, mw.selected);
+    goto STARTUP;
+  }
+
+  p.current_item = 0; p.menu_number = -1; p.item_number = -1;
+  if (menubar) mw.handle(FL_DRAG); // find the initial menu
+  initial_item = p.current_item;
+  if (initial_item) goto STARTUP;
+
+  // the main loop, runs until p.state goes to 2:
+  for (;;) {
+
+    // make sure all the menus are shown:
+    {for (int k = menubar; k < p.nummenus; k++)
+      if (!p.p[k]->shown()) {
+	if (p.p[k]->title) p.p[k]->title->show();
+	p.p[k]->show();
+      }
+    }
+
+    // get events:
+    {const Fl_Menu_Item* oldi = p.current_item;
+    Fl::wait();
+    if (p.state == 2) break; // done.
+    if (p.current_item == oldi) continue;}
+    // only do rest if item changes:
+
+    delete fakemenu; fakemenu = 0; // turn off "menubar button"
+
+    if (!p.current_item) { // pointing at nothing
+      // turn off selection in deepest menu, but don't erase other menus:
+      p.p[p.nummenus-1]->set_selected(-1);
+      continue;
+    }
+
+    delete fakemenu; fakemenu = 0;
+    initial_item = 0; // stop the startup code
+    p.p[p.menu_number]->autoscroll(p.item_number);
+
+  STARTUP:
+    menuwindow& cw = *p.p[p.menu_number];
+    const Fl_Menu_Item* m = p.current_item;
+    if (!m->activevisible()) { // pointing at inactive item
+      cw.set_selected(-1);
+      initial_item = 0; // turn off startup code
+      continue;
+    }
+    cw.set_selected(p.item_number);
+
+    if (m==initial_item) initial_item=0; // stop the startup code if item found
+    if (m->submenu()) {
+      const Fl_Menu_Item* title = m;
+      const Fl_Menu_Item* menutable;
+      if (m->flags&FL_SUBMENU) menutable = m+1;
+      else menutable = (Fl_Menu_Item*)(m)->user_data_;
+      // figure out where new menu goes:
+      int nX, nY;
+      if (!p.menu_number && p.menubar) {	// menu off a menubar:
+	nX = cw.x() + cw.titlex(p.item_number);
+	nY = cw.y() + cw.h();
+	initial_item = 0;
+      } else {
+	nX = cw.x() + cw.w();
+	nY = cw.y() + 1 + p.item_number * cw.itemheight;
+	title = 0;
+      }
+      if (initial_item) { // bring up submenu containing initial item:
+	menuwindow* n = new menuwindow(menutable,X,Y,W,H,initial_item,title);
+	p.p[p.nummenus++] = n;
+	// move all earlier menus to line up with this new one:
+	if (n->selected>=0) {
+	  int dy = n->y()-nY;
+	  int dx = n->x()-nX;
+	  for (int menu = 0; menu <= p.menu_number; menu++) {
+	    menuwindow* t = p.p[menu];
+	    int nx = t->x()+dx; if (nx < 0) {nx = 0; dx = -t->x();}
+	    int ny = t->y()+dy+1; if (ny < 0) {ny = 0; dy = -t->y()-1;}
+	    t->position(nx, ny);
+	  }
+	  setitem(p.nummenus-1, n->selected);
+	  goto STARTUP;
+	}
+      } else if (p.nummenus > p.menu_number+1 &&
+		 p.p[p.menu_number+1]->menu == menutable) {
+	// the menu is already up:
+	while (p.nummenus > p.menu_number+2) delete p.p[--p.nummenus];
+	p.p[p.nummenus-1]->set_selected(-1);
+      } else {
+	// delete all the old menus and create new one:
+	while (p.nummenus > p.menu_number+1) delete p.p[--p.nummenus];
+	p.p[p.nummenus++]= new menuwindow(menutable,nX,nY,title?1:0,0,0,title);
+      }
+    } else { // !m->submenu():
+      while (p.nummenus > p.menu_number+1) delete p.p[--p.nummenus];
+      if (!p.menu_number && p.menubar) {
+	// kludge so "menubar buttons" turn "on" by using menu title:
+	fakemenu = new menuwindow(0,
+				  cw.x()+cw.titlex(p.item_number),
+				  cw.y()+cw.h(), 0, 0,
+				  0, m);
+	fakemenu->title->show();
+      }
+    }
+  }
+  const Fl_Menu_Item* m = p.current_item;
+  delete fakemenu;
+  while (p.nummenus>1) delete p.p[--p.nummenus];
+  mw.hide();
+  Fl::release();
+  return m;
+}
+
+const Fl_Menu_Item*
+Fl_Menu_Item::popup(
+  int X, int Y,
+  const char* title,
+  const Fl_Menu_Item* picked,
+  const Fl_Menu_* button
+  ) const
+{
+  static Fl_Menu_Item dummy; // static so it is all zeros
+  dummy.text = title;
+  return pulldown(X, Y, 0, 0, picked, button, title ? &dummy : 0);
+}
+
+const Fl_Menu_Item* Fl_Menu_Item::test_shortcut() const {
+  const Fl_Menu_Item* m = this;
+  const Fl_Menu_Item* ret = 0;
+  if (m) for (; m->text; m = m->next()) {
+    if (m->activevisible()) {
+      // return immediately any match of an item in top level menu:
+      if (Fl::test_shortcut(m->shortcut_)) return m;
+      // if (Fl_Widget::test_shortcut(m->text)) return m;
+      // only return matches from lower menu if nothing found in top menu:
+      if (!ret && m->submenu()) {
+	const Fl_Menu_Item* s =
+	  (m->flags&FL_SUBMENU) ? m+1:(const Fl_Menu_Item*)m->user_data_;
+	ret = s->test_shortcut();
+      }
+    }
+  }
+  return ret;
+}
+
+// end of Fl_Menu.C
diff --git a/src/Fl_Menu_.cxx b/src/Fl_Menu_.cxx
new file mode 100644
index 000000000..a045b3489
--- /dev/null
+++ b/src/Fl_Menu_.cxx
@@ -0,0 +1,96 @@
+// Fl_Menu_.C
+
+// This is a base class for all items that have a menu:
+//	Fl_Menu_Bar, Fl_Menu_Button, Fl_Choice
+// This provides storage for a menu item, functions to add/modify/delete
+// items, and a call for when the user picks a menu item.
+
+// More code in Fl_Menu_add.C
+
+#include 
+#include 
+#include 
+
+Fl_Font Fl_Menu_::default_font_;
+int Fl_Menu_::default_size_;
+
+int Fl_Menu_::value(const Fl_Menu_Item* m) {
+  clear_changed();
+  if (value_ != m) {value_ = m; return 1;}
+  return 0;
+}
+
+// When user picks a menu item, call this.  It will do the callback.
+// Unfortunatly this also casts away const for the checkboxes, but this
+// was necessary so non-checkbox menus can really be declared const...
+const Fl_Menu_Item* Fl_Menu_::picked(const Fl_Menu_Item* v) {
+  if (v) {
+    if (v->radio()) {
+      if (!v->value()) { // they are turning on a radio item
+	set_changed();
+	((Fl_Menu_Item*)v)->setonly();
+      }
+    } else if (v->flags & FL_MENU_TOGGLE) {
+      set_changed();
+      ((Fl_Menu_Item*)v)->flags ^= FL_MENU_VALUE;
+    } else if (v != value_) { // normal item
+      set_changed();
+    }
+    value_ = v;
+    if (when()&(FL_WHEN_CHANGED|FL_WHEN_RELEASE)) {
+      if (changed() || when()&FL_WHEN_NOT_CHANGED) {
+	clear_changed();
+	if (value_ && value_->callback_) value_->do_callback((Fl_Widget*)this);
+	else do_callback();
+      }
+    }
+  }
+  return v;
+}
+
+// turn on one of a set of radio buttons
+void Fl_Menu_Item::setonly() {
+  flags |= FL_MENU_RADIO | FL_MENU_VALUE;
+  Fl_Menu_Item* j;
+  for (j = this; ; ) {	// go down
+    if (j->flags & FL_MENU_DIVIDER) break; // stop on divider lines
+    j++;
+    if (!j->text || !j->radio()) break; // stop after group
+    j->clear();
+  }
+  for (j = this-1; ; j--) { // go up
+    if (!j->text || (j->flags&FL_MENU_DIVIDER) || !j->radio()) break;
+    j->clear();
+  }
+}
+
+Fl_Menu_::Fl_Menu_(int X,int Y,int W,int H,const char* l)
+: Fl_Widget(X,Y,W,H,l) {
+  set_flag(SHORTCUT_LABEL);
+  box(FL_UP_BOX);
+  when(FL_WHEN_RELEASE_ALWAYS);
+  value_ = menu_ = 0;
+  alloc = 0;
+  selection_color(FL_SELECTION_COLOR);
+  textfont(FL_HELVETICA);
+  textsize(FL_NORMAL_SIZE);
+  textcolor(FL_BLACK);
+  down_box(FL_NO_BOX);
+}
+
+int Fl_Menu_::size() const {
+  if (!menu_) return 0;
+  return menu_->size();
+}
+
+void Fl_Menu_::menu(const Fl_Menu_Item* m) {
+  // if (alloc) clear();
+  alloc = 0;
+  value_ = menu_ = (Fl_Menu_Item*)m;
+}
+
+Fl_Menu_::~Fl_Menu_() {
+  // if (alloc) clear();
+}
+
+// end of Fl_Menu_.C
diff --git a/src/Fl_Menu_Bar.cxx b/src/Fl_Menu_Bar.cxx
new file mode 100644
index 000000000..763f1acb1
--- /dev/null
+++ b/src/Fl_Menu_Bar.cxx
@@ -0,0 +1,33 @@
+#include 
+#include 
+
+void Fl_Menu_Bar::draw() {
+  draw_box();
+  if (!menu() || !menu()->text) return;
+  const Fl_Menu_Item* m;
+  int X = x()+9;
+  for (m=menu(); m->text; m = m->next()) {
+    m->draw(X, y(), 0, h(), this);
+    X += m->measure(0,this) + 16;
+  }
+}
+
+int Fl_Menu_Bar::handle(int event) {
+  const Fl_Menu_Item* v;
+  if (menu() && menu()->text) switch (event) {
+  case FL_PUSH:
+    v = 0;
+  J1:
+    v = menu()->pulldown(x(), y(), w(), h(), v, this, 0, 1);
+    picked(v);
+    return 1;
+  case FL_SHORTCUT:
+    v = menu()->test_shortcut();
+    if (v) {picked(v); return 1;}
+    v = menu()->find_shortcut();
+    if (v) goto J1;
+    return 0;
+  }
+  return 0;
+}
+
diff --git a/src/Fl_Menu_Button.cxx b/src/Fl_Menu_Button.cxx
new file mode 100644
index 000000000..96c250063
--- /dev/null
+++ b/src/Fl_Menu_Button.cxx
@@ -0,0 +1,57 @@
+// Fl_Menu_Button.C
+
+#include 
+#include 
+#include 
+
+void Fl_Menu_Button::draw() {
+  if (!box() || type()) return;
+  draw_box(box(), color());
+  draw_label();
+  if (box() == FL_FLAT_BOX) return; // for XForms compatability
+  int H = (labelsize()-3)&-2;
+  int X = x()+w()-H*2;
+  int Y = y()+(h()-H)/2;
+  fl_color(FL_DARK3); fl_line(X+H/2, Y+H, X, Y, X+H, Y);
+  fl_color(FL_LIGHT3); fl_line(X+H, Y, X+H/2, Y+H);
+}
+
+const Fl_Menu_Item* Fl_Menu_Button::popup() {
+  const Fl_Menu_Item* m;
+  if (!box() || type()) {
+    m = menu()->popup(Fl::event_x(), Fl::event_y(), label(), mvalue(), this);
+  } else {
+    m = menu()->pulldown(x(), y(), w(), h(), 0, this);
+  }
+  picked(m);
+  return m;
+}
+
+int Fl_Menu_Button::handle(int e) {
+  if (!menu() || !menu()->text) return 0;
+  switch (e) {
+  case FL_ENTER:
+  case FL_LEAVE:
+    return (box() && !type()) ? 1 : 0;
+  case FL_PUSH:
+    if (!box()) {
+      if (Fl::event_button() != 3) return 0;
+    } else if (type()) {
+      if (!(type() & (1 << (Fl::event_button()-1)))) return 0;
+    }
+    popup();
+    return 1;
+  case FL_SHORTCUT:
+    if (Fl_Widget::test_shortcut()) {popup(); return 1;}
+    return test_shortcut() != 0;
+  default:
+    return 0;
+  }
+}
+
+Fl_Menu_Button::Fl_Menu_Button(int X,int Y,int W,int H,const char *l)
+: Fl_Menu_(X,Y,W,H,l) {
+  down_box(FL_NO_BOX);
+}
+
+// end of Fl_Menu_Button.C
diff --git a/src/Fl_Menu_Window.cxx b/src/Fl_Menu_Window.cxx
new file mode 100644
index 000000000..f74db6ea2
--- /dev/null
+++ b/src/Fl_Menu_Window.cxx
@@ -0,0 +1,130 @@
+// Fl_Menu_Window.H
+
+// This is the window type used by Fl_Menu to make the pop-ups.
+// It draws in the overlay planes if possible.
+
+// Also here is the implementation of the mouse & keyboard grab,
+// which are used so that clicks outside the program's windows
+// can be used to dismiss the menus.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+// WIN32 note: HAVE_OVERLAY is false
+#if HAVE_OVERLAY
+extern XVisualInfo *fl_find_overlay_visual();
+extern XVisualInfo *fl_overlay_visual;
+extern Colormap fl_overlay_colormap;
+extern unsigned long fl_transparent_pixel;
+static GC gc;	// the GC used by all X windows
+extern uchar fl_overlay; // changes how fl_color(x) works
+#endif
+
+#include 
+
+void Fl_Menu_Window::show() {
+#if HAVE_OVERLAY
+  if (!shown() && overlay() && fl_find_overlay_visual()) {
+    XInstallColormap(fl_display, fl_overlay_colormap);
+    fl_background_pixel = int(fl_transparent_pixel);
+    Fl_X::make_xid(this, fl_overlay_visual, fl_overlay_colormap);
+    fl_background_pixel = -1;
+  } else
+#endif
+    Fl_Single_Window::show();
+}
+
+void Fl_Menu_Window::flush() {
+#if HAVE_OVERLAY
+  if (!fl_overlay_visual || !overlay()) {Fl_Single_Window::flush(); return;}
+  Fl_X *i = Fl_X::i(this);
+  fl_window = i->xid;
+  if (!gc) gc = XCreateGC(fl_display, i->xid, 0, 0);
+  fl_gc = gc;
+  fl_overlay = 1;
+  fl_clip_region(i->region); i->region = 0;
+  draw();
+  fl_overlay = 0;
+#else
+  Fl_Single_Window::flush();
+#endif
+}
+
+void Fl_Menu_Window::erase() {
+#if HAVE_OVERLAY
+  if (!gc || !shown()) return;
+//XSetForeground(fl_display, gc, 0);
+//XFillRectangle(fl_display, fl_xid(this), gc, 0, 0, w(), h());
+  XClearWindow(fl_display, fl_xid(this));
+#endif
+}
+
+// Fix the colormap flashing on Maximum Impact Graphics by erasing the
+// menu before unmapping it:
+void Fl_Menu_Window::hide() {
+  erase();
+  Fl_Single_Window::hide();
+}
+
+Fl_Menu_Window::~Fl_Menu_Window() {
+  hide();
+}
+
+////////////////////////////////////////////////////////////////
+// "Grab" is done while menu systems are up.  This has several effects:
+// Events are all sent to the "grab window", which does not even
+// have to be displayed (and in the case of Fl_Menu.C it isn't).
+// Under X override_redirect and save_under is done to new windows.
+// The system is also told to "grab" events and send them to this app.
+
+extern void fl_fix_focus();
+#ifdef WIN32
+HWND fl_capture; // for some reason we must keep forcing it back on!
+#endif
+
+void Fl::grab(Fl_Window& w) {
+  grab_ = &w;
+  fl_fix_focus();
+#ifdef WIN32
+  // this seems to have no effect...
+  SetCapture(fl_capture = fl_xid(first_window()));
+#else
+  XGrabPointer(fl_display,
+	       fl_xid(first_window()),
+	       1,
+	       ButtonPressMask|ButtonReleaseMask|
+	       ButtonMotionMask|PointerMotionMask,
+	       GrabModeAsync,
+	       GrabModeAsync, 
+	       None,
+	       0,
+	       fl_event_time);
+  XGrabKeyboard(fl_display,
+		fl_xid(first_window()),
+		1,
+		GrabModeAsync,
+		GrabModeAsync, 
+		fl_event_time);
+#endif
+}
+
+void Fl::release() {
+  grab_ = 0;
+  fl_fix_focus();
+#ifdef WIN32
+  fl_capture = 0;
+  ReleaseCapture();
+#else
+  XUngrabKeyboard(fl_display, fl_event_time);
+  XUngrabPointer(fl_display, fl_event_time);
+  // this flush is done in case the picked menu item goes into
+  // an infinite loop, so we don't leave the X server locked up:
+  XFlush(fl_display);
+#endif
+  return;
+}
+
+// end of Fl_Menu_Window.C
diff --git a/src/Fl_Menu_add.cxx b/src/Fl_Menu_add.cxx
new file mode 100644
index 000000000..1aee7517a
--- /dev/null
+++ b/src/Fl_Menu_add.cxx
@@ -0,0 +1,151 @@
+// Fl_Menu_add.C
+
+// Methods to alter the menu in an Fl_Menu_ widget.
+// This code is seperated so that it is not linked in if not used.
+
+// These functions are for emulation of Forms and for dynamically
+// changing the menus.  They are in this source file so they are
+// not linked in if not used, which is what will happen if the
+// the program only uses constant menu tables.
+
+// Not at all guaranteed to be Forms compatable, especially with any
+// string with a % sign in it!
+
+#include 
+#include 
+#include 
+
+int fl_old_shortcut(const char* s) {
+  if (!s || !*s) return 0;
+  int n = 0;
+  if (*s == '#') {n |= FL_ALT; s++;}
+  if (*s == '+') {n |= FL_SHIFT; s++;}
+  if (*s == '^') {n |= FL_CTRL; s++;}
+  return n | *s;
+}
+
+int Fl_Menu_Item::add(
+  const char *text,
+  int shortcut,
+  Fl_Callback *cb,	
+  void *data,
+  int flags)
+{
+  Fl_Menu_Item *m;
+  const char *p;
+  char *q;
+  char buf[1024];
+
+  int size = this->size();
+  int flags1 = 0;
+  char* item;
+
+  m = this;
+
+  for (;;) {    /* do all the supermenus: */
+
+    /* fill in the buf with name, changing \x to x: */
+    q = buf;
+    for (p=text; *p && *p != '/'; *q++ = *p++) if (*p=='\\') p++;
+    *q = 0;
+
+    item = buf;
+    if (*item == '_') {item++; flags1 = FL_MENU_DIVIDER;}
+    if (*p != '/') break; /* not a menu title */
+    text = p+1;	/* point at item title */
+
+    /* find a matching menu title: */
+    for (; m->text; m = m->next())
+      if (m->flags&FL_SUBMENU && !strcmp(item,m->text)) break;
+
+    if (!m->text) { /* create a new menu */
+      memmove(m+2,m,sizeof(Fl_Menu_Item)*(this+size-m));
+      m->text = strdup(item);
+      m->shortcut_ = 0;
+      m->callback_ = 0;
+      m->user_data_ = 0;
+      m->flags = FL_SUBMENU|flags1;
+      m->labeltype_ = m->labelfont_ = m->labelsize_ = m->labelcolor_ = 0;
+      (m+1)->text = 0;
+      size += 2;
+    }
+    m++;	/* go into the menu */
+    flags1 = 0;
+  }
+
+  /* find a matching menu item: */
+  for (; m->text; m = m->next())
+    if (!strcmp(m->text,item)) break;
+
+  if (!m->text) {	/* add a new menu item */
+    memmove(m+1,m,sizeof(Fl_Menu_Item)*(this+size-m));
+    size++;
+    m->text = strdup(item);
+  }
+
+  /* fill it in */
+  m->shortcut_ = shortcut;
+  m->callback_ = cb;
+  m->user_data_ = data;
+  m->flags = flags|flags1;
+  m->labeltype_ = m->labelfont_ = m->labelsize_ = m->labelcolor_ = 0;
+
+  return m-this;
+}
+
+// this is really lame, it will crash if this many items are added:
+#define FL_MENU_MAXITEMS	128
+
+int Fl_Menu_::add(const char *t, int s, Fl_Callback *c,void *v,int f) {
+  if (!menu_) {
+    value_ = menu_ = new Fl_Menu_Item[FL_MENU_MAXITEMS+1];
+    alloc = 1;
+    menu_[0].text = 0;
+  }
+  return menu_->add(t,s,c,v,f);
+}
+
+int Fl_Menu_::add(const char *str) {
+  char buf[128];
+  int r = 0;
+  while (*str) {
+    int shortcut = 0;
+    char *c;
+    for (c = buf; *str && *str != '|'; str++) {
+      if (*str == '\t') {*c++ = 0; shortcut = fl_old_shortcut(str);}
+      else *c++ = *str;
+    }
+    *c = 0;
+    r = add(buf, shortcut, 0, 0, 0);
+    if (*str) str++;
+  }
+  return r;
+}
+
+void Fl_Menu_::replace(int i, const char *str) {
+  if (i<0 || i>=size()) return;
+  if (alloc) free((void *)menu_[i].text);
+  menu_[i].text = strdup(str);
+}
+
+void Fl_Menu_::remove(int i) {
+  int n = size();
+  if (i<0 || i>=n) return;
+  if (alloc) free((void *)menu_[i].text);
+  memmove(&menu_[i],&menu_[i+1],(n-i)*sizeof(Fl_Menu_Item));
+}
+
+void Fl_Menu_::clear() {
+  for (int i = size(); i--;)
+    if (menu_[i].text) free((void*)menu_[i].text);
+  if (alloc) {
+    delete[] menu_;
+    menu_ = 0;
+    alloc = 0;
+  } else if (menu_) {
+    menu_[0].text = 0;
+    value_ = menu_;
+  }
+}
+
+// end of Fl_Menu_.C
diff --git a/src/Fl_Menu_global.cxx b/src/Fl_Menu_global.cxx
new file mode 100644
index 000000000..ddbf8e1de
--- /dev/null
+++ b/src/Fl_Menu_global.cxx
@@ -0,0 +1,20 @@
+// Fl_Menu_global.C
+
+// Make all the shortcuts in this menu global.
+// Currently only one menu at a time and you cannot destruct the menu,
+// is this sufficient?
+
+#include 
+#include 
+
+static Fl_Menu_* the_widget;
+
+static int handler(int e) {
+  if (e != FL_SHORTCUT || Fl::modal()) return 0;
+  return the_widget->test_shortcut() != 0;
+}
+
+void Fl_Menu_::global() {
+  if (!the_widget) Fl::add_handler(handler);
+  the_widget = this;
+}
diff --git a/src/Fl_Multi_Label.cxx b/src/Fl_Multi_Label.cxx
new file mode 100644
index 000000000..e2b59168b
--- /dev/null
+++ b/src/Fl_Multi_Label.cxx
@@ -0,0 +1,51 @@
+// Fl_Multi_Label.C
+
+// Allows two labels to be used on a widget (by having one of them
+// be one of these it allows an infinte number!)
+
+#include 
+#include 
+#include 
+#include 
+
+static void multi_labeltype(
+    const Fl_Label* o, int x, int y, int w, int h, Fl_Align a)
+{
+  Fl_Multi_Label* b = (Fl_Multi_Label*)(o->value);
+  Fl_Label local = *o;
+  local.value = b->labela;
+  local.type = b->typea;
+  int W = w; int H = h; local.measure(W, H);
+  local.draw(x,y,w,h,a);
+  if (a & FL_ALIGN_BOTTOM) h -= H;
+  else if (a & FL_ALIGN_TOP) {y += H; h -= H;}
+  else if (a & FL_ALIGN_RIGHT) w -= W;
+  else if (a & FL_ALIGN_LEFT) {x += W; w -= W;}
+  else {int d = (h+H)/2; y += d; h -= d;}
+  local.value = b->labelb;
+  local.type = b->typeb;
+  local.draw(x,y,w,h,a);
+}
+
+// measurement is only correct for left-to-right appending...
+static void multi_measure(const Fl_Label* o, int& w, int& h) {
+  Fl_Multi_Label* b = (Fl_Multi_Label*)(o->value);
+  Fl_Label local = *o;
+  local.value = b->labela;
+  local.type = b->typea;
+  local.measure(w,h);
+  local.value = b->labelb;
+  local.type = b->typeb;
+  int W = 0; int H = 0; local.measure(W,H);
+  w += W; if (H>h) h = H;
+}
+
+void Fl_Multi_Label::label(Fl_Widget* o) {
+  Fl::set_labeltype(_FL_MULTI_LABEL, multi_labeltype, multi_measure);
+  o->label(_FL_MULTI_LABEL, (const char*)this);
+}
+
+void Fl_Multi_Label::label(Fl_Menu_Item* o) {
+  Fl::set_labeltype(_FL_MULTI_LABEL, multi_labeltype, multi_measure);
+  o->label(_FL_MULTI_LABEL, (const char*)this);
+}
diff --git a/src/Fl_Output.cxx b/src/Fl_Output.cxx
new file mode 100644
index 000000000..a6dba007e
--- /dev/null
+++ b/src/Fl_Output.cxx
@@ -0,0 +1,23 @@
+// Fl_Output.C
+
+// This subclass of Fl_Input_ does not allow user to edit the output.
+// Used to display output.
+
+#include 
+#include 
+#include 
+
+void Fl_Output::draw() {
+  Fl_Boxtype b = box() ? box() : default_box();
+  if (damage() & 128) draw_box(b, color());
+  Fl_Input_::drawtext(x()+Fl::box_dx(b)+3, y()+Fl::box_dy(b),
+		      w()-Fl::box_dw(b)-6, h()-Fl::box_dh(b));
+}
+
+int Fl_Output::handle(int event) {
+  if (event == FL_FOCUS) return 0;
+  Fl_Boxtype b = box() ? box() : default_box();
+  return Fl_Input_::handletext(event,
+	x()+Fl::box_dx(b)+3, y()+Fl::box_dy(b),
+	w()-Fl::box_dw(b)-6, h()-Fl::box_dh(b));
+}
diff --git a/src/Fl_Overlay_Window.cxx b/src/Fl_Overlay_Window.cxx
new file mode 100644
index 000000000..7bbd85904
--- /dev/null
+++ b/src/Fl_Overlay_Window.cxx
@@ -0,0 +1,115 @@
+// Fl_Overlay_Window.C
+
+// A window using double-buffering and able to draw an overlay
+// on top of that.  Uses the hardware to draw the overlay if
+// possible, otherwise it just draws in the front buffer.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+void Fl_Overlay_Window::show() {
+  Fl_Double_Window::show();
+  if (overlay_ && overlay_ != this) overlay_->show();
+}
+
+void Fl_Overlay_Window::hide() {
+  Fl_Double_Window::hide();
+}
+
+void Fl_Overlay_Window::flush() {
+  // a non-zero argument copies entire back buffer to window, erasing
+  // the overlay.  We should only do this if fake overlay needs redraw:
+  uchar overlay_damage = damage()&8; clear_damage(damage()&~8);
+  _flush(overlay_damage);
+  if (overlay_ == this) draw_overlay();
+}
+
+void Fl_Overlay_Window::resize(int X, int Y, int W, int H) {
+  Fl_Double_Window::resize(X,Y,W,H);
+  if (overlay_ && overlay_!=this) overlay_->resize(0,0,w(),h());
+}
+
+Fl_Overlay_Window::~Fl_Overlay_Window() {
+  hide();
+//  delete overlay; this is done by ~Fl_Group
+}
+
+#if !HAVE_OVERLAY
+
+int Fl_Overlay_Window::can_do_overlay() {return 0;}
+
+void Fl_Overlay_Window::redraw_overlay() {overlay_ = this; damage(8);}
+
+#else
+
+extern XVisualInfo *fl_find_overlay_visual();
+extern XVisualInfo *fl_overlay_visual;
+extern Colormap fl_overlay_colormap;
+extern unsigned long fl_transparent_pixel;
+static GC gc;	// the GC used by all X windows
+extern uchar fl_overlay; // changes how fl_color(x) works
+
+class _Fl_Overlay : public Fl_Window {
+  friend class Fl_Overlay_Window;
+  void flush();
+  void show();
+public:
+  _Fl_Overlay(int x, int y, int w, int h) :
+    Fl_Window(x,y,w,h) {deactivate();}
+};
+
+int Fl_Overlay_Window::can_do_overlay() {
+  return fl_find_overlay_visual() != 0;
+}
+
+void _Fl_Overlay::show() {
+  if (shown()) {Fl_Window::show(); return;}
+  fl_background_pixel = int(fl_transparent_pixel);
+  Fl_X::make_xid(this, fl_overlay_visual, fl_overlay_colormap);
+  fl_background_pixel = -1;
+  // find the outermost window to tell wm about the colormap:
+  Fl_Window *w = window();
+  for (;;) {Fl_Window *w1 = w->window(); if (!w1) break; w = w1;}
+  XSetWMColormapWindows(fl_display, fl_xid(w), &(Fl_X::i(this)->xid), 1);
+}
+
+void _Fl_Overlay::flush() {
+  fl_window = fl_xid(this);
+  if (!gc) gc = XCreateGC(fl_display, fl_xid(this), 0, 0);
+  fl_gc = gc;
+  fl_overlay = 1;
+  Fl_Overlay_Window *w = (Fl_Overlay_Window *)parent();
+  Fl_X *i = Fl_X::i(this);
+  if (damage() != 2) XClearWindow(fl_display, fl_xid(this));
+  fl_clip_region(i->region); i->region = 0;
+  w->draw_overlay();
+  fl_overlay = 0;
+}
+
+void Fl_Overlay_Window::redraw_overlay() {
+  if (!fl_display) return; // this prevents fluid -c from opening display
+  if (!overlay_) {
+    if (can_do_overlay()) {
+      Fl_Group::current(this);
+      overlay_ = new _Fl_Overlay(0,0,w(),h());
+      Fl_Group::current(0);
+    } else {
+      overlay_ = this;	// fake the overlay
+    }
+  }
+  if (shown()) {
+    if (overlay_ == this)
+      damage(8);
+    else if (!overlay_->shown())
+      overlay_->show();
+    else
+      overlay_->redraw();
+  }
+}
+
+#endif
+
+// End of Fl_Overlay_Window.C
diff --git a/src/Fl_Pack.cxx b/src/Fl_Pack.cxx
new file mode 100644
index 000000000..c236f29c6
--- /dev/null
+++ b/src/Fl_Pack.cxx
@@ -0,0 +1,78 @@
+// Fl_Pack.C
+
+// Based on code by Curtis Edwards
+// Group that compresses all it's children together and resizes to surround
+// them on each redraw (only if box() is zero)
+// Bugs: ?
+
+#include 
+#include 
+#include 
+
+Fl_Pack::Fl_Pack(int x,int y,int w ,int h,const char *l)
+: Fl_Group(x, y, w, h, l) {
+  resizable(0);
+  spacing_ = 0;
+  // type(VERTICAL); // already set like this
+}
+
+void Fl_Pack::draw() {
+  int tx = x()+Fl::box_dx(box());
+  int ty = y()+Fl::box_dy(box());
+  int tw = w()-Fl::box_dw(box());
+  int th = h()-Fl::box_dh(box());
+  int current_position = horizontal() ? tx : ty;
+  int maximum_position = current_position;
+  uchar d = damage();
+  Fl_Widget*const* a = array();
+  for (int i = children(); i--;) {
+    Fl_Widget* o = *a++;
+    int X,Y,W,H;
+    if (horizontal()) {
+      X = current_position;
+      W = o->w();
+      Y = ty;
+      H = th;
+    } else {
+      X = tx;
+      W = tw;
+      Y = current_position;
+      H = o->h();
+    }
+    if (spacing_ && current_position>maximum_position &&
+	(X != o->x() || Y != o->y() || d&128)) {
+      fl_color(color());
+      if (horizontal())
+	fl_rectf(maximum_position, ty, spacing_, th);
+      else
+	fl_rectf(tx, maximum_position, tw, spacing_);
+    }
+    if (X != o->x() || Y != o->y() || W != o->w() || H != o->h()) {
+      o->resize(X,Y,W,H);
+      o->clear_damage(~0);
+    }
+    if (d&128) draw_child(*o); else update_child(*o);
+    // child's draw() can change it's size, so use new size:
+    current_position += (horizontal() ? o->w() : o->h());
+    if (current_position > maximum_position)
+      maximum_position = current_position;
+    current_position += spacing_;
+  }
+  if (horizontal()) {
+    if (maximum_position < tx+tw) {
+      fl_color(color());
+      fl_rectf(maximum_position, ty, tx+tw-maximum_position, th);
+    }
+    tw = maximum_position-tx;
+  } else {
+    if (maximum_position < ty+th) {
+      fl_color(color());
+      fl_rectf(tx, maximum_position, tw, ty+th-maximum_position);
+    }
+    th = maximum_position-ty;
+  }
+  tw += Fl::box_dw(box()); if (tw <= 0) tw = 1;
+  th += Fl::box_dh(box()); if (th <= 0) th = 1;
+  if (tw != w() || th != h()) {Fl_Widget::resize(x(),y(),tw,th); d = 128;}
+  if (d&128) draw_box();
+}
diff --git a/src/Fl_Pixmap.cxx b/src/Fl_Pixmap.cxx
new file mode 100644
index 000000000..3e4e1af11
--- /dev/null
+++ b/src/Fl_Pixmap.cxx
@@ -0,0 +1,113 @@
+// Fl_Pixmap.C
+
+// Draws X pixmap data, keeping it stashed in a server pixmap so it
+// redraws fast.
+
+// See fl_draw_pixmap.C for code used to get the actual data into pixmap.
+// Implemented without using the xpm library (which I can't use because
+// it interferes with the color cube used by fl_draw_image).
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+extern uchar **fl_mask_bitmap; // used by fl_draw_pixmap.C to store mask
+void fl_restore_clip(); // in fl_rect.C
+
+void Fl_Pixmap::draw(int X, int Y, int W, int H, int cx,int cy) {
+  if (w<0) fl_measure_pixmap(data, w, h);
+  if (!w) return;
+  // clip the box down to the size of image, quit if empty:
+  if (cx < 0) {W += cx; X -= cx; cx = 0;}
+  if (cx+W > w) W = w-cx;
+  if (W <= 0) return;
+  if (cy < 0) {H += cy; Y -= cy; cy = 0;}
+  if (cy+H > h) H = h-cy;
+  if (H <= 0) return;
+  if (!id) {
+    id = (ulong)fl_create_offscreen(w, h);
+    fl_begin_offscreen((Fl_Offscreen)id);
+#ifdef WIN32 // mask is nyi, instead use a constant color
+    fl_draw_pixmap(data, 0, 0, (Fl_Color)mask);
+#else
+    uchar *bitmap = 0;
+    fl_mask_bitmap = &bitmap;
+    fl_draw_pixmap(data, 0, 0, FL_BLACK);
+    fl_mask_bitmap = 0;
+    if (bitmap) {
+      mask = XCreateBitmapFromData(fl_display, fl_window,
+				   (const char*)bitmap, (w+7)&-8, h);
+      delete[] bitmap;
+    }
+#endif
+    fl_end_offscreen();
+  }
+#ifndef WIN32
+  if (mask) {
+    // I can't figure out how to combine a mask with existing region,
+    // so cut the image down to a clipped rectangle:
+    int nx, ny; fl_clip_box(X,Y,W,H,nx,ny,W,H);
+    cx += nx-X; X = nx;
+    cy += ny-Y; Y = ny;
+    // make X use the bitmap as a mask:
+    XSetClipMask(fl_display, fl_gc, mask);
+    int ox = X-cx; if (ox < 0) ox += w;
+    int oy = Y-cy; if (oy < 0) oy += h;
+    XSetClipOrigin(fl_display, fl_gc, X-cx, Y-cy);
+  }
+#endif
+  fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy);
+#ifndef WIN32
+  if (mask) {
+    // put the old clip region back
+    XSetClipOrigin(fl_display, fl_gc, 0, 0);
+    fl_restore_clip();
+  }
+#endif
+}
+
+Fl_Pixmap::~Fl_Pixmap() {
+  if (id) fl_delete_offscreen((Fl_Offscreen)id);
+#ifndef WIN32
+  if (mask) fl_delete_offscreen((Fl_Offscreen)mask);
+#endif
+}
+
+static void pixmap_labeltype(
+    const Fl_Label* o, int x, int y, int w, int h, Fl_Align a)
+{
+  Fl_Pixmap* b = (Fl_Pixmap*)(o->value);
+  if (b->w<0) fl_measure_pixmap(b->data, b->w, b->h);
+  int cx;
+  if (a & FL_ALIGN_LEFT) cx = 0;
+  else if (a & FL_ALIGN_RIGHT) cx = b->w-w;
+  else cx = (b->w-w)/2;
+  int cy;
+  if (a & FL_ALIGN_TOP) cy = 0;
+  else if (a & FL_ALIGN_BOTTOM) cy = b->h-h;
+  else cy = (b->h-h)/2;
+  b->draw(x,y,w,h,cx,cy);
+}
+
+static void pixmap_measure(const Fl_Label* o, int& w, int& h) {
+  Fl_Pixmap* b = (Fl_Pixmap*)(o->value);
+  if (b->w<0) fl_measure_pixmap(b->data, b->w, b->h);
+  w = b->w;
+  h = b->h;
+}
+
+void Fl_Pixmap::label(Fl_Widget* o) {
+#ifdef WIN32
+  mask = o->color();
+#endif
+  Fl::set_labeltype(_FL_PIXMAP_LABEL, pixmap_labeltype, pixmap_measure);
+  o->label(_FL_PIXMAP_LABEL, (const char*)this);
+}
+
+void Fl_Pixmap::label(Fl_Menu_Item* o) {
+  Fl::set_labeltype(_FL_PIXMAP_LABEL, pixmap_labeltype, pixmap_measure);
+  o->label(_FL_PIXMAP_LABEL, (const char*)this);
+}
diff --git a/src/Fl_Positioner.cxx b/src/Fl_Positioner.cxx
new file mode 100644
index 000000000..017a4ef4d
--- /dev/null
+++ b/src/Fl_Positioner.cxx
@@ -0,0 +1,106 @@
+// Fl_Positioner.C
+
+// The positioner widget from Forms, gives 2D input
+// Written by: Mark Overmars
+
+#include 
+#include 
+#include 
+
+static double flinear(double val, double smin, double smax, double gmin, double gmax)
+{
+  if (smin == smax) return gmax;
+  else return gmin + (gmax - gmin) * (val - smin) / (smax - smin);
+}
+
+void Fl_Positioner::draw(int x, int y, int w, int h) {
+  int x1 = x + 4;
+  int y1 = y + 4;
+  int w1 = w - 2 * 4;
+  int h1 = h - 2 * 4;
+  int xx = int(flinear(xvalue(), xmin, xmax, x1, x1+w1-1)+.5);
+  int yy = int(flinear(yvalue(), ymin, ymax, y1, y1+h1-1)+.5);
+  draw_box(box(), x, y, w, h, color());
+  fl_color(selection_color());
+  fl_xyline(x1, yy, x1+w1);
+  fl_yxline(xx, y1, y1+h1);
+}
+
+void Fl_Positioner::draw() {
+  draw(x(), y(), w(), h());
+  draw_label();
+}
+
+int Fl_Positioner::value(double X, double Y) {
+  clear_changed();
+  if (X == xvalue_ && Y == yvalue_) return 0;
+  xvalue_ = X; yvalue_ = Y;
+  redraw();
+  return 1;
+}
+
+int Fl_Positioner::xvalue(double X) {
+  return(value(X, yvalue_));
+}
+
+int Fl_Positioner::yvalue(double Y) {
+  return(value(xvalue_, Y));
+}
+
+int Fl_Positioner::handle(int event, int x, int y, int w, int h) {
+  switch (event) {
+  case FL_PUSH:
+  case FL_DRAG:
+  case FL_RELEASE: {
+    double x1 = x + 4;
+    double y1 = y + 4;
+    double w1 = w - 2 * 4;
+    double h1 = h - 2 * 4;
+    double X = flinear(Fl::event_x(), x1, x1+w1-1.0, xmin, xmax);
+    if (xstep_) X = int(X/xstep_+0.5) * xstep_;
+    if (X < xmin) X = xmin;
+    if (X > xmax) X = xmax;
+    double Y = flinear(Fl::event_y(), y1, y1+h1-1.0, ymin, ymax);
+    if (ystep_) Y = int(Y/ystep_+0.5) * ystep_;
+    if (Y < ymin) Y = ymin;
+    if (Y > ymax) Y = ymax;
+    if (value(X, Y)) set_changed();}
+    if (!(when() & FL_WHEN_CHANGED ||
+	  when() & FL_WHEN_RELEASE && event == FL_RELEASE)) return 1;
+    if (changed() || when()&FL_WHEN_NOT_CHANGED) {
+      clear_changed(); do_callback();}
+    return 1;
+  default:
+    return 0;
+  }
+}
+
+int Fl_Positioner::handle(int e) {
+  return handle(e, x(), y(), w(), h());
+}
+
+Fl_Positioner::Fl_Positioner(int x, int y, int w, int h, const char* l)
+: Fl_Widget(x, y, w, h, l) {
+  box(FL_DOWN_BOX);
+  selection_color(FL_RED);
+  align(FL_ALIGN_BOTTOM);
+  when(FL_WHEN_CHANGED);
+  xmin = ymin = 0;
+  xmax = ymax = 1;
+  xvalue_ = yvalue_ = .5;
+  xstep_ = ystep_ = 0;
+}
+
+void Fl_Positioner::xbounds(double a, double b) {
+  if (a != xmin || b != xmax) {
+    xmin = a; xmax = b;
+    redraw();
+  }
+}
+
+void Fl_Positioner::ybounds(double a, double b) {
+  if (a != ymin || b != ymax) {
+    ymin = a; ymax = b;
+    redraw();
+  }
+}
diff --git a/src/Fl_Repeat_Button.cxx b/src/Fl_Repeat_Button.cxx
new file mode 100644
index 000000000..e13e05c44
--- /dev/null
+++ b/src/Fl_Repeat_Button.cxx
@@ -0,0 +1,36 @@
+// Fl_Repeat_Button.C
+
+#include 
+#include 
+
+#define INITIALREPEAT .5
+#define REPEAT .1
+
+void Fl_Repeat_Button::repeat_callback(void *v) {
+  Fl_Button *b = (Fl_Button*)v;
+  Fl::add_timeout(REPEAT,repeat_callback,b);
+  b->do_callback();
+}
+
+int Fl_Repeat_Button::handle(int event) {
+  int newval;
+  switch (event) {
+  case FL_RELEASE:
+    newval = 0; goto J1;
+  case FL_PUSH:
+  case FL_DRAG:
+    newval = Fl::event_inside(this);
+  J1:
+    if (value(newval)) {
+      if (newval) {
+	Fl::add_timeout(INITIALREPEAT,repeat_callback,this);
+	do_callback();
+      } else {
+	Fl::remove_timeout(repeat_callback,this);
+      }
+    }
+    return 1;
+  default:
+    return Fl_Button::handle(event);
+  }
+}
diff --git a/src/Fl_Return_Button.cxx b/src/Fl_Return_Button.cxx
new file mode 100644
index 000000000..6d2e224ff
--- /dev/null
+++ b/src/Fl_Return_Button.cxx
@@ -0,0 +1,42 @@
+// Fl_Return_Button.C
+
+#include 
+#include 
+#include 
+
+int fl_return_arrow(int x, int y, int w, int h) {
+  int size = w; if (h
+#include 
+#include 
+#include 
+
+int Fl_Roller::handle(int event) {
+  static int ipos;
+  int newpos = horizontal() ? Fl::event_x() : Fl::event_y();
+  switch (event) {
+  case FL_PUSH:
+    handle_push();
+    ipos = newpos;
+    return 1;
+  case FL_DRAG:
+    handle_drag(clamp(round(increment(previous_value(),newpos-ipos))));
+    return 1;
+  case FL_RELEASE:
+    handle_release();
+    return 1;
+  default:
+    return 0;
+  }
+}
+
+void Fl_Roller::draw() {
+  if (damage()&128) draw_box();
+  int X = x()+Fl::box_dx(box());
+  int Y = y()+Fl::box_dy(box());
+  int W = w()-Fl::box_dw(box())-1;
+  int H = h()-Fl::box_dh(box())-1;
+  int offset = step() ? int(value()/step()) : 0;
+  const double ARC = 1.5; // 1/2 the number of radians visible
+  const double delta = .2; // radians per knurl
+  if (horizontal()) { // horizontal one
+    // draw shaded ends of wheel:
+    int h1 = W/4+1; // distance from end that shading starts
+    fl_color(color()); fl_rectf(X+h1,Y,W-2*h1,H);
+    for (int i=0; h1; i++) {
+      fl_color((Fl_Color)(FL_GRAY-i-1));
+      int h2 = FL_GRAY-i-1 > FL_DARK3 ? 2*h1/3+1 : 0;
+      fl_rectf(X+h2,Y,h1-h2,H);
+      fl_rectf(X+W-h1,Y,h1-h2,H);
+      h1 = h2;
+    }
+    // draw ridges:
+    double junk;
+    for (double y = -ARC+modf(offset*sin(ARC)/(W/2)/delta,&junk)*delta;;
+	 y += delta) {
+      int y1 = int((sin(y)/sin(ARC)+1)*W/2);
+      if (y1 <= 0) continue; else if (y1 >= W-1) break;
+      fl_color(FL_DARK3); fl_yxline(X+y1,Y+1,Y+H-1);
+      if (y < 0) y1--; else y1++;
+      fl_color(FL_LIGHT1);fl_yxline(X+y1,Y+1,Y+H-1);
+    }
+    // draw edges:
+    h1 = W/8+1; // distance from end the color inverts
+    fl_color(FL_DARK2);
+    fl_xyline(X+h1,Y+H-1,X+W-h1);
+    fl_color(FL_DARK3);
+    fl_yxline(X,Y+H,Y,X+h1);
+    fl_xyline(X+W-h1,Y,X+W);
+    fl_color(FL_LIGHT2);
+    fl_xyline(X+h1,Y-1,X+W-h1);
+    fl_yxline(X+W,Y,Y+H,X+W-h1);
+    fl_xyline(X+h1,Y+H,X);
+  } else { // vertical one
+    // draw shaded ends of wheel:
+    int h1 = H/4+1; // distance from end that shading starts
+    fl_color(color()); fl_rectf(X,Y+h1,W,H-2*h1);
+    for (int i=0; h1; i++) {
+      fl_color((Fl_Color)(FL_GRAY-i-1));
+      int h2 = FL_GRAY-i-1 > FL_DARK3 ? 2*h1/3+1 : 0;
+      fl_rectf(X,Y+h2,W,h1-h2);
+      fl_rectf(X,Y+H-h1,W,h1-h2);
+      h1 = h2;
+    }
+    // draw ridges:
+    double junk;
+    for (double y = -ARC+modf(offset*sin(ARC)/(H/2)/delta,&junk)*delta;
+	 ; y += delta) {
+      int y1 = int((sin(y)/sin(ARC)+1)*H/2);
+      if (y1 <= 0) continue; else if (y1 >= H-1) break;
+      fl_color(FL_DARK3); fl_xyline(X+1,Y+y1,X+W-1);
+      if (y < 0) y1--; else y1++;
+      fl_color(FL_LIGHT1);fl_xyline(X+1,Y+y1,X+W-1);
+    }
+    // draw edges:
+    h1 = H/8+1; // distance from end the color inverts
+    fl_color(FL_DARK2);
+    fl_yxline(X+W-1,Y+h1,Y+H-h1);
+    fl_color(FL_DARK3);
+    fl_xyline(X+W,Y,X,Y+h1);
+    fl_yxline(X,Y+H-h1,Y+H);
+    fl_color(FL_LIGHT2);
+    fl_yxline(X,Y+h1,Y+H-h1);
+    fl_xyline(X,Y+H,X+W,Y+H-h1);
+    fl_yxline(X+W,Y+h1,Y);
+  }
+}
+
+Fl_Roller::Fl_Roller(int X,int Y,int W,int H,const char* L)
+  : Fl_Valuator(X,Y,W,H,L) {
+  box(FL_UP_FRAME);
+  step(1,1000);
+}
+
+// end of Fl_Roller.C
diff --git a/src/Fl_Round_Button.cxx b/src/Fl_Round_Button.cxx
new file mode 100644
index 000000000..34a3eab72
--- /dev/null
+++ b/src/Fl_Round_Button.cxx
@@ -0,0 +1,15 @@
+// Fl_Round_Button.C
+
+// A subclass of Fl_Button that always draws as a round circle.  This
+// circle is smaller than the widget size and can be surrounded by
+// another box type, for compatability with Forms.
+
+#include 
+#include 
+
+Fl_Round_Button::Fl_Round_Button(int x,int y,int w,int h, const char *l)
+: Fl_Light_Button(x,y,w,h,l) {
+  box(FL_NO_BOX);
+  down_box(FL_ROUND_DOWN_BOX);
+  selection_color(FL_RED);
+}
diff --git a/src/Fl_Scroll.cxx b/src/Fl_Scroll.cxx
new file mode 100644
index 000000000..b5cc49520
--- /dev/null
+++ b/src/Fl_Scroll.cxx
@@ -0,0 +1,210 @@
+// Fl_Scroll.C
+
+#include 
+#include 
+#include 
+
+// Insure the scrollbars are the last children:
+void Fl_Scroll::fix_scrollbar_order() {
+  Fl_Widget*const* a = array();
+  if (a[children()-1] != &scrollbar) {
+    Fl_Widget** a = (Fl_Widget**)array();
+    int i,j; for (i = j = 0; j < children(); j++)
+      if (a[j] != &hscrollbar && a[j] != &scrollbar) a[i++] = a[j];
+    a[i++] = &hscrollbar;
+    a[i++] = &scrollbar;
+  }
+}
+
+void Fl_Scroll::draw_clip(void* v,int X, int Y, int W, int H) {
+  fl_clip(X,Y,W,H);
+  Fl_Scroll* s = (Fl_Scroll*)v;
+  // erase background if there is a boxtype:
+  if (s->box() && !(s->damage()&128)) {
+    fl_color(s->color());
+    fl_rectf(X,Y,W,H);
+  }
+  Fl_Widget*const* a = s->array();
+  int R = X; int B = Y; // track bottom & right edge of all children
+  for (int i=s->children()-2; i--;) {
+    Fl_Widget& o = **a++;
+    s->draw_child(o);
+    s->draw_outside_label(o);
+    if (o.x()+o.w() > R) R = o.x()+o.w();
+    if (o.y()+o.h() > B) B = o.y()+o.h();
+  }
+  // fill any area to right & bottom of widgets:
+  if (R < X+W && B > Y) {
+    fl_color(s->color());
+    fl_rectf(R,Y,X+W-R,B-Y);
+  }
+  if (B < Y+H) {
+    fl_color(s->color());
+    fl_rectf(X,B,W,Y+H-B);
+  }
+  fl_pop_clip();
+}
+
+void Fl_Scroll::bbox(int& X, int& Y, int& W, int& H) {
+  X = x()+Fl::box_dx(box());
+  Y = y()+Fl::box_dy(box());
+  W = w()-Fl::box_dw(box());
+  H = h()-Fl::box_dh(box());
+  if (scrollbar.visible()) {
+    W -= scrollbar.w();
+    if (scrollbar.align() & FL_ALIGN_LEFT) X += scrollbar.w();
+  }
+  if (hscrollbar.visible()) {
+    H -= hscrollbar.h();
+    if (scrollbar.align() & FL_ALIGN_TOP) Y += hscrollbar.h();
+  }
+}
+
+void Fl_Scroll::draw() {
+  fix_scrollbar_order();
+  int X,Y,W,H; bbox(X,Y,W,H);
+
+  uchar d = damage();
+
+  if (d & 128) { // full redraw
+    draw_box(box(),x(),y(),w(),h(),color());
+    draw_clip(this, X, Y, W, H);
+  } else {
+    if (d & 2) { // scroll the contents:
+      fl_scroll(X, Y, W, H, oldx-xposition_, oldy-yposition_, draw_clip, this);
+    }
+    if (d & 1) { // draw damaged children
+      fl_clip(X, Y, W, H);
+      Fl_Widget*const* a = array();
+      for (int i=children()-2; i--;) update_child(**a++);
+      fl_pop_clip();
+    }
+  }
+
+  // accumulate bounding box of children:
+  int l = X; int r = X; int t = Y; int b = Y;
+  Fl_Widget*const* a = array();
+  for (int i=children()-2; i--;) {
+    Fl_Object* o = *a++;
+    if (o->x() < l) l = o->x();
+    if (o->y() < t) t = o->y();
+    if (o->x()+o->w() > r) r = o->x()+o->w();
+    if (o->y()+o->h() > b) b = o->y()+o->h();
+  }
+
+  // turn the scrollbars on and off as necessary:
+  for (int z = 0; z<2; z++) {
+    if ((type()&VERTICAL) && (type()&ALWAYS_ON || t < Y || b > Y+H)) {
+      if (!scrollbar.visible()) {
+	scrollbar.set_visible();
+	W -= scrollbar.w();
+	d = 128;
+      }
+    } else {
+      if (scrollbar.visible()) {
+	scrollbar.clear_visible();
+	draw_clip(this,
+		  scrollbar.align()&FL_ALIGN_LEFT ? X-scrollbar.w() : X+W,
+		  Y, scrollbar.w(), H);
+	W += scrollbar.w();
+	d = 128;
+      }
+    }
+    if ((type()&HORIZONTAL) && (type()&ALWAYS_ON || l < X || r > X+W)) {
+      if (!hscrollbar.visible()) {
+	hscrollbar.set_visible();
+	H -= hscrollbar.h();
+	d = 128;
+      }
+    } else {
+      if (hscrollbar.visible()) {
+	hscrollbar.clear_visible();
+	draw_clip(this, X,
+		  scrollbar.align()&FL_ALIGN_TOP ? Y-hscrollbar.h() : Y+H,
+		  W, hscrollbar.h());
+	H += hscrollbar.h();
+	d = 128;
+      }
+    }
+  }
+
+  scrollbar.resize(scrollbar.align()&FL_ALIGN_LEFT ? X-scrollbar.w() : X+W,
+		   Y, scrollbar.w(), H);
+  scrollbar.value(oldy = yposition_ = Y, H, t, b-t);
+
+  hscrollbar.resize(X,
+		    scrollbar.align()&FL_ALIGN_TOP ? Y-hscrollbar.h() : Y+H,
+		    W, hscrollbar.h());
+  hscrollbar.value(oldx = xposition_ = X, W, l, r-l);
+
+  // draw the scrollbars:
+  if (d & 128) {
+    draw_child(scrollbar);
+    draw_child(hscrollbar);
+    if (scrollbar.visible() && hscrollbar.visible()) {
+      // fill in the little box in the corner
+      fl_color(color());
+      fl_rectf(scrollbar.x(), hscrollbar.y(), scrollbar.w(), hscrollbar.h());
+    }
+  } else {
+    update_child(scrollbar);
+    update_child(hscrollbar);
+  }
+}
+
+void Fl_Scroll::resize(int X, int Y, int W, int H) {
+  fix_scrollbar_order();
+  // move all the children:
+  Fl_Widget*const* a = array();
+  for (int i=children()-2; i--;) {
+    Fl_Object* o = *a++;
+    o->position(o->x()+X-x(), o->y()+Y-y());
+  }
+  Fl_Widget::resize(X,Y,W,H);
+}
+
+void Fl_Scroll::position(int X, int Y) {
+  int dx = xposition_-X;
+  int dy = yposition_-Y;
+  if (!dx && !dy) return;
+  xposition_ = X;
+  yposition_ = Y;
+  Fl_Widget*const* a = array();
+  for (int i=children(); i--;) {
+    Fl_Widget* o = *a++;
+    if (o == &hscrollbar || o == &scrollbar) continue;
+    o->position(o->x()+dx, o->y()+dy);
+  }
+  damage(2);
+}
+
+void Fl_Scroll::hscrollbar_cb(Fl_Widget* o, void*) {
+  Fl_Scroll* s = (Fl_Scroll*)(o->parent());
+  s->position(int(((Fl_Scrollbar*)o)->value()), s->yposition());
+}
+
+void Fl_Scroll::scrollbar_cb(Fl_Widget* o, void*) {
+  Fl_Scroll* s = (Fl_Scroll*)(o->parent());
+  s->position(s->xposition(), int(((Fl_Scrollbar*)o)->value()));
+}
+
+#define SLIDER_WIDTH 17
+
+Fl_Scroll::Fl_Scroll(int X,int Y,int W,int H,const char* L)
+  : Fl_Group(X,Y,W,H,L), 
+    scrollbar(X+W-SLIDER_WIDTH,Y,SLIDER_WIDTH,H-SLIDER_WIDTH),
+    hscrollbar(X,Y+H-SLIDER_WIDTH,W-SLIDER_WIDTH,SLIDER_WIDTH) {
+  type(BOTH);
+  xposition_ = 0;
+  yposition_ = 0;
+  hscrollbar.type(FL_HORIZONTAL);
+  hscrollbar.callback(hscrollbar_cb);
+  scrollbar.callback(scrollbar_cb);
+}
+
+int Fl_Scroll::handle(int event) {
+  fix_scrollbar_order();
+  return Fl_Group::handle(event);
+}
+
+// end of Fl_Scroll.C
diff --git a/src/Fl_Scrollbar.cxx b/src/Fl_Scrollbar.cxx
new file mode 100644
index 000000000..4863d9431
--- /dev/null
+++ b/src/Fl_Scrollbar.cxx
@@ -0,0 +1,158 @@
+// Fl_Scrollbar.C
+
+#include 
+#include 
+#include 
+#include 
+
+#define INITIALREPEAT .5
+#define REPEAT .05
+
+void Fl_Scrollbar::increment_cb() {
+  handle_drag(clamp(value() + (
+	((pushed_>1) == (maximum()>=minimum())) ? linesize_ : -linesize_)));
+}
+
+void Fl_Scrollbar::timeout_cb(void* v) {
+  Fl_Scrollbar* s = (Fl_Scrollbar*)v;
+  s->increment_cb();
+  Fl::add_timeout(REPEAT, timeout_cb, s);
+}
+
+int Fl_Scrollbar::handle(int event) {
+  if (!pushed_) {
+    if (horizontal()) {
+      if (w() < 3*h()) return Fl_Slider::handle(event);
+      if (Fl_Slider::handle(event, x()+h(), y(), w()-2*h(), h())) return 1;
+    } else {
+      if (h() < 3*w()) return Fl_Slider::handle(event);
+      if (Fl_Slider::handle(event, x(), y()+w(), w(), h()-2*w())) return 1;
+    }
+  }
+  switch (event) {
+  case FL_RELEASE:
+    if (pushed_) {
+      Fl::remove_timeout(timeout_cb, this);
+      pushed_ = 0;
+      redraw();
+    }
+    handle_release();
+    return 1;
+  case FL_PUSH:
+    if (horizontal()) {
+      if (Fl::event_inside(x(), y(), h(), h())) pushed_ = 1;
+      if (Fl::event_inside(x()+w()-h(), y(), h(), h())) pushed_ = 2;
+    } else {
+      if (Fl::event_inside(x(), y(), w(), w())) pushed_ = 1;
+      if (Fl::event_inside(x(), y()+h()-w(), w(), w())) pushed_ = 2;
+    }
+    if (pushed_) {
+      handle_push();
+      Fl::add_timeout(INITIALREPEAT, timeout_cb, this);
+      increment_cb();
+      redraw();
+    }
+    return 1;
+  case FL_DRAG:
+    return pushed_;
+  case FL_SHORTCUT: {
+    int v = value();
+    int ls = maximum()>=minimum() ? linesize_ : -linesize_;
+    if (horizontal()) {
+      switch (Fl::event_key()) {
+      case FL_Left:
+	v -= ls;
+	break;
+      case FL_Right:
+	v += ls;
+	break;
+      default:
+	return 0;
+      }
+    } else { // vertical
+      switch (Fl::event_key()) {
+      case FL_Up:
+	v -= ls;
+	break;
+      case FL_Down:
+	v += ls;
+	break;
+      case FL_Page_Up:
+	if (slider_size() >= 1.0) return 0;
+	v -= int((maximum()-minimum())*slider_size()/(1.0-slider_size()));
+	v += ls;
+	break;
+      case FL_Page_Down:
+	if (slider_size() >= 1.0) return 0;
+	v += int((maximum()-minimum())*slider_size()/(1.0-slider_size()));
+	v -= ls;
+	break;
+      case FL_Home:
+	v = int(minimum());
+	break;
+      case FL_End:
+	v = int(maximum());
+	break;
+      default:
+	return 0;
+      }
+    }
+    v = int(clamp(v));
+    if (v != value()) {
+      Fl_Slider::value(v);
+      value_damage();
+      do_callback();
+    }
+    return 1;}
+  }
+  return 0;
+}
+
+void Fl_Scrollbar::draw() {
+  if (horizontal()) {
+    if (w() < 3*h()) {Fl_Slider::draw(); return;}
+    Fl_Slider::draw(x()+h(), y(), w()-2*h(), h());
+    if (damage()&128) {
+      draw_box((pushed_&1) ? down(slider()) : slider(),
+	       x(), y(), h(), h(), selection_color());
+      draw_box((pushed_&2) ? down(slider()) : slider(),
+		  x()+w()-h(), y(), h(), h(), selection_color());
+      fl_color(labelcolor());
+      int w1 = (h()-1)|1; // use odd sizes only
+      int Y = y()+w1/2;
+      int W = w1/3;
+      int X = x()+w1/2+W/2;
+      fl_polygon(X-W, Y, X, Y-W, X, Y+W);
+      X = x()+w()-(X-x())-1;
+      fl_polygon(X+W, Y, X, Y+W, X, Y-W);
+    }
+  } else { // vertical
+    if (h() < 3*w()) {Fl_Slider::draw(); return;}
+    Fl_Slider::draw(x(), y()+w(), w(), h()-2*w());
+    if (damage()&128) {
+      draw_box((pushed_&1) ? down(slider()) : slider(),
+	       x(), y(), w(), w(), selection_color());
+      draw_box((pushed_&2) ? down(slider()) : slider(),
+	       x(), y()+h()-w(), w(), w(), selection_color());
+      fl_color(labelcolor());
+      int w1 = (w()-1)|1; // use odd sizes only
+      int X = x()+w1/2;
+      int W = w1/3;
+      int Y = y()+w1/2+W/2;
+      fl_polygon(X, Y-W, X+W, Y, X-W, Y);
+      Y = y()+h()-(Y-y())-1;
+      fl_polygon(X, Y+W, X-W, Y, X+W, Y);
+    }
+  }
+}
+
+Fl_Scrollbar::Fl_Scrollbar(int X, int Y, int W, int H, const char* L)
+  : Fl_Slider(X, Y, W, H, L)
+{
+  box(FL_FLAT_BOX);
+  color(FL_DARK2);
+  slider(FL_UP_BOX);
+  linesize_ = 16;
+  pushed_ = 0;
+  step(1);
+}
diff --git a/src/Fl_Single_Window.cxx b/src/Fl_Single_Window.cxx
new file mode 100644
index 000000000..6bfe091a5
--- /dev/null
+++ b/src/Fl_Single_Window.cxx
@@ -0,0 +1,14 @@
+/*	Fl_Single_Window.H
+
+	A window with a single-buffered context
+
+	This is provided for systems where the base class is double
+	buffered.  You can turn it off using this subclass in case
+	your display looks better without it.
+
+*/
+
+#include 
+
+void Fl_Single_Window::show() {Fl_Window::show();}
+void Fl_Single_Window::flush() {Fl_Window::flush();}
diff --git a/src/Fl_Slider.cxx b/src/Fl_Slider.cxx
new file mode 100644
index 000000000..6d062a608
--- /dev/null
+++ b/src/Fl_Slider.cxx
@@ -0,0 +1,200 @@
+// Fl_Slider.C
+
+#include 
+#include 
+#include 
+#include 
+
+void Fl_Slider::_Fl_Slider() {
+  slider_size_ = 0;
+  slider_ = 0; // FL_UP_BOX;
+}
+
+Fl_Slider::Fl_Slider(int x, int y, int w, int h, const char* l)
+: Fl_Valuator(x, y, w, h, l) {
+  box(FL_DOWN_BOX);
+  _Fl_Slider();
+}
+
+Fl_Slider::Fl_Slider(uchar t, int x, int y, int w, int h, const char* l)
+  : Fl_Valuator(x, y, w, h, l) {
+  type(t);
+  box(t==FL_HOR_NICE_SLIDER || t==FL_VERT_NICE_SLIDER ?
+      FL_FLAT_BOX : FL_DOWN_BOX);
+  _Fl_Slider();
+}
+
+void Fl_Slider::slider_size(double v) {
+  if (v <  0) v = 0;
+  if (v > 1) v = 1;
+  if (slider_size_ != float(v)) {slider_size_ = float(v); damage(2);}
+}
+
+void Fl_Slider::bounds(double a, double b) {
+  if (minimum() != a || maximum() != b) {Fl_Valuator::bounds(a, b); damage(2);}
+}
+
+int Fl_Slider::scrollvalue(int p, int w, int t, int l) {
+//	p = position, first line displayed
+//	w = window, number of lines displayed
+//	t = top, number of first line
+//	l = length, total number of lines
+  step(1, 1);
+  if (p+w > t+l) l = p+w-t;
+  slider_size(w >= l ? 1.0 : double(w)/double(l));
+  bounds(t, l-w+t);
+  return value(p);
+}
+
+// All slider interaction is done as though the slider ranges from
+// zero to one, and the left (bottom) edge of the slider is at the
+// given position.  Since when the slider is all the way to the
+// right (top) the left (bottom) edge is not all the way over, a
+// position on the widget itself covers a wider range than 0-1,
+// actually it ranges from 0 to 1/(1-size).
+
+void Fl_Slider::draw_bg(int x, int y, int w, int h) {
+  draw_box(box(), x, y, w, h, color());
+  int BW = Fl::box_dx(box());
+  if (type() == FL_VERT_NICE_SLIDER) {
+    draw_box(FL_THIN_DOWN_BOX, x+w/2-2, y+BW, 4, h-2*BW, FL_BLACK);
+  } else if (type() == FL_HOR_NICE_SLIDER) {
+    draw_box(FL_THIN_DOWN_BOX, x+BW, y+h/2-2, w-2*BW, 4, FL_BLACK);
+  }
+}
+
+void Fl_Slider::draw(int x, int y, int w, int h) {
+  double val;
+
+  if (minimum() == maximum())
+    val = 0.5;
+  else {
+    val = (value()-minimum())/(maximum()-minimum());
+    if (val > 1.0) val = 1.0;
+    else if (val < 0.0) val = 0.0;
+  }
+
+  int BW = Fl::box_dx(box());
+  int W = (horizontal() ? w : h) - 2*BW;
+  int X, S;
+  if (type()==FL_HOR_FILL_SLIDER || type() == FL_VERT_FILL_SLIDER) {
+    S = int(val*W+.5);
+    if (minimum()>maximum()) {S = W-S; X = h-BW-S;}
+    else X = BW;
+  } else {
+    S = int(slider_size_*W+.5);
+    int T = (horizontal() ? h : w)/2-BW+1;
+    if (type()==FL_VERT_NICE_SLIDER || type()==FL_HOR_NICE_SLIDER) T += 4;
+    if (S < T) S = T;
+    X = BW+int(val*(W-S)+.5);
+  }
+  int xsl, ysl, wsl, hsl;
+  if (horizontal()) {
+    xsl = x+X;
+    wsl = S;
+    ysl = y+BW;
+    hsl = h-2*BW;
+  } else {
+    ysl = y+X;
+    hsl = S;
+    xsl = x+BW;
+    wsl = w-2*BW;
+  }
+
+  if (damage()&128) { // complete redraw
+    draw_bg(x, y, w, h);
+  } else { // partial redraw, clip off new position of slider
+    if (X > BW) {
+      if (horizontal()) fl_clip(x, ysl, X, hsl);
+      else fl_clip(xsl, y, wsl, X);
+      draw_bg(x, y, w, h);
+      fl_pop_clip();
+    }
+    if (X+S < W+BW) {
+      if (horizontal()) fl_clip(xsl+wsl, ysl, x+w-BW-xsl-wsl, hsl);
+      else fl_clip(xsl, ysl+hsl, wsl, y+h-BW-ysl-hsl);
+      draw_bg(x, y, w, h);
+      fl_pop_clip();
+    }
+  }
+
+  Fl_Boxtype box1 = slider();
+  if (!box1) {box1 = (Fl_Boxtype)(box()&-2); if (!box1) box1 = FL_UP_BOX;}
+  if (type() == FL_VERT_NICE_SLIDER) {
+    draw_box(box1, xsl, ysl, wsl, hsl, FL_GRAY);
+    int d = (hsl-4)/2;
+    draw_box(FL_THIN_DOWN_BOX, xsl+2, ysl+d, wsl-4, hsl-2*d,selection_color());
+  } else if (type() == FL_HOR_NICE_SLIDER) {
+    draw_box(box1, xsl, ysl, wsl, hsl, FL_GRAY);
+    int d = (wsl-4)/2;
+    draw_box(FL_THIN_DOWN_BOX, xsl+d, ysl+2, wsl-2*d, hsl-4,selection_color());
+  } else {
+    if (wsl>0 && hsl>0) draw_box(box1, xsl, ysl, wsl, hsl, selection_color());
+  }
+
+  draw_label(xsl, ysl, wsl, hsl);
+}
+
+void Fl_Slider::draw() {
+  draw(x(), y(), w(), h());
+}
+
+int Fl_Slider::handle(int event, int x, int y, int w, int h) {
+  switch (event) {
+  case FL_PUSH:
+    if (!Fl::event_inside(x, y, w, h)) return 0;
+    handle_push();
+  case FL_DRAG: {
+    if (slider_size() >= 1 || minimum()==maximum()) return 1;
+    int BW = Fl::box_dx(box());
+    int W = (horizontal() ? w : h) - 2*BW;
+    int X = (horizontal() ? Fl::event_x()-x : Fl::event_y()-y) - BW;
+    int S = int(slider_size_*W+.5);
+    int T = (horizontal() ? h : w)/2-BW+1;
+    if (type()==FL_VERT_NICE_SLIDER || type()==FL_HOR_NICE_SLIDER) T += 4;
+    if (S < T) S = T;
+    double v = double(X)/(W-S);
+    double sliderwidth = double(S)/(W-S);
+    double val = (value()-minimum())/(maximum()-minimum());
+    static double offcenter;
+    if (event == FL_PUSH) {
+      offcenter = v-val;
+      if (offcenter < 0) offcenter = 0;
+      else if (offcenter > sliderwidth) offcenter = sliderwidth;
+      else return 1;
+    }
+  TRY_AGAIN:
+    v -= offcenter;
+    if (v < 0) {
+      offcenter = v+offcenter;
+      if (offcenter<0) offcenter=0;
+      v = 0;
+    } else if (v > 1) {
+      offcenter =  v+offcenter-1;
+      if (offcenter > sliderwidth) offcenter = sliderwidth;
+      v = 1;
+    }
+    // if (Fl::event_state(FL_SHIFT)) v = val+(v-val)*.05;
+    v = round(v*(maximum()-minimum())+minimum());
+    // make sure a click outside the sliderbar moves it:
+    if (event == FL_PUSH && v == value()) {
+      offcenter = sliderwidth/2;
+      v = double(X)/(W-S);
+      event = FL_DRAG;
+      goto TRY_AGAIN;
+    }
+    handle_drag(clamp(v));
+    } return 1;
+  case FL_RELEASE:
+    handle_release();
+    return 1;
+  default:
+    return 0;
+  }
+}
+
+int Fl_Slider::handle(int event) {
+  return handle(event, x(), y(), w(), h());
+}
+
+// End of Fl_Slider.C
diff --git a/src/Fl_Tabs.cxx b/src/Fl_Tabs.cxx
new file mode 100644
index 000000000..44e2d7ecf
--- /dev/null
+++ b/src/Fl_Tabs.cxx
@@ -0,0 +1,234 @@
+// Fl_Tabs.C
+
+// This is the "file card tabs" interface to allow you to put lots and lots
+// of buttons and switches in a panel, as popularized by many toolkits.
+
+// Each child widget is a card, and it's label() is printed on the card tab.
+// Clicking the tab makes that card visible.
+
+#include 
+#include 
+#include 
+
+#define BORDER 10
+#define TABSLOPE 8
+
+// return the left edges of each tab (plus a fake left edge for a tab
+// past the right-hand one).  These position are actually of the left
+// edge of the slope.  They are either seperated by the correct distance
+// or by TABSLOPE or by zero.
+// Return value is the index of the selected item.
+
+int Fl_Tabs::tab_positions(int* p, int* w) {
+  int selected = 0;
+  Fl_Widget*const* a = array();
+  int i;
+  p[0] = 0;
+  for (i=0; ilabel()) {
+      int wt = 0; int ht = 0; o->measure_label(wt,ht);
+      w[i] = wt+TABSLOPE;
+    } else 
+      w[i] = 2*TABSLOPE;
+    p[i+1] = p[i]+w[i];
+  }
+  int r = this->w()-TABSLOPE-1;
+  if (p[i] <= r) return selected;
+  // uh oh, they are too big:
+  // pack them against right edge:
+  p[i] = r;
+  for (i = children(); i--;) {
+    int l = r-w[i];
+    if (p[i+1]-TABSLOPE < l) l = p[i+1]-TABSLOPE;
+    if (p[i] <= l) break;
+    p[i] = l;
+    r -= TABSLOPE;
+  }
+  // pack them against left edge and truncate width if they still don't fit:
+  for (i = 0; i= i*TABSLOPE) break;
+    p[i] = i*TABSLOPE;
+    int W = this->w()-1-TABSLOPE*(children()-i) - p[i];
+    if (w[i] > W) w[i] = W;
+  }
+  // adjust edges according to visiblity:
+  for (i = children(); i > selected; i--) {
+    p[i] = p[i-1]+w[i-1];
+  }
+  return selected;
+}
+
+// return space needed for tabs.  Negative to put them on the bottom:
+int Fl_Tabs::tab_height() {
+  int H = h();
+  int H2 = y();
+  Fl_Widget*const* a = array();
+  for (int i=children(); i--;) {
+    Fl_Widget* o = *a++;
+    if (o->y() < y()+H) H = o->y()-y();
+    if (o->y()+o->h() > H2) H2 = o->y()+o->h();
+  }
+  H2 = y()+h()-H2;
+  if (H2 > H) {
+    H = H2-Fl::box_dy(box());
+    return (H <= 0) ? 0 : -H;
+  } else {
+    H = H-Fl::box_dy(box());
+    return (H <= 0) ? 0 : H;
+  }
+}
+
+// this is used by fluid to pick tabs:
+Fl_Widget *Fl_Tabs::which(int event_x, int event_y) {
+  int H = tab_height();
+  if (H < 0) {
+    if (event_y > y()+h() || event_y < y()+h()+H) return 0;
+  } else {
+    if (event_y > y()+H || event_y < y()) return 0;
+  }
+  if (event_x < x()) return 0;
+  int p[128], w[128];
+  int selected = tab_positions(p, w);
+  int d = (event_y-(H>=0?y():y()+h()))*TABSLOPE/H;
+  for (int i=0; i= 0) {
+      if (Fl::event_y() > y()+H) goto DEFAULT;
+    } else {
+      if (Fl::event_y() < y()+h()+H) goto DEFAULT;
+    }}
+  case FL_DRAG:
+  case FL_RELEASE:
+    o = which(Fl::event_x(), Fl::event_y());
+    if (event == FL_RELEASE) {push(0); if (o) value(o);}
+    else push(o);
+    return 1;
+
+  default:
+  DEFAULT:
+    value(); // initialize value & visibility if value_ == 0
+    return Fl_Group::handle(event);
+
+  }
+}
+
+int Fl_Tabs::push(Fl_Widget *o) {
+  if (push_ == o) return 0;
+  if (push_ && push_ != value_ || o && o != value_) damage(2);
+  push_ = o;
+  return 1;
+}
+
+Fl_Widget* Fl_Tabs::value() {
+  Fl_Widget *v = value_;
+  if (!v) {
+    // If value() has not been called, find first visible() child:
+    Fl_Widget*const* a = array();
+    for (int i=children(); i--;) {
+      Fl_Widget* o = *a++;
+      if (v) o->hide();
+      else if (o->visible()) v = o;
+    }
+    if (!v) return 0; // no children...
+    value_ = v;
+  }
+  return v;
+}
+
+int Fl_Tabs::value(Fl_Widget *o) {
+  if (value_ == o) return 0;
+  if (o) o->show();
+  if (value_) value_->hide();
+  value_ = o;
+  redraw();
+  do_callback();
+  return 1;
+}
+
+enum {LEFT, RIGHT, SELECTED};
+
+void Fl_Tabs::draw() {
+  Fl_Widget *v = value();
+  int H = tab_height();
+  if (damage() & ~3) { // redraw the entire thing:
+    fl_clip(x(), y()+(H>=0?H:0), w(), h()-(H>=0?H:-H));
+    draw_box(box(), x(), y(), w(), h(), v->color());
+    fl_pop_clip();
+    draw_child(*v);
+  } else { // redraw the child
+    update_child(*v);
+  }
+  if (damage() & 2) {
+    int p[128]; int w[128];
+    int selected = tab_positions(p,w);
+    int i;
+    Fl_Widget*const* a = array();
+    for (i=0; i selected; i--)
+      draw_tab(x()+p[i], x()+p[i+1], w[i], H, a[i], RIGHT);
+    i = selected;
+    draw_tab(x()+p[i], x()+p[i+1], w[i], H, a[i], SELECTED);
+  }
+}
+
+void Fl_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) {
+  if (x2 < x1+W) {
+    if (what == LEFT) {
+      if (x1+W < x2+TABSLOPE) x2 = x1+W;
+      else x2 += TABSLOPE;
+    } else {
+      if (x1+W < x2+TABSLOPE) x1 = x2-W;
+      else x1 -= TABSLOPE;
+    }
+  }
+  int sel = (what == SELECTED);
+  fl_color(o->color());
+  if (H >= 0) {
+    fl_polygon(x1, y()+H+sel, x1+TABSLOPE, y(), x2, y(),
+	       x2+TABSLOPE, y()+H+sel);
+    fl_color(!sel && o==push_ ? FL_DARK3 : FL_LIGHT3);
+    fl_line(x1, y()+H, x1+TABSLOPE, y(), x2, y());
+    if (sel) {
+      if (x1>x()) fl_xyline(x(), y()+H, x1);
+      if (x2+TABSLOPE < x()+w()-1) fl_xyline(x2+TABSLOPE, y()+H, x()+w()-1);
+    }
+    fl_color(!sel && o==push_ ? FL_LIGHT3 : FL_DARK3);
+    fl_line(x2, y(), x2+TABSLOPE, y()+H);
+  } else {
+    fl_polygon(x1, y()+h()+H-sel, x1+TABSLOPE, y()+h(), x2, y()+h(),
+	       x2+TABSLOPE, y()+h()+H-sel);
+    fl_color(!sel && o==push_ ? FL_LIGHT3 : FL_DARK3);
+    fl_line(x1+TABSLOPE, y()+h()-1, x2, y()+h()-1, x2+TABSLOPE, y()+h()+H);
+    if (sel) {
+      if (x1>x()) fl_xyline(x(), y()+h()+H, x1);
+      if (x2+TABSLOPE < x()+w()-1) fl_xyline(x2+TABSLOPE, y()+h()+H,x()+w()-1);
+    }
+    fl_color(!sel && o==push_ ? FL_DARK3 : FL_LIGHT3);
+    fl_line(x1, y()+h()+H, x1+TABSLOPE, y()+h()-1);
+  }
+  if (x2-x1 > 2*TABSLOPE)
+    o->draw_label(what==LEFT ? x1+TABSLOPE : x2-W+TABSLOPE,
+		  y()+(H<0?h()+H-3:0), W-TABSLOPE,
+		  (H<0?-H:H)+3, FL_ALIGN_CENTER);
+}
+
+Fl_Tabs::Fl_Tabs(int X,int Y,int W, int H, const char *l) :
+  Fl_Group(X,Y,W,H,l) {
+    box(FL_THIN_UP_BOX);
+    value_ = push_ = 0;
+}
diff --git a/src/Fl_Tile.cxx b/src/Fl_Tile.cxx
new file mode 100644
index 000000000..d422b844d
--- /dev/null
+++ b/src/Fl_Tile.cxx
@@ -0,0 +1,173 @@
+// Fl_Tile.C - Group of 2 or 4 "tiles" that can be resized by dragging border
+
+// The size of the first child determines where the resize border is.
+// The resizebox is used to limit where the border can be dragged to.
+
+#include 
+#include 
+#include 
+#include 
+
+// Drag the edges that were initially at oldx,oldy to newx,newy:
+// pass zero as oldx or oldy to disable drag in that direction:
+
+void Fl_Tile::position(int oix, int oiy, int newx, int newy) {
+  Fl_Widget*const* a = array();
+  short* p = sizes();
+  p += 8; // skip group & resizable's saved size
+  for (int i=children(); i--;) {
+    Fl_Widget* o = *a++;
+    if (o == resizable()) continue;
+    int X = o->x();
+    int R = X+o->w();
+    if (oix) {
+      int t = p[0];
+      if (t == oix || t>oix && Xnewx) X = newx;
+      t = p[1];
+      if (t == oix || t>oix && Rnewx) R = newx;
+    }
+    int Y = o->y();
+    int B = Y+o->h();
+    if (oiy) {
+      int t = p[2];
+      if (t == oiy || t>oiy && Ynewy) Y = newy;
+      t = p[3];
+      if (t == oiy || t>oiy && Bnewy) B = newy;
+    }
+    o->damage_resize(X,Y,R-X,B-Y);
+    p += 4;
+  }
+}
+
+// move the lower-right corner (sort of):
+void Fl_Tile::resize(int X,int Y,int W,int H) {
+  // remember how much to move the child widgets:
+  int dx = X-x();
+  int dy = Y-y();
+  int dw = W-w();
+  int dh = H-h();
+  short* p = sizes();
+  // resize this (skip the Fl_Group resize):
+  Fl_Widget::resize(X,Y,W,H);
+  // find bottom-right of resiable:
+  int OR = p[5];
+  int NR = X+W-(p[1]-OR);
+  int OB = p[7];
+  int NB = Y+H-(p[3]-OB);
+  // move everything to be on correct side of new resizable:
+  Fl_Widget*const* a = array();
+  p += 8;
+  for (int i=children(); i--;) {
+    Fl_Widget* o = *a++;
+    int X = o->x()+dx;
+    int R = X+o->w();
+    if (*p++ >= OR) X += dw; else if (X > NR) X = NR;
+    if (*p++ >= OR) R += dw; else if (R > NR) R = NR;
+    int Y = o->y()+dy;
+    int B = Y+o->h();
+    if (*p++ >= OB) Y += dh; else if (Y > NB) Y = NB;
+    if (*p++ >= OB) B += dh; else if (B > NB) B = NB;
+    o->resize(X,Y,R-X,B-Y); o->redraw();
+  }
+}
+
+static void set_cursor(Fl_Tile*t, Fl_Cursor c) {
+  static Fl_Cursor cursor;
+  if (cursor == c) return;
+  cursor = c;
+#ifdef __sgi
+  t->window()->cursor(c,FL_RED,FL_WHITE);
+#else
+  t->window()->cursor(c);
+#endif
+}
+
+static Fl_Cursor cursors[4] = {
+  FL_CURSOR_DEFAULT,
+  FL_CURSOR_WE,
+  FL_CURSOR_NS,
+  FL_CURSOR_MOVE};
+
+int Fl_Tile::handle(int event) {
+  static int sdrag;
+  static int sdx, sdy;
+  static int sx, sy;
+#define DRAGH 1
+#define DRAGV 2
+#define GRABAREA 4
+
+  int mx = Fl::event_x();
+  int my = Fl::event_y();
+
+  switch (event) {
+
+  case FL_MOVE:
+  case FL_ENTER:
+  case FL_PUSH: {
+    int mindx = 100;
+    int mindy = 100;
+    int oldx = 0;
+    int oldy = 0;
+    Fl_Widget*const* a = array();
+    short* q = sizes();
+    short* p = q+8;
+    for (int i=children(); i--; p += 4) {
+      Fl_Widget* o = *a++;
+      if (o == resizable()) continue;
+      if (p[1]y()<=my+GRABAREA && o->y()+o->h()>=my-GRABAREA) {
+	int t = mx - (o->x()+o->w());
+	if (abs(t) < mindx) {
+	  sdx = t;
+	  mindx = abs(t);
+	  oldx = p[1];
+	}
+      }
+      if (p[3]x()<=mx+GRABAREA && o->x()+o->w()>=mx-GRABAREA) {
+	int t = my - (o->y()+o->h());
+	if (abs(t) < mindy) {
+	  sdy = t;
+	  mindy = abs(t);
+	  oldy = p[3];
+	}
+      }
+    }
+    sdrag = 0; sx = sy = 0;
+    if (mindx <= GRABAREA) {sdrag = DRAGH; sx = oldx;}
+    if (mindy <= GRABAREA) {sdrag |= DRAGV; sy = oldy;}
+    set_cursor(this, cursors[sdrag]);
+    if (sdrag) return 1;
+    return Fl_Group::handle(event);
+  }
+
+  case FL_LEAVE:
+    set_cursor(this, FL_CURSOR_DEFAULT);
+    break;
+
+  case FL_DRAG:
+    if (damage()) return 1; // don't fall behind
+  case FL_RELEASE: {
+    if (!sdrag) return 0; // should not happen
+    Fl_Widget* r = resizable(); if (!r) r = this;
+    int newx;
+    if (sdrag&DRAGH) {
+      newx = Fl::event_x()-sdx;
+      if (newx < r->x()) newx = r->x();
+      else if (newx > r->x()+r->w()) newx = r->x()+r->w();
+    } else
+      newx = sx;
+    int newy;
+    if (sdrag&DRAGV) {
+      newy = Fl::event_y()-sdy;
+      if (newy < r->y()) newy = r->y();
+      else if (newy > r->y()+r->h()) newy = r->y()+r->h();
+    } else
+      newy = sy;
+    position(sx,sy,newx,newy);
+    return 1;}
+
+  }
+
+  return Fl_Group::handle(event);
+}
+
+// end of Fl_Tile.C
diff --git a/src/Fl_Valuator.cxx b/src/Fl_Valuator.cxx
new file mode 100644
index 000000000..a39513c37
--- /dev/null
+++ b/src/Fl_Valuator.cxx
@@ -0,0 +1,100 @@
+// Fl_Valuator.C
+
+// Base class for sliders and all other one-value "knobs"
+
+#include 
+#include 
+#include 
+#include 
+
+Fl_Valuator::Fl_Valuator(int X, int Y, int W, int H, const char* L)
+  : Fl_Widget(X,Y,W,H,L) {
+  align(FL_ALIGN_BOTTOM);
+  when(FL_WHEN_CHANGED);
+  value_ = 0;
+  min = 0;
+  max = 1;
+  A = 0.0;
+  B = 1;
+}
+
+const double epsilon = 1e-12 ;
+
+void Fl_Valuator::step(double s) {
+  if (s < 0) s = -s;
+  A = rint(s);
+  B = 1;
+  while (fabs(s-A/B) > epsilon) {B *= 10; A = rint(s*B);}
+}
+
+void Fl_Valuator::precision(int p) {
+  A = 1.0;
+  for (B = 1; p--;) B *= 10;
+}
+
+void Fl_Valuator::value_damage() {damage(2);} // by default do partial-redraw
+
+int Fl_Valuator::value(double v) {
+  clear_changed();
+  if (v == value_) return 0;
+  value_ = v;
+  value_damage();
+  return 1;
+}
+
+double Fl_Valuator::softclamp(double v) {
+  int which = (min<=max);
+  double p = previous_value_;
+  if ((vmax)==which && p!=max && (p>max)!=which) return max;
+  else return v;
+}
+
+// inline void Fl_Valuator::handle_push() {previous_value_ = value_;}
+
+void Fl_Valuator::handle_drag(double v) {
+  if (v != value_) {
+    value_ = v;
+    value_damage();
+    if (when() & FL_WHEN_CHANGED) do_callback();
+    else set_changed();
+  }
+}
+
+void Fl_Valuator::handle_release() {
+  if (when()&FL_WHEN_RELEASE) {
+    // insure changed() is off even if no callback is done.  It may have
+    // been turned on by the drag, and then the slider returned to it's
+    // initial position:
+    clear_changed();
+    // now do the callback only if slider in new position or always is on:
+    if (value_ != previous_value_ || when() & FL_WHEN_NOT_CHANGED)
+      do_callback();
+  }
+}
+
+double Fl_Valuator::round(double v) {
+  if (A) return rint(v*B/A)*A/B;
+  else return v;
+}
+
+double Fl_Valuator::clamp(double v) {
+  if ((vmax)==(min<=max)) return max;
+  else return v;
+}
+
+double Fl_Valuator::increment(double v, int n) {
+  if (!A) return v+n*(max-min)/100;
+  if (min > max) n = -n;
+  return (rint(v*B/A)+n)*A/B;
+}
+
+int Fl_Valuator::format(char* buffer) {
+  double v = value();
+  if (!A || B==1) return sprintf(buffer, "%g", v);
+  int i, x;
+  for (x = 10, i = 2; x < B; x *= 10) i++;
+  if (x == B) i--;
+  return sprintf(buffer, "%.*f", i, v);
+}
diff --git a/src/Fl_Value_Input.cxx b/src/Fl_Value_Input.cxx
new file mode 100644
index 000000000..c9cf28db1
--- /dev/null
+++ b/src/Fl_Value_Input.cxx
@@ -0,0 +1,100 @@
+// Fl_Value_Input.C
+
+// Fltk widget for drag-adjusting a floating point value.
+
+// Warning: this works by making a child Fl_Input object, even
+// though this object is *not* an Fl_Group.  May be a kludge?
+
+#include 
+#include 
+#include 
+#include 
+
+void Fl_Value_Input::input_cb(Fl_Widget*, void* v) {
+  Fl_Value_Input& t = *(Fl_Value_Input*)v;
+  double nv;
+  if (t.step()>=1.0) nv = strtol(t.input.value(), 0, 0);
+  else nv = strtod(t.input.value(), 0);
+  t.handle_push();
+  t.handle_drag(nv);
+  t.handle_release();
+}
+
+void Fl_Value_Input::draw() {
+  if (damage()&~1) input.clear_damage(~0);
+  input.box(box());
+  input.color(color(), selection_color());
+  input.draw();
+  input.clear_damage();
+}
+
+void Fl_Value_Input::resize(int X, int Y, int W, int H) {
+  Fl_Valuator::resize(X, Y, W, H);
+  input.resize(X, Y, W, H);
+}
+
+void Fl_Value_Input::value_damage() {
+  char buf[128];
+  format(buf);
+  input.value(buf);
+  input.mark(input.position()); // turn off selection highlight
+}
+
+int Fl_Value_Input::handle(int event) {
+  double v;
+  int delta;
+  int mx = Fl::event_x();
+  static int ix, drag;
+  switch (event) {
+  case FL_PUSH:
+    if (!step()) goto DEFAULT;
+    ix = mx;
+    drag = Fl::event_button();
+    handle_push();
+    return 1;
+  case FL_DRAG:
+    if (!step()) goto DEFAULT;
+    delta = Fl::event_x()-ix;
+    if (delta > 5) delta -= 5;
+    else if (delta < -5) delta += 5;
+    else delta = 0;
+    switch (drag) {
+    case 3: v = increment(previous_value(), delta*100); break;
+    case 2: v = increment(previous_value(), delta*10); break;
+    default:v = increment(previous_value(), delta); break;
+    }
+    v = round(v);
+    handle_drag(soft()?softclamp(v):clamp(v));;
+    return 1;
+  case FL_RELEASE:
+    if (!step()) goto DEFAULT;
+    if (value() != previous_value() || !Fl::event_is_click())
+      handle_release();
+    else {
+      input.handle(FL_PUSH);
+      input.handle(FL_RELEASE);
+    }
+    return 1;
+  case FL_FOCUS:
+    return input.take_focus();
+  default:
+  DEFAULT:
+    input.type(step()>=1.0 ? FL_INT_INPUT : FL_FLOAT_INPUT);
+    return input.handle(event);
+  }
+}
+
+Fl_Value_Input::Fl_Value_Input(int x, int y, int w, int h, const char* l)
+: Fl_Valuator(x, y, w, h, l), input(x, y, w, h, 0) {
+  soft_ = 0;
+  if (input.parent())  // defeat automatic-add
+    ((Fl_Group*)input.parent())->remove(input);
+  input.parent(this); // kludge!
+  input.callback(input_cb, this);
+  input.when((Fl_When)(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY));
+  box(input.box());
+  color(input.color());
+  selection_color(input.selection_color());
+  align(FL_ALIGN_LEFT);
+  value_damage();
+}
diff --git a/src/Fl_Value_Output.cxx b/src/Fl_Value_Output.cxx
new file mode 100644
index 000000000..8c3f26bcd
--- /dev/null
+++ b/src/Fl_Value_Output.cxx
@@ -0,0 +1,73 @@
+// Fl_Value_Output.C
+
+// Fltk widget for drag-adjusting a floating point value.
+// This is much lighter than Fl_Value_Input because it has no text editor
+// If step() is zero then it can be used to display a floating-point value
+
+#include 
+#include 
+#include 
+#include  // for default_font
+
+void Fl_Value_Output::draw() {
+  Fl_Boxtype b = box() ? box() : Fl_Input::default_box();
+  int X = x()+Fl::box_dx(b);
+  int Y = y()+Fl::box_dy(b);
+  int W = w()-Fl::box_dw(b);
+  int H = h()-Fl::box_dh(b);
+  if (damage()&~1)
+    draw_box(b, color());
+  else {
+    fl_color(color());
+    fl_rectf(X, Y, W, H);
+  }
+  char buf[128];
+  format(buf);
+  fl_color(active_r() ? textcolor() : inactive(textcolor()));
+  fl_font(textfont(), textsize(),
+	  Fl_Input::default_font(), Fl_Input::default_size());
+  fl_draw(buf,X+3,Y,W-6,H,FL_ALIGN_LEFT);
+}
+
+int Fl_Value_Output::handle(int event) {
+  if (!step()) return 0;
+  double v;
+  int delta;
+  int mx = Fl::event_x();
+  static int ix, drag;
+  switch (event) {
+  case FL_PUSH:
+    ix = mx;
+    drag = Fl::event_button();
+    handle_push();
+    return 1;
+  case FL_DRAG:
+    delta = Fl::event_x()-ix;
+    if (delta > 5) delta -= 5;
+    else if (delta < -5) delta += 5;
+    else delta = 0;
+    switch (drag) {
+    case 3: v = increment(previous_value(),delta*100); break;
+    case 2: v = increment(previous_value(),delta*10); break;
+    default:v = increment(previous_value(),delta); break;
+    }
+    v = round(v);
+    handle_drag(soft()?softclamp(v):clamp(v));;
+    return 1;
+  case FL_RELEASE:
+    handle_release();
+    return 1;
+  default:
+    return 0;
+  }
+}
+
+Fl_Value_Output::Fl_Value_Output(int x,int y,int w,int h,const char *l)
+: Fl_Valuator(x,y,w,h,l) {
+  box(FL_NO_BOX);
+  align(FL_ALIGN_LEFT);
+  textfont_ = FL_HELVETICA;
+  textsize_ = FL_NORMAL_SIZE;
+  textcolor_ = FL_BLACK;
+  soft_ = 0;
+}
diff --git a/src/Fl_Value_Slider.cxx b/src/Fl_Value_Slider.cxx
new file mode 100644
index 000000000..ade51106d
--- /dev/null
+++ b/src/Fl_Value_Slider.cxx
@@ -0,0 +1,45 @@
+/*	Fl_Value_Slider.C	*/
+
+#include 
+#include 
+#include 
+#include 
+#include  // for default_font
+
+Fl_Value_Slider::Fl_Value_Slider(int x,int y,int w,int h, const char*l)
+: Fl_Slider(x,y,w,h,l) {
+  step(1,100);
+  textfont_ = FL_HELVETICA;
+  textsize_ = 10;
+  textcolor_ = FL_BLACK;
+}
+
+void Fl_Value_Slider::draw() {
+  int sxx = x(), syy = y(), sww = w(), shh = h();
+  int bxx = x(), byy = y(), bww = w(), bhh = h();
+  if (horizontal()) {
+    bww = 35; sxx += 35; sww -= 35;
+  } else {
+    syy += 25; bhh = 25; shh -= 25;
+  }
+  Fl_Slider::draw(sxx,syy,sww,shh);
+  draw_box(box(),bxx,byy,bww,bhh,color());
+  char buf[128];
+  format(buf);
+  fl_font(textfont(), textsize(),
+	  Fl_Input_::default_font(), Fl_Input_::default_size());
+  fl_color(active_r() ? textcolor() : inactive(textcolor()));
+  fl_draw(buf, bxx, byy, bww, bhh, FL_ALIGN_CLIP);
+}
+
+int Fl_Value_Slider::handle(int event) {
+  int sxx = x(), syy = y(), sww = w(), shh = h();
+  if (horizontal()) {
+    sxx += 35; sww -= 35;
+  } else {
+    syy += 25; shh -= 25;
+  }
+  return Fl_Slider::handle(event,sxx,syy,sww,shh);
+}
+
+// End of Fl_Value_Slider.C
diff --git a/src/Fl_Widget.cxx b/src/Fl_Widget.cxx
new file mode 100644
index 000000000..65fda468c
--- /dev/null
+++ b/src/Fl_Widget.cxx
@@ -0,0 +1,164 @@
+// Fl_Widget.C
+
+// fltk (Fast Light Tool Kit) version 0.99
+// Copyright (C) 1998 Bill Spitzak
+
+#include 
+#include 
+#include 
+
+////////////////////////////////////////////////////////////////
+// for compatability with Forms, all widgets without callbacks are
+// inserted into a "queue" when they are activated, and the forms
+// compatability interaction functions (fl_do_events, etc) will
+// read one widget at a time from this queue and return it:
+
+const int QUEUE_SIZE = 20;
+
+static Fl_Widget *obj_queue[QUEUE_SIZE];
+static int obj_head, obj_tail;
+
+void Fl_Widget::default_callback(Fl_Widget *o, void * /*v*/) {
+#if 0
+  // This is necessary for strict forms compatability but is confusing.
+  // Use the parent's callback if this widget does not have one.
+  for (Fl_Widget *p = o->parent(); p; p = p->parent())
+    if (p->callback() != default_callback) {
+      p->do_callback(o,v);
+      return;
+    }
+#endif
+  obj_queue[obj_head++] = o;
+  if (obj_head >= QUEUE_SIZE) obj_head = 0;
+  if (obj_head == obj_tail) {
+    obj_tail++;
+    if (obj_tail >= QUEUE_SIZE) obj_tail = 0;
+  }
+}
+
+Fl_Widget *Fl::readqueue() {
+  if (obj_tail==obj_head) return 0;
+  Fl_Widget *o = obj_queue[obj_tail++];
+  if (obj_tail >= QUEUE_SIZE) obj_tail = 0;
+  return o;
+}
+    
+////////////////////////////////////////////////////////////////
+
+int Fl_Widget::handle(int) {return 0;}
+
+Fl_Widget::Fl_Widget(int X, int Y, int W, int H, const char* L) {
+
+  x_ = X; y_ = Y; w_ = W; h_ = H;
+
+  label_.value	= L;
+  label_.type	= FL_NORMAL_LABEL;
+  label_.font	= FL_HELVETICA;
+  label_.size	= FL_NORMAL_SIZE;
+  label_.color	= FL_BLACK;
+  callback_	= default_callback;
+  user_data_ 	= 0;
+  type_		= 0;
+  flags_	= 0;
+  damage_	= 0;
+  box_		= FL_NO_BOX;
+  color_	= FL_GRAY;
+  color2_	= FL_GRAY;
+  align_	= FL_ALIGN_CENTER;
+  when_		= FL_WHEN_RELEASE;
+
+  parent_ = 0;
+  if (Fl_Group::current()) Fl_Group::current()->add(this);
+}
+
+void Fl_Widget::resize(int X, int Y, int W, int H) {
+  x_ = X; y_ = Y; w_ = W; h_ = H;
+}
+
+// this is useful for parent widgets to call to resize children:
+int Fl_Widget::damage_resize(int X, int Y, int W, int H) {
+  if (x() == X && y() == Y && w() == W && h() == H) return 0;
+  resize(X, Y, W, H);
+  redraw();
+  return 1;
+}
+
+int Fl_Widget::take_focus() {
+  if (!takesevents()) return 0;
+  if (!handle(FL_FOCUS)) return 0; // see if it wants it
+  if (contains(Fl::focus())) return 1; // it called Fl::focus for us
+  Fl::focus(this);
+  return 1;
+}
+
+extern void fl_throw_focus(Fl_Widget*); // in Fl_x.C
+
+// Destruction does not remove from any parent group!  And groups when
+// destroyed destroy all their children.  This is convienent and fast.
+// However, it is only legal to destroy a "root" such as an Fl_Window,
+// and automatic destructors may be called.
+Fl_Widget::~Fl_Widget() {
+  parent_ = 0; // kludge to prevent ~Fl_Group from destroying again
+  fl_throw_focus(this);
+}
+
+// redraw this, plus redraw opaque object if there is an outside label
+static void redraw_label(Fl_Widget* w) {
+  w->redraw();
+  if (w->label() && (w->align()&15) && !(w->align() & FL_ALIGN_INSIDE)) {
+    for (Fl_Widget *p = w->parent(); p; p = p->parent())
+      if (p->box() || !p->parent()) {p->redraw(); break;}
+  }
+}
+
+void Fl_Widget::activate() {
+  if (active()) return;
+  clear_flag(INACTIVE);
+  handle(FL_ACTIVATE);
+  if (inside(Fl::focus())) Fl::focus()->take_focus();
+  redraw_label(this);
+}
+
+void Fl_Widget::deactivate() {
+  if (!active()) return;
+  set_flag(INACTIVE);
+  handle(FL_DEACTIVATE);
+  fl_throw_focus(this);
+  redraw_label(this);
+}
+
+int Fl_Widget::active_r() const {
+  for (const Fl_Widget* o = this; o; o = o->parent())
+    if (!o->active()) return 0;
+  return 1;
+}
+
+void Fl_Widget::show() {
+  if (visible()) return;
+  clear_flag(INVISIBLE);
+  handle(FL_SHOW);
+  if (inside(Fl::focus())) Fl::focus()->take_focus();
+  redraw_label(this);
+}
+
+void Fl_Widget::hide() {
+  if (!visible()) return;
+  set_flag(INVISIBLE);
+  handle(FL_HIDE);
+  fl_throw_focus(this);
+  for (Fl_Widget *p = parent(); p; p = p->parent())
+    if (p->box() || !p->parent()) {p->redraw(); break;}
+}
+
+int Fl_Widget::visible_r() const {
+  for (const Fl_Widget* o = this; o; o = o->parent())
+    if (!o->visible()) return 0;
+  return 1;
+}
+
+// return true if widget is inside (or equal to) this:
+// Returns false for null widgets.
+int Fl_Widget::contains(const Fl_Widget *o) const {
+  for (; o; o = o->parent_) if (o == this) return 1;
+  return 0;
+}
diff --git a/src/Fl_Window.cxx b/src/Fl_Window.cxx
new file mode 100644
index 000000000..9c987df4e
--- /dev/null
+++ b/src/Fl_Window.cxx
@@ -0,0 +1,83 @@
+// Fl_Window.C
+
+// fltk (Fast Light Tool Kit) version 0.99
+// Copyright (C) 1998 Bill Spitzak
+
+// The Fl_Window is a window in the fltk library.
+// This is the system-independent portions.  The huge amount of 
+// crap you need to do to communicate with X is in Fl_x.C, the
+// equivalent (but totally different) crap for MSWindows is in Fl_win32.C
+
+#include 
+#include 
+
+void Fl_Window::_Fl_Window() {
+  type(FL_WINDOW);
+  box(FL_FLAT_BOX);
+  labeltype(FL_NO_LABEL);
+  i = 0;
+  xclass_ = 0;
+  iconlabel_ = 0;
+  resizable(0);
+  size_range_set = 0;
+  callback((Fl_Callback*)default_callback);
+}
+
+Fl_Window::Fl_Window(int X,int Y,int W, int H, const char *l)
+: Fl_Group(X, Y, W, H, l) {
+  _Fl_Window();
+  set_flag(FL_FORCE_POSITION);
+}
+
+Fl_Window::Fl_Window(int W, int H, const char *l)
+// fix common user error of a missing end() with current(0):
+  : Fl_Group((Fl_Group::current(0),0), 0, W, H, l) {
+  _Fl_Window();
+  clear_visible();
+}
+
+Fl_Window *Fl_Widget::window() const {
+  for (Fl_Widget *o = parent(); o; o = o->parent())
+    if (o->type()>=FL_WINDOW) return (Fl_Window*)o;
+  return 0;
+}
+
+int Fl_Window::x_root() const {
+  Fl_Window *p = window();
+  if (p) return p->x_root() + x();
+  return x();
+}
+
+int Fl_Window::y_root() const {
+  Fl_Window *p = window();
+  if (p) return p->y_root() + y();
+  return y();
+}
+
+void Fl_Window::draw() {
+  int savex = x(); x(0);
+  int savey = y(); y(0);
+  Fl_Group::draw();
+  y(savey);
+  x(savex);
+}
+
+void Fl_Window::label(const char *name) {label(name, iconlabel());}
+
+void Fl_Window::iconlabel(const char *iname) {label(label(), iname);}
+
+// the Fl::atclose pointer is provided for back compatability.  You
+// can now just change the callback for the window instead.
+
+void Fl::default_atclose(Fl_Window* window, void* v) {
+  window->hide();
+  Fl_Widget::default_callback(window, v); // put on Fl::read_queue()
+}
+
+void (*Fl::atclose)(Fl_Window*, void*) = default_atclose;
+
+void Fl_Window::default_callback(Fl_Window* window, void* v) {
+  Fl::atclose(window, v);
+}
+
+// End of Fl_Window.C
diff --git a/src/Fl_Window_fullscreen.cxx b/src/Fl_Window_fullscreen.cxx
new file mode 100644
index 000000000..332a52cc4
--- /dev/null
+++ b/src/Fl_Window_fullscreen.cxx
@@ -0,0 +1,46 @@
+// Turning the border on/off by changing the motif_wm_hints property
+// works on Irix 4DWM.  Does not appear to work for any other window
+// manager.  Fullscreen still works on some window managers (fvwm is one)
+// because they allow the border to be placed off-screen.
+
+// Unfortunatly most X window managers ignore changes to the border
+// and refuse to position the border off-screen, so attempting to make
+// the window full screen will lose the size of the border off the
+// bottom and right.
+
+#include 
+#include 
+
+void Fl_Window::border(int b) {
+  if (b) {
+    if (border()) return;
+    clear_flag(FL_NOBORDER);
+  } else {
+    if (!border()) return;
+    set_flag(FL_NOBORDER);
+  }
+#ifdef WIN32
+  // not yet implemented, but it's possible
+  // for full fullscreen we have to make the window topmost as well
+#else
+  if (shown()) Fl_X::i(this)->sendxjunk();
+#endif
+}
+
+void Fl_Window::fullscreen() {
+  border(0);
+  if (!x()) x(1); // force it to call XResizeWindow()
+  resize(0,0,Fl::w(),Fl::h());
+}
+
+void Fl_Window::fullscreen_off(int X,int Y,int W,int H) {
+#ifdef WIN32
+  border(1);
+  resize(X,Y,W,H);
+#else
+  // this order produces less blinking on IRIX:
+  resize(X,Y,W,H);
+  border(1);
+#endif
+}
+
diff --git a/src/Fl_Window_hotspot.cxx b/src/Fl_Window_hotspot.cxx
new file mode 100644
index 000000000..9a6f58a20
--- /dev/null
+++ b/src/Fl_Window_hotspot.cxx
@@ -0,0 +1,27 @@
+// Fl_Window_hotspot.C
+
+#include 
+#include 
+
+void Fl_Window::hotspot(int X, int Y, int offscreen) {
+  int mx,my; Fl::get_mouse(mx,my);
+  X = mx-X; Y = my-Y;
+  if (!offscreen) {
+    if (X < 0) X = 0;
+    if (X > Fl::w()-w()) X = Fl::w()-w();
+    if (Y > Fl::h()-h()) Y = Fl::h()-h();
+    if (Y < 0) Y = 0;
+    if (border() && Y < 20) Y = 20;
+  }
+  position(X,Y);
+}
+
+void Fl_Window::hotspot(const Fl_Widget *o, int offscreen) {
+  int X = o->w()/2;
+  int Y = o->h()/2;
+  while (o != this) {
+    X += o->x(); Y += o->y();
+    o = o->window();
+  }
+  hotspot(X,Y,offscreen);
+}
diff --git a/src/Fl_Window_iconize.cxx b/src/Fl_Window_iconize.cxx
new file mode 100644
index 000000000..a89080623
--- /dev/null
+++ b/src/Fl_Window_iconize.cxx
@@ -0,0 +1,19 @@
+// X-specific code that is not called by all programs, so it is put
+// here in it's own source file to make programs smaller.
+
+#include 
+
+extern char fl_show_iconic; // in Fl_x.C
+
+void Fl_Window::iconize() {
+  if (!shown()) {
+    fl_show_iconic = 1;
+    show();
+  } else {
+#ifdef WIN32
+    ShowWindow(i->xid, SW_MINIMIZE);
+#else
+    XIconifyWindow(fl_display, i->xid, fl_screen);
+#endif
+  }
+}
diff --git a/src/Fl_XColor.H b/src/Fl_XColor.H
new file mode 100644
index 000000000..0f2936d74
--- /dev/null
+++ b/src/Fl_XColor.H
@@ -0,0 +1,18 @@
+// X-specific structure for storing allocated colors.  Used by fl_color.C,
+// fl_draw_image.C, fl_set_color.C.
+
+#include 
+
+// one of these for each color in fltk's "colormap":
+// if overlays are enabled, another one for the overlay
+struct Fl_XColor {
+  unsigned char r,g,b;	// actual color used by X
+  unsigned char mapped;	// true when XAllocColor done
+  unsigned long pixel;	// the X pixel to use
+};
+extern Fl_XColor fl_xmap[/*overlay*/][256];
+
+// mask & shifts to produce xcolor for truecolor visuals:
+extern unsigned char fl_redmask, fl_greenmask, fl_bluemask;
+extern int fl_redshift, fl_greenshift, fl_blueshift, fl_extrashift;
+
diff --git a/src/Fl_abort.cxx b/src/Fl_abort.cxx
new file mode 100644
index 000000000..047af80a9
--- /dev/null
+++ b/src/Fl_abort.cxx
@@ -0,0 +1,51 @@
+// This method is in it's own source file so that stdlib and stdio
+// do not need to be included in Fl.C:
+// You can also override this by redefining all of these.
+
+#include 
+#include 
+#include 
+#include 
+
+#ifndef WIN32
+
+static void warning(const char *format, ...) {
+  va_list args;
+  va_start(args, format);
+  vfprintf(stderr, format, args);
+  va_end(args);
+  fputc('\n', stderr);
+  fflush(stderr);
+}
+
+static void error(const char *format, ...) {
+  va_list args;
+  va_start(args, format);
+  vfprintf(stderr, format, args);
+  va_end(args);
+  fputc('\n', stderr);
+  fflush(stderr);
+//abort(); // this produces a core dump, probably not desirable?
+  ::exit(1);
+}
+
+#else
+
+// windows version is currently lame as vsprintf() is missing?
+
+#include 
+
+static void warning(const char *format, ...) {
+  MessageBox(0,format,"Fltk warning",MB_ICONEXCLAMATION|MB_OK);
+}
+
+static void error(const char *format, ...) {
+  MessageBox(0,format,"Fltk error",MB_ICONSTOP|MB_SYSTEMMODAL);
+  ::exit(1);
+}
+
+#endif
+
+void (*Fl::warning)(const char* format, ...) = ::warning;
+void (*Fl::error)(const char* format, ...) = ::error;
+void (*Fl::fatal)(const char* format, ...) = ::error;
diff --git a/src/Fl_add_idle.cxx b/src/Fl_add_idle.cxx
new file mode 100644
index 000000000..3b0e127c2
--- /dev/null
+++ b/src/Fl_add_idle.cxx
@@ -0,0 +1,62 @@
+// Fl_add_idle.C
+
+// Allows you to manage an arbitrary set of idle() callbacks.
+// Replaces the older set_idle() call (which is used to implement this)
+
+#include 
+
+struct idle_cb {
+  void (*cb)(void*);
+  void* data;
+  idle_cb *next;
+};
+
+// the callbacks are stored linked in a ring.  last points at the one
+// just called, first at the next to call.  last->next == first.
+
+static idle_cb* first;
+static idle_cb* last;
+static idle_cb* freelist;
+
+static void call_idle() {
+  idle_cb* p = first;
+  last = p; first = p->next;
+  p->cb(p->data); // this may call add_idle() or remove_idle()!
+}
+
+void Fl::add_idle(void (*cb)(void*), void* data) {
+  idle_cb* p = freelist;
+  if (p) freelist = p->next;
+  else p = new idle_cb;
+  p->cb = cb;
+  p->data = data;
+  if (first) {
+    last->next = p;
+    p->next = first;
+    first = p;
+  } else {
+    first = last = p;
+    p->next = p;
+    set_idle(call_idle);
+  }
+}
+
+void Fl::remove_idle(void (*cb)(void*), void* data) {
+  idle_cb* p = first;
+  if (!p) return;
+  idle_cb* l = last;
+  for (;; p = p->next) {
+    if (p->cb == cb && p->data == data) break;
+    if (p==last) return; // not found
+    l = p;
+  }
+  if (l == p) { // only one
+    first = last = 0;
+    set_idle(0);
+  } else {
+    last = l;
+    first = l->next = p->next;
+  }
+  p->next = freelist;
+  freelist = p;
+}
diff --git a/src/Fl_arg.cxx b/src/Fl_arg.cxx
new file mode 100644
index 000000000..f15d4b5b7
--- /dev/null
+++ b/src/Fl_arg.cxx
@@ -0,0 +1,377 @@
+// Fl_arg.C
+
+// OPTIONAL initialization code for a program using fltk.
+// You do not need to call this!  Feel free to make up your own switches.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifdef WIN32
+int XParseGeometry(const char*, int*, int*, unsigned int*, unsigned int*);
+#define NoValue		0x0000
+#define XValue  	0x0001
+#define YValue		0x0002
+#define WidthValue  	0x0004
+#define HeightValue  	0x0008
+#define AllValues 	0x000F
+#define XNegative 	0x0010
+#define YNegative 	0x0020
+#endif
+
+static int match(const char *a, const char *match, int atleast = 1) {
+  const char *b = match;
+  while (*a && (*a == *b || tolower(*a) == *b)) {a++; b++;}
+  return !*a && b >= match+atleast;
+}
+
+// flags set by previously parsed arguments:
+extern char fl_show_iconic; // in Fl_x.C
+static char arg_called;
+static char return_i;
+static const char *name;
+static const char *fg;
+static const char *bg;
+static const char *bg2;
+static const char *geometry;
+static const char *title;
+
+// consume a switch from argv.  Returns number of words eaten, 0 on error:
+int Fl::arg(int argc, char **argv, int &i) {
+  arg_called = 1;
+  const char *s = argv[i];
+
+  if (!s) {i++; return 1;}	// something removed by calling program?
+
+  // a word that does not start with '-', or a word after a '--', or
+  // the word '-' by itself all start the "non-switch arguments" to
+  // a program.  Return 0 to indicate that we don't understand the
+  // word, but set a flag (return_i) so that args() will return at
+  // that point:
+  if (s[0] != '-' || !s[1]) {return_i = 1; return 0;}
+  if (s[1] == '-') {
+    if (!s[2]) {i++; return_i = 1; return 0;}
+    s++; // make "--word" work the same as "-word" for Gnu compatability
+  }
+  s++; // point after the dash
+
+  if (match(s, "iconic")) {
+    fl_show_iconic = 1;
+    i++;
+    return 1;
+  }
+
+  const char *v = argv[i+1];
+  if (i >= argc-1 || !v)
+    return 0;	// all the rest need an argument, so if missing it is an error
+
+  if (match(s, "geometry")) {
+
+    int flags, gx, gy; unsigned int gw, gh;
+    flags = XParseGeometry(v, &gx, &gy, &gw, &gh);
+    if (!flags) return 0;
+    geometry = v;
+
+#ifndef WIN32
+  } else if (match(s, "display")) {
+    Fl::display(v);
+#endif
+
+  } else if (match(s, "title")) {
+    title = v;
+
+  } else if (match(s, "name")) {
+    name = v;
+
+  } else if (match(s, "bg2", 3) || match(s, "background2", 11)) {
+    bg2 = v;
+
+  } else if (match(s, "bg") || match(s, "background")) {
+    bg = v;
+
+  } else if (match(s, "fg") || match(s, "foreground")) {
+    fg = v;
+
+  } else return 0; // unrecognized
+
+  i += 2;
+  return 2;
+}
+
+// consume all switches from argv.  Returns number of words eaten.
+// Returns zero on error.  'i' will either point at first word that
+// does not start with '-', at the error word, or after a '--', or at
+// argc.  If your program does not take any word arguments you can
+// report an error if i < argc.
+
+int Fl::args(int argc, char** argv, int& i, int (*cb)(int,char**,int&)) {
+  arg_called = 1;
+  i = 1; // skip argv[0]
+  while (i < argc) {
+    if (cb && cb(argc,argv,i)) continue;
+    if (!arg(argc,argv,i)) return return_i ? i : 0;
+  }
+  return i;
+}
+
+#ifdef WIN32
+#include 
+// simulation of XParseColor:
+int fl_parse_color(const char* p, uchar& r, uchar& g, uchar& b) {
+  if (*p == '#') p++;
+  int n = strlen(p);
+  int m = n/3;
+  const char *pattern = 0;
+  switch(m) {
+  case 1: pattern = "%1x%1x%1x"; break;
+  case 2: pattern = "%2x%2x%2x"; break;
+  case 3: pattern = "%3x%3x%3x"; break;
+  case 4: pattern = "%4x%4x%4x"; break;
+  default: return 0;
+  }
+  int R,G,B; if (sscanf(p,pattern,&R,&G,&B) != 3) return 0;
+  r = R; g = G; b = B;
+  return 1;
+}
+
+static void parsecolor(const char *name, void (*func)(uchar,uchar,uchar)) {
+  uchar r,g,b;
+  if (!name) return;
+  if (!fl_parse_color(name, r,g,b))
+    Fl::error("Unknown color: %s", name);
+  else
+    func(r,g,b);
+}
+
+#else
+
+static void parsecolor(const char *name, void (*func)(uchar,uchar,uchar)) {
+  XColor x;
+  if (!name) return;
+  if (!XParseColor(fl_display, fl_colormap, name, &x))
+    Fl::error("Unknown color: %s", name);
+  else
+    func(x.red>>8, x.green>>8, x.blue>>8);
+}
+
+#endif
+
+// show a main window, use any parsed arguments
+void Fl_Window::show(int argc, char **argv) {
+  if (!arg_called) Fl::args(argc,argv);
+
+  // set colors first, so background_pixel is correct:
+  static char beenhere;
+  if (!beenhere) {
+    beenhere = 1;
+    Fl::get_system_colors(); // opens display!  May call Fl::fatal()
+    parsecolor(fg, Fl::foreground);
+    parsecolor(bg, Fl::background);
+    parsecolor(bg2,Fl::background2);
+    if (geometry) {
+      int flags = 0, gx = x(), gy = y(); unsigned int gw = w(), gh = h();
+      flags = XParseGeometry(geometry, &gx, &gy, &gw, &gh);
+      if (flags & XNegative) gx = Fl::w()-w()+gx;
+      if (flags & YNegative) gy = Fl::h()-h()+gy;
+      //  int mw,mh; minsize(mw,mh);
+      //  if (mw > gw) gw = mw;
+      //  if (mh > gh) gh = mh;
+      Fl_Widget *r = resizable();
+      if (!r) resizable(this);
+      // for WIN32 we assumme window is not mapped yet:
+      if (flags & (XValue | YValue))
+	x(-1), resize(gx,gy,gw,gh);
+      else
+	size(gw,gh);
+      resizable(r);
+    }
+  }
+
+  if (name) {xclass(name); name = 0;}
+  else if (!xclass()) xclass(filename_name(argv[0]));
+  if (title) {label(title); title = 0;}
+  else if (!label()) label(xclass());
+  show();
+
+#ifndef WIN32
+  // set the command string, used by state-saving window managers:
+  int i;
+  int n=0; for (i=0; ix{+-}{+-}", where
+ *   width, height, xoffset, and yoffset are unsigned integers.
+ *   Example:  "=80x24+300-49"
+ *   The equal sign is optional.
+ *   It returns a bitmask that indicates which of the four values
+ *   were actually found in the string.  For each value found,
+ *   the corresponding argument is updated;  for each value
+ *   not found, the corresponding argument is left unchanged. 
+ */
+
+static int ReadInteger(char* string, char** NextString)
+{
+  register int Result = 0;
+  int Sign = 1;
+    
+  if (*string == '+')
+    string++;
+  else if (*string == '-') {
+    string++;
+    Sign = -1;
+  }
+  for (; (*string >= '0') && (*string <= '9'); string++) {
+    Result = (Result * 10) + (*string - '0');
+  }
+  *NextString = string;
+  if (Sign >= 0)
+    return (Result);
+  else
+    return (-Result);
+}
+
+int XParseGeometry(const char* string, int* x, int* y,
+		   unsigned int* width, unsigned int* height)
+{
+  int mask = NoValue;
+  register char *strind;
+  unsigned int tempWidth, tempHeight;
+  int tempX, tempY;
+  char *nextCharacter;
+
+  if ( (string == NULL) || (*string == '\0')) return(mask);
+  if (*string == '=')
+    string++;  /* ignore possible '=' at beg of geometry spec */
+
+  strind = (char *)string;
+  if (*strind != '+' && *strind != '-' && *strind != 'x') {
+    tempWidth = ReadInteger(strind, &nextCharacter);
+    if (strind == nextCharacter) 
+      return (0);
+    strind = nextCharacter;
+    mask |= WidthValue;
+  }
+
+  if (*strind == 'x' || *strind == 'X') {	
+    strind++;
+    tempHeight = ReadInteger(strind, &nextCharacter);
+    if (strind == nextCharacter)
+      return (0);
+    strind = nextCharacter;
+    mask |= HeightValue;
+  }
+
+  if ((*strind == '+') || (*strind == '-')) {
+    if (*strind == '-') {
+      strind++;
+      tempX = -ReadInteger(strind, &nextCharacter);
+      if (strind == nextCharacter)
+	return (0);
+      strind = nextCharacter;
+      mask |= XNegative;
+
+    } else {
+      strind++;
+      tempX = ReadInteger(strind, &nextCharacter);
+      if (strind == nextCharacter)
+	return(0);
+      strind = nextCharacter;
+      }
+    mask |= XValue;
+    if ((*strind == '+') || (*strind == '-')) {
+      if (*strind == '-') {
+	strind++;
+	tempY = -ReadInteger(strind, &nextCharacter);
+	if (strind == nextCharacter)
+	  return(0);
+	strind = nextCharacter;
+	mask |= YNegative;
+
+      } else {
+	strind++;
+	tempY = ReadInteger(strind, &nextCharacter);
+	if (strind == nextCharacter)
+	  return(0);
+	strind = nextCharacter;
+      }
+      mask |= YValue;
+    }
+  }
+	
+  /* If strind isn't at the end of the string the it's an invalid
+     geometry specification. */
+
+  if (*strind != '\0') return (0);
+
+  if (mask & XValue)
+    *x = tempX;
+  if (mask & YValue)
+    *y = tempY;
+  if (mask & WidthValue)
+    *width = tempWidth;
+  if (mask & HeightValue)
+    *height = tempHeight;
+  return (mask);
+}
+
+#endif // ifdef WIN32
+
+// end of Fl_Window_arg.C
diff --git a/src/Fl_cutpaste.cxx b/src/Fl_cutpaste.cxx
new file mode 100644
index 000000000..e7fcdd5e5
--- /dev/null
+++ b/src/Fl_cutpaste.cxx
@@ -0,0 +1,127 @@
+// Fl_cutpaste.C
+
+// Implementation of cut and paste.
+
+// This is seperated from Fl.C mostly to test Fl::add_handler().
+// But this will save a small amount of code size in a program that
+// has no text editing fields or other things that call cut or paste.
+
+#ifdef WIN32
+#include "Fl_cutpaste_win32.C"
+#else
+
+#include 
+#include 
+#include 
+#include 
+
+static char *selection_buffer;
+static int selection_length;
+static int selection_buffer_length;
+static char beenhere;
+
+extern Fl_Widget *fl_selection_requestor; // widget doing request_paste()
+
+static int selection_xevent_handler(int) {
+
+  switch (fl_xevent->type) {
+
+  case SelectionNotify: {
+    if (!fl_selection_requestor) return 0;
+    static char *pastebuffer;
+    if (pastebuffer) {XFree(pastebuffer); pastebuffer = 0;}
+    if (fl_xevent->xselection.property != 0) {
+      Atom a; int f; unsigned long n,b;
+      if (!XGetWindowProperty(fl_display,
+			      fl_xevent->xselection.requestor,
+			      fl_xevent->xselection.property,
+			      0,100000,1,0,&a,&f,&n,&b,
+			      (unsigned char**)&pastebuffer)) {
+	Fl::e_text = pastebuffer;
+	Fl::e_length = int(n);
+	fl_selection_requestor->handle(FL_PASTE);
+      }
+    }}
+    return 1;
+
+  case SelectionClear:
+    Fl::selection_owner(0);
+    return 1;
+
+  case SelectionRequest: {
+    XSelectionEvent e;
+    e.type = SelectionNotify;
+    e.display = fl_display;
+    e.requestor = fl_xevent->xselectionrequest.requestor;
+    e.selection = fl_xevent->xselectionrequest.selection;
+    e.target = fl_xevent->xselectionrequest.target;
+    e.time = fl_xevent->xselectionrequest.time;
+    if (fl_xevent->xselectionrequest.target != XA_STRING || !selection_length) {
+      e.property = 0;
+    } else {
+      e.property = fl_xevent->xselectionrequest.property;
+    }
+    if (e.property) {
+      XChangeProperty(fl_display, e.requestor, e.property,
+		      XA_STRING, 8, 0, (unsigned char *)selection_buffer,
+		      selection_length);
+    }
+    XSendEvent(fl_display, e.requestor, 0, 0, (XEvent *)&e);}
+    return 1;
+
+  default:
+    return 0;
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+// Call this when a "paste" operation happens:
+void Fl::paste(Fl_Widget &receiver) {
+  if (selection_owner()) {
+    // We already have it, do it quickly without window server.
+    // Notice that the text is clobbered if set_selection is
+    // called in response to FL_PASTE!
+    Fl::e_text = selection_buffer;
+    Fl::e_length = selection_length;
+    receiver.handle(FL_PASTE);
+    return;
+  }
+  // otherwise get the window server to return it:
+  fl_selection_requestor = &receiver;
+  XConvertSelection(fl_display, XA_PRIMARY, XA_STRING, XA_PRIMARY,
+		    fl_xid(Fl::first_window()), fl_event_time);
+  if (!beenhere) {
+    Fl::add_handler(selection_xevent_handler);
+    beenhere = 1;
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+// call this when you create a selection:
+void Fl::selection(Fl_Widget &owner, const char *stuff, int len) {
+  if (!stuff || len<=0) return;
+  if (len+1 > selection_buffer_length) {
+    delete[] selection_buffer;
+    selection_buffer = new char[len+100];
+    selection_buffer_length = len+100;
+  }
+  memcpy(selection_buffer, stuff, len);
+  selection_buffer[len] = 0; // needed for direct paste
+  selection_length = len;
+  selection_owner(&owner);
+  static Window selxid; // window X thinks selection belongs to
+  if (!selxid) selxid =
+		 XCreateSimpleWindow(fl_display, 
+				     RootWindow(fl_display, fl_screen),
+				     0,0,1,1,0,0,0);
+  XSetSelectionOwner(fl_display, XA_PRIMARY, selxid, fl_event_time);
+  if (!beenhere) {
+    Fl::add_handler(selection_xevent_handler);
+    beenhere = 1;
+  }
+}
+
+#endif
+// end of Fl_cutpaste.C
diff --git a/src/Fl_cutpaste_win32.cxx b/src/Fl_cutpaste_win32.cxx
new file mode 100644
index 000000000..de60c8ed2
--- /dev/null
+++ b/src/Fl_cutpaste_win32.cxx
@@ -0,0 +1,106 @@
+// Fl_cutpaste_win32.C
+
+// Implementation of cut and paste.
+
+// This is seperated from Fl.C mostly to test Fl::add_handler().
+// But this will save a small amount of code size in a program that
+// has no text editing fields or other things that call cut or paste.
+
+#include 
+#include 
+#include 
+#include 
+
+static char *selection_buffer;
+static int selection_length;
+static int selection_buffer_length;
+static char beenhere;
+
+extern Fl_Widget *fl_selection_requestor; // widget doing request_paste()
+
+static int selection_xevent_handler(int) {
+
+  switch (fl_msg.message) {
+
+  case WM_DESTROYCLIPBOARD:
+    Fl::selection_owner(0);
+    Fl::flush(); // get the redraw to happen
+    return 1;
+
+  case WM_RENDERALLFORMATS:
+    if (!OpenClipboard(fl_xid(Fl::first_window()))) return 0;
+    EmptyClipboard();
+    // fall through...
+  case WM_RENDERFORMAT: {
+    HANDLE h = GlobalAlloc(GHND, selection_length+1);
+    if (h) {
+      LPSTR p = (LPSTR)GlobalLock(h);
+      memcpy(p, selection_buffer, selection_length);
+      p[selection_length] = 0;
+      GlobalUnlock(h);
+      SetClipboardData(CF_TEXT, h);
+    }
+    if (fl_msg.message == WM_RENDERALLFORMATS)
+      CloseClipboard();
+    return 1;}
+
+  default:
+    return 0;
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+// call this when you create a selection:
+void Fl::selection(Fl_Widget &owner, const char *stuff, int len) {
+  if (!stuff || len<=0) return;
+  if (len+1 > selection_buffer_length) {
+    delete[] selection_buffer;
+    selection_buffer = new char[len+100];
+    selection_buffer_length = len+100;
+  }
+  memcpy(selection_buffer, stuff, len);
+  selection_buffer[len] = 0; // needed for direct paste
+  selection_length = len;
+  if (OpenClipboard(fl_xid(Fl::first_window()))) {
+    EmptyClipboard();
+    SetClipboardData(CF_TEXT, NULL);
+    CloseClipboard();
+    if (!beenhere) {
+      Fl::add_handler(selection_xevent_handler);
+      beenhere = 1;
+    }
+  }
+  selection_owner(&owner);
+}
+
+////////////////////////////////////////////////////////////////
+
+// Call this when a "paste" operation happens:
+void Fl::paste(Fl_Widget &receiver) {
+  if (selection_owner()) {
+    // We already have it, do it quickly without window server.
+    // Notice that the text is clobbered if set_selection is
+    // called in response to FL_PASTE!
+    Fl::e_text = selection_buffer;
+    Fl::e_length = selection_length;
+    receiver.handle(FL_PASTE);
+  } else {
+    if (!OpenClipboard(fl_xid(Fl::first_window()))) return;
+    HANDLE h = GetClipboardData(CF_TEXT);
+    if (h) {
+      Fl::e_text = (LPSTR)GlobalLock(h);
+      LPSTR a,b;
+      a = b = Fl::e_text;
+      while (*a) { // strip the CRLF pairs ($%$#@^)
+	if (*a == '\r' && a[1] == '\n') a++;
+	else *b++ = *a++;
+      }
+      *b = 0;
+      Fl::e_length = b - Fl::e_text;
+      receiver.handle(FL_PASTE);
+      GlobalUnlock(h);
+    }
+    CloseClipboard();
+  }
+}
diff --git a/src/Fl_display.cxx b/src/Fl_display.cxx
new file mode 100644
index 000000000..12985db54
--- /dev/null
+++ b/src/Fl_display.cxx
@@ -0,0 +1,16 @@
+// Fl_display.C
+
+// Startup method to set what display to use.
+// Using setenv makes programs that are exec'd use the same display.
+
+#include 
+#include 
+#include 
+
+void Fl::display(const char *d) {
+  char *e = new char[strlen(d)+13];
+  strcpy(e,"DISPLAY=");
+  strcpy(e+8,d);
+  for (char *c = e+8; *c!=':'; c++) if (!*c) {strcpy(c,":0.0"); break;}
+  putenv(e);
+}
diff --git a/src/Fl_get_key.cxx b/src/Fl_get_key.cxx
new file mode 100644
index 000000000..72d9d070a
--- /dev/null
+++ b/src/Fl_get_key.cxx
@@ -0,0 +1,37 @@
+// Fl_get_key.C
+
+#ifdef WIN32
+#include "Fl_get_key_win32.C"
+#else
+
+// Return the current state of a key.  This is the X version.  I identify
+// keys (mostly) by the X keysym.  So this turns the keysym into a keycode
+// and looks it up in the X key bit vector, which Fl_x.C keeps track of.
+
+#include 
+#include 
+
+extern char fl_key_vector[32]; // in Fl_x.C
+
+int Fl::event_key(int k) {
+  if (k > FL_Button && k <= FL_Button+8)
+    return Fl::event_state(8<<(k-FL_Button));
+  int i;
+#ifdef __sgi
+  // get some missing PC keyboard keys:
+  if (k == FL_Meta_L) i = 147;
+  else if (k == FL_Meta_R) i = 148;
+  else if (k == FL_Menu) i = 149;
+  else
+#endif
+    i = XKeysymToKeycode(fl_display, k);
+  return fl_key_vector[i/8] & (1 << (i%8));
+}
+
+int Fl::get_key(int k) {
+  fl_open_display();
+  XQueryKeymap(fl_display, fl_key_vector);
+  return event_key(k);
+}
+
+#endif
diff --git a/src/Fl_get_key_win32.cxx b/src/Fl_get_key_win32.cxx
new file mode 100755
index 000000000..f094e2982
--- /dev/null
+++ b/src/Fl_get_key_win32.cxx
@@ -0,0 +1,108 @@
+// Fl_get_key_win32.C
+
+// Return the current state of a key.  Keys are named by fltk symbols,
+// which are actually X keysyms.  So this has to translate to MSWindows
+// VK_x symbols.
+
+#include 
+#include 
+
+// convert an Fltk (X) keysym to a MSWindows VK symbol:
+// See also the inverse converter in Fl_win32.C
+// This table is in numeric order by Fltk symbol order for binary search:
+
+static const struct {unsigned short vk, fltk;} vktab[] = {
+  {VK_SPACE,	' '},
+  {'1',		'!'},
+  {0xde,	'\"'},
+  {'3',		'#'},
+  {'4',		'$'},
+  {'5',		'%'},
+  {'7',		'&'},
+  {0xde,	'\''},
+  {'9',		'('},
+  {'0',		')'},
+  {'8',		'*'},
+  {0xbb,	'+'},
+  {0xbc,	','},
+  {0xbd,	'-'},
+  {0xbe,	'.'},
+  {0xbf,	'/'},
+  {0xba,	':'},
+  {0xba,	';'},
+  {0xbc,	'<'},
+  {0xbb,	'='},
+  {0xbe,	'>'},
+  {0xbf,	'?'},
+  {'2',		'@'},
+  {0xdb,	'['},
+  {0xdc,	'\\'},
+  {0xdd,	']'},
+  {'6',		'^'},
+  {0xbd,	'_'},
+  {0xc0,	'`'},
+  {0xdb,	'{'},
+  {0xdc,	'|'},
+  {0xdd,	'}'},
+  {0xc0,	'~'},
+  {VK_BACK,	FL_BackSpace},
+  {VK_TAB,	FL_Tab},
+  {VK_RETURN,	FL_Enter},
+  {VK_PAUSE,	FL_Pause},
+  {VK_SCROLL,	FL_Scroll_Lock},
+  {VK_ESCAPE,	FL_Escape},
+  {VK_HOME,	FL_Home},
+  {VK_LEFT,	FL_Left},
+  {VK_UP,	FL_Up},
+  {VK_RIGHT,	FL_Right},
+  {VK_DOWN,	FL_Down},
+  {VK_PRIOR,	FL_Page_Up},
+  {VK_NEXT,	FL_Page_Down},
+  {VK_END,	FL_End},
+  {VK_SNAPSHOT,	FL_Print},
+  {VK_INSERT,	FL_Insert},
+  {VK_APPS,	FL_Menu},
+  {VK_NUMLOCK,	FL_Num_Lock},
+//{VK_???,	FL_KP_Enter},
+  {VK_MULTIPLY,	FL_KP+'*'},
+  {VK_ADD,	FL_KP+'+'},
+  {VK_SUBTRACT,	FL_KP+'-'},
+  {VK_DECIMAL,	FL_KP+'.'},
+  {VK_DIVIDE,	FL_KP+'/'},
+  {VK_LSHIFT,	FL_Shift_L},
+  {VK_RSHIFT,	FL_Shift_R},
+  {VK_LCONTROL,	FL_Control_L},
+  {VK_RCONTROL,	FL_Control_R},
+  {VK_CAPITAL,	FL_Caps_Lock},
+  {VK_LWIN,	FL_Meta_L},
+  {VK_RWIN,	FL_Meta_R},
+  {VK_LMENU,	FL_Alt_L},
+  {VK_RMENU,	FL_Alt_R},
+  {VK_DELETE,	FL_Delete}
+};
+
+static int fltk2ms(int fltk) {
+  if (fltk >= '0' && fltk <= '9') return fltk;
+  if (fltk >= 'A' && fltk <= 'Z') return fltk;
+  if (fltk >= 'a' && fltk <= 'z') return toupper(fltk);
+  if (fltk > FL_F && fltk <= FL_F+16) return fltk-(FL_F-(VK_F1-1));
+  if (fltk >= FL_KP+'0' && fltk<=FL_KP+'9') return fltk-(FL_KP+'0'-VK_NUMPAD0);
+  int a = 0;
+  int b = sizeof(vktab)/sizeof(*vktab);
+  while (a < b) {
+    int c = (a+b)/2;
+    if (vktab[c].fltk == fltk) return vktab[c].vk;
+    if (vktab[c].fltk < fltk) a = c+1; else b = c;
+  }
+  return 0;
+}
+
+int Fl::event_key(int k) {
+  return GetKeyState(fltk2ms(k))&~1;
+}
+
+int Fl::get_key(int k) {
+  uchar foo[256];
+  GetKeyboardState(foo);
+  return foo[fltk2ms(k)]&~1;
+}
diff --git a/src/Fl_get_system_colors.cxx b/src/Fl_get_system_colors.cxx
new file mode 100644
index 000000000..ada3fdd3c
--- /dev/null
+++ b/src/Fl_get_system_colors.cxx
@@ -0,0 +1,66 @@
+// Fl_get_system_colors.C
+
+#include 
+#include 
+#include 
+
+void Fl::background(uchar r, uchar g, uchar b) {
+  // replace the gray ramp so that FL_GRAY is this color
+  if (!r) r = 1; else if (r==255) r = 254;
+  double powr = log(r/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0));
+  if (!g) g = 1; else if (g==255) g = 254;
+  double powg = log(g/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0));
+  if (!b) b = 1; else if (b==255) b = 254;
+  double powb = log(b/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0));
+  for (int i = 0; i < FL_NUM_GRAY; i++) {
+    double gray = i/(FL_NUM_GRAY-1.0);
+    Fl::set_color(fl_gray_ramp(i),
+		  uchar(pow(gray,powr)*255+.5),
+		  uchar(pow(gray,powg)*255+.5),
+		  uchar(pow(gray,powb)*255+.5));
+  }
+}
+
+static void set_others() {
+  uchar r,g,b; Fl::get_color(FL_BLACK,r,g,b);
+  uchar r1,g1,b1; Fl::get_color(FL_WHITE,r1,g1,b1);
+  Fl::set_color(FL_INACTIVE_COLOR,(2*r+r1)/3, (2*g+g1)/3, (2*b+b1)/3);
+  Fl::set_color(FL_SELECTION_COLOR,(2*r1+r)/3, (2*g1+g)/3, (2*b1+b)/3);
+}
+
+void Fl::foreground(uchar r, uchar g, uchar b) {
+  Fl::set_color(FL_BLACK,r,g,b);
+  set_others();
+}
+
+void Fl::background2(uchar r, uchar g, uchar b) {
+  Fl::set_color(FL_WHITE,r,g,b);
+  set_others();
+}
+
+#ifdef WIN32
+
+static void getsyscolor(int what, void (*func)(uchar,uchar,uchar)) {
+  DWORD x = GetSysColor(what);
+  uchar r = uchar(x&255);
+  uchar g = uchar(x>>8);
+  uchar b = uchar(x>>16);
+  func(r,g,b);
+}
+
+void Fl::get_system_colors() {
+  getsyscolor(COLOR_WINDOWTEXT, Fl::foreground);
+  getsyscolor(COLOR_BTNFACE, Fl::background);
+  getsyscolor(COLOR_WINDOW, Fl::background2);
+}
+
+#else
+// For X we should do something. KDE stores these colors in some standard
+// place, where?
+
+void Fl::get_system_colors()
+{
+  fl_open_display();
+}
+
+#endif
diff --git a/src/Fl_own_colormap.cxx b/src/Fl_own_colormap.cxx
new file mode 100644
index 000000000..8f4ca3524
--- /dev/null
+++ b/src/Fl_own_colormap.cxx
@@ -0,0 +1,50 @@
+// Fl_own_colormap.C
+
+// Using the default system colormap can be a bad idea on PseudoColor
+// visuals, since typically every application uses the default colormap and
+// you can run out of colormap entries easily.
+//
+// The solution is to always create a new colormap on PseudoColor displays
+// and copy the first 16 colors from the default colormap so that we won't
+// get huge color changes when switching windows.
+
+#include 
+#include 
+#include 
+
+#ifdef WIN32
+// There is probably something relevant to do on MSWindows 8-bit displays
+// but I don't know what it is
+
+void Fl::own_colormap() {}
+
+#else
+// X version
+
+void Fl::own_colormap() {
+  fl_open_display();
+#if USE_COLORMAP
+  switch (fl_visual->c_class) {
+  case GrayScale :
+  case PseudoColor :
+  case DirectColor :
+    break;
+  default:
+    return; // don't do anything for non-colormapped visuals
+  }
+  int i;
+  XColor colors[16];
+  // Get the first 16 colors from the default colormap...
+  for (i = 0; i < 16; i ++) colors[i].pixel = i;
+  XQueryColors(fl_display, fl_colormap, colors, 16);
+  // Create a new colormap...
+  fl_colormap = XCreateColormap(fl_display,
+				RootWindow(fl_display,fl_screen),
+				fl_visual->visual, AllocNone);
+  // Copy those first 16 colors to our own colormap:
+  for (i = 0; i < 16; i ++)
+    XAllocColor(fl_display, fl_colormap, colors + i);
+#endif
+}
+
+#endif
diff --git a/src/Fl_visual.cxx b/src/Fl_visual.cxx
new file mode 100644
index 000000000..d45c3ed49
--- /dev/null
+++ b/src/Fl_visual.cxx
@@ -0,0 +1,78 @@
+// Fl_visual.C
+//
+// Set the default visual according to passed switches:
+
+#include 
+#include 
+#include 
+
+#ifdef WIN32
+int Fl::visual(int flags) {
+  if (flags & FL_DOUBLE) return 0;
+  if (!(flags & FL_INDEX) &&
+    GetDeviceCaps(fl_GetDC(0),BITSPIXEL) <= 8) return 0;
+  if ((flags & FL_RGB8) && GetDeviceCaps(fl_GetDC(0),BITSPIXEL)<24) return 0;
+  return 1;
+}
+#else
+
+#if USE_XDBE
+#include 
+#endif
+
+static int test_visual(XVisualInfo& v, int flags) {
+  if (v.screen != fl_screen) return 0;
+  if (!(flags & FL_INDEX)) {
+    if (!v.red_mask) return 0; // detects static, true, and direct color
+    if (v.depth <= 8) return 0; // fltk will work better in colormap mode
+  }
+  if (flags & FL_RGB8) {
+    if (v.depth < 24) return 0;
+  }
+  // for now, fltk does not like colormaps of more than 8 bits:
+  if (!v.red_mask && v.depth > 8) return 0;
+#if USE_XDBE
+  if (flags & FL_DOUBLE) {
+    static XdbeScreenVisualInfo *xdbejunk;
+    if (!xdbejunk) {
+      int event_base, error_base;
+      if (!XdbeQueryExtension(fl_display, &event_base, &error_base)) return 0;
+      Drawable root = RootWindow(fl_display,fl_screen);
+      int numscreens = 1;
+      xdbejunk = XdbeGetVisualInfo(fl_display,&root,&numscreens);
+      if (!xdbejunk) return 0;
+    }
+    for (int j = 0; ; j++) {
+      if (j >= xdbejunk->count) return 0;
+      if (xdbejunk->visinfo[j].visual == v.visualid) break;
+    }
+  }
+#endif
+  return 1;
+}
+
+int Fl::visual(int flags) {
+#if USE_XDBE == 0
+  if (flags & FL_DOUBLE) return 0;
+#endif
+  fl_open_display();
+  // always use default if possible:
+  if (test_visual(*fl_visual, flags)) return 1;
+  // get all the visuals:
+  XVisualInfo vTemplate;
+  int num;
+  XVisualInfo *visualList = XGetVisualInfo(fl_display, 0, &vTemplate, &num);
+  // find all matches, use the one with greatest depth:
+  XVisualInfo *found = 0;
+  for (int i=0; idepth < visualList[i].depth)
+      found = &visualList[i];
+  }
+  if (!found) {XFree((void*)visualList); return 0;}
+  fl_visual = found;
+  fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen),
+				fl_visual->visual, AllocNone);
+  return 1;
+}
+
+#endif
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx
new file mode 100644
index 000000000..d00a22531
--- /dev/null
+++ b/src/Fl_win32.cxx
@@ -0,0 +1,696 @@
+// Fl_win32.C
+
+// fltk (Fast Light Tool Kit) version 0.99
+// Copyright (C) 1998 Bill Spitzak
+
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library 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
+// Library General Public License for more details.
+
+// You should have received a copy of the GNU Library 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.
+
+// Written by Bill Spitzak spitzak@d2.com
+
+// This file contains win32-specific code for fltk which is always linked
+// in.  Search other files for "WIN32" or filenames ending in _win32.C
+// for other system-specific code.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+////////////////////////////////////////////////////////////////
+// interface to poll/select call:
+
+// fd's are not yet implemented.
+// On NT these are probably only used for network stuff, so this may
+// talk to a package that Wonko has proposed writing to make the network
+// interface system independent.
+
+#define POLLIN 1
+#define POLLOUT 4
+#define POLLERR 8
+
+void Fl::add_fd(int n, int events, void (*cb)(int, void*), void *v) {}
+
+void Fl::add_fd(int fd, void (*cb)(int, void*), void* v) {
+  Fl::add_fd(fd,POLLIN,cb,v);
+}
+
+void Fl::remove_fd(int n) {}
+
+MSG fl_msg;
+
+int fl_ready() {
+  return PeekMessage(&fl_msg, NULL, 0, 0, PM_NOREMOVE);
+}
+
+double fl_wait(int timeout_flag, double time) {
+  int have_message;
+  // get the first message by waiting the correct amount of time:
+  if (!timeout_flag) {
+    GetMessage(&fl_msg, NULL, 0, 0);
+    have_message = 1;
+  } else {
+    if (time >= 0.001) {
+      int timerid = SetTimer(NULL, 0, int(time*1000), NULL);
+      GetMessage(&fl_msg, NULL, 0, 0);
+      KillTimer(NULL, timerid);
+      have_message = 1;
+    } else {
+      have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
+    }
+  }
+  // execute it, them execute any other messages that become ready during it:
+  while (have_message) {
+    DispatchMessage(&fl_msg);
+    have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
+  }
+  return time;
+}
+
+////////////////////////////////////////////////////////////////
+
+int Fl::h() {return GetSystemMetrics(SM_CYSCREEN);}
+
+int Fl::w() {return GetSystemMetrics(SM_CXSCREEN);}
+
+void Fl::get_mouse(int &x, int &y) {
+  POINT p;
+  GetCursorPos(&p);
+  x = p.x;
+  y = p.y;
+}
+
+////////////////////////////////////////////////////////////////
+
+extern Fl_Window *fl_xfocus;	// in Fl.C
+extern Fl_Window *fl_xmousewin; // in Fl.C
+void fl_fix_focus(); // in Fl.C
+
+////////////////////////////////////////////////////////////////
+
+extern HWND fl_capture;
+
+static int mouse_event(Fl_Window *window, int what, int button,
+			WPARAM wParam, LPARAM lParam)
+{
+  static int px, py, pmx, pmy;
+  POINT pt;
+  Fl::e_x = pt.x = (signed short)LOWORD(lParam);
+  Fl::e_y = pt.y = (signed short)HIWORD(lParam);
+  ClientToScreen(fl_xid(window), &pt);
+  Fl::e_x_root = pt.x;
+  Fl::e_y_root = pt.y;
+  while (window->parent()) {
+    Fl::e_x += window->x();
+    Fl::e_y += window->y();
+    window = window->window();
+  }
+
+  ulong state = Fl::e_state & 0xff0000; // keep shift key states
+#if 0
+  // mouse event reports some shift flags, perhaps save them?
+  if (wParam & MK_SHIFT) state |= FL_SHIFT;
+  if (wParam & MK_CONTROL) state |= FL_CTRL;
+#endif
+  if (wParam & MK_LBUTTON) state |= FL_BUTTON1;
+  if (wParam & MK_MBUTTON) state |= FL_BUTTON2;
+  if (wParam & MK_RBUTTON) state |= FL_BUTTON3;
+  Fl::e_state = state;
+
+  switch (what) {
+  case 1: // double-click
+    if (Fl::e_is_click) {Fl::e_clicks++; goto J1;}
+  case 0: // single-click
+    Fl::e_clicks = 0;
+  J1:
+    if (!fl_capture) SetCapture(fl_xid(window));
+    Fl::e_keysym = FL_Button + button;
+    Fl::e_is_click = 1;
+    px = pmx = Fl::e_x_root; py = pmy = Fl::e_y_root;
+    return Fl::handle(FL_PUSH,window);
+
+  case 2: // release:
+    if (!fl_capture) ReleaseCapture();
+    Fl::e_keysym = FL_Button + button;
+    return Fl::handle(FL_RELEASE,window);
+
+  case 3: // move:
+  default: // avoid compiler warning
+    // MSWindows produces extra events even if mouse does not move, ignore em:
+    if (Fl::e_x_root == pmx && Fl::e_y_root == pmy) return 1;
+    pmx = Fl::e_x_root; pmy = Fl::e_y_root;
+    if (abs(Fl::e_x_root-px)>5 || abs(Fl::e_y_root-py)>5) Fl::e_is_click = 0;
+    return Fl::handle(FL_MOVE,window);
+
+  }
+}
+
+// convert a Micro$oft VK_x to an Fltk (X) Keysym:
+// See also the inverse converter in Fl_get_key_win32.C
+// This table is in numeric order by VK:
+static const struct {unsigned short vk, fltk;} vktab[] = {
+  {VK_BACK,	FL_BackSpace},
+  {VK_TAB,	FL_Tab},
+  {VK_CLEAR,	FL_KP+'5'},
+  {VK_RETURN,	FL_Enter},
+  {VK_SHIFT,	FL_Shift_L},
+  {VK_CONTROL,	FL_Control_L},
+  {VK_MENU,	FL_Alt_L},
+  {VK_PAUSE,	FL_Pause},
+  {VK_CAPITAL,	FL_Caps_Lock},
+  {VK_ESCAPE,	FL_Escape},
+  {VK_SPACE,	' '},
+  {VK_PRIOR,	FL_Page_Up},
+  {VK_NEXT,	FL_Page_Down},
+  {VK_END,	FL_End},
+  {VK_HOME,	FL_Home},
+  {VK_LEFT,	FL_Left},
+  {VK_UP,	FL_Up},
+  {VK_RIGHT,	FL_Right},
+  {VK_DOWN,	FL_Down},
+  {VK_SNAPSHOT,	FL_Print},	// does not work on NT
+  {VK_INSERT,	FL_Insert},
+  {VK_DELETE,	FL_Delete},
+  {VK_LWIN,	FL_Meta_L},
+  {VK_RWIN,	FL_Meta_R},
+  {VK_APPS,	FL_Menu},
+  {VK_MULTIPLY,	FL_KP+'*'},
+  {VK_ADD,	FL_KP+'+'},
+  {VK_SUBTRACT,	FL_KP+'-'},
+  {VK_DECIMAL,	FL_KP+'.'},
+  {VK_DIVIDE,	FL_KP+'/'},
+  {VK_NUMLOCK,	FL_Num_Lock},
+  {VK_SCROLL,	FL_Scroll_Lock},
+  {0xba,	';'},
+  {0xbb,	'='},
+  {0xbc,	','},
+  {0xbd,	'-'},
+  {0xbe,	'.'},
+  {0xbf,	'/'},
+  {0xc0,	'`'},
+  {0xdb,	'['},
+  {0xdc,	'\\'},
+  {0xdd,	']'},
+  {0xde,	'\''}
+};
+static int ms2fltk(int vk, int extended) {
+  static unsigned short vklut[256];
+  if (!vklut[1]) { // init the table
+    int i;
+    for (i = 0; i < 256; i++) vklut[i] = tolower(i);
+    for (i=VK_F1; i<=VK_F16; i++) vklut[i] = i+(FL_F-(VK_F1-1));
+    for (i=VK_NUMPAD0; i<=VK_NUMPAD9; i++) vklut[i] = i+(FL_KP+'0'-VK_NUMPAD0);
+    for (i = 0; i < sizeof(vktab)/sizeof(*vktab); i++)
+      vklut[vktab[i].vk] = vktab[i].fltk;
+  }
+  if (extended) switch (vk) {
+    case VK_CONTROL : return FL_Control_R;
+    case VK_MENU: return FL_Alt_R;
+    case VK_RETURN: return FL_KP_Enter;
+  }
+  return vklut[vk];
+}
+
+char fl_direct_paint;
+static HDC direct_paint_dc;
+
+#if USE_COLORMAP
+extern HPALETTE fl_select_palette(); // in fl_color_win32.C
+#endif
+
+static Fl_Window* resize_bug_fix;
+
+static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
+{
+  static char buffer[2];
+
+  fl_msg.message = uMsg;
+
+  Fl_Window *window = fl_find(hWnd);
+
+ STUPID_MICROSOFT:
+  if (window) switch (uMsg) {
+
+  case WM_QUIT: // this should not happen?
+    Fl::fatal("WM_QUIT message");
+
+  case WM_CLOSE: // user clicked close box
+    Fl::handle(FL_CLOSE, window);
+    return 0;
+
+  case WM_PAINT: {
+    // MSWindows has already set the clip region!  Fltk does not like this,
+    // since it wants to draw it's own damage at the same time, and
+    // this damage may be outside the clip region.  I kludge around
+    // this, grep for fl_direct_paint to find the kludges...
+    if (!window->damage()) fl_direct_paint = 1;
+    PAINTSTRUCT ps;
+    direct_paint_dc = BeginPaint(hWnd, &ps);
+    window->expose(2, ps.rcPaint.left, ps.rcPaint.top,
+		   ps.rcPaint.right-ps.rcPaint.left,
+		   ps.rcPaint.bottom-ps.rcPaint.top);
+    if (!fl_direct_paint) {EndPaint(hWnd,&ps);ReleaseDC(hWnd,direct_paint_dc);}
+    Fl_X::i(window)->flush();
+    window->clear_damage();
+    Fl_X::i(window)->region = 0;
+    if (fl_direct_paint) {EndPaint(hWnd, &ps); fl_direct_paint = 0;}
+    } break;
+
+  case WM_LBUTTONDOWN:  mouse_event(window, 0, 1, wParam, lParam); return 0;
+  case WM_LBUTTONDBLCLK:mouse_event(window, 1, 1, wParam, lParam); return 0;
+  case WM_LBUTTONUP:    mouse_event(window, 2, 1, wParam, lParam); return 0;
+  case WM_MBUTTONDOWN:  mouse_event(window, 0, 2, wParam, lParam); return 0;
+  case WM_MBUTTONDBLCLK:mouse_event(window, 1, 2, wParam, lParam); return 0;
+  case WM_MBUTTONUP:    mouse_event(window, 2, 2, wParam, lParam); return 0;
+  case WM_RBUTTONDOWN:  mouse_event(window, 0, 3, wParam, lParam); return 0;
+  case WM_RBUTTONDBLCLK:mouse_event(window, 1, 3, wParam, lParam); return 0;
+  case WM_RBUTTONUP:    mouse_event(window, 2, 3, wParam, lParam); return 0;
+  case WM_MOUSEMOVE:    mouse_event(window, 3, 0, wParam, lParam); return 0;
+
+  // kludges so the pop-up menus work.  Title bar still blinks, sigh...
+  case WM_CAPTURECHANGED:
+    if (fl_capture && lParam != (LPARAM)fl_capture) {
+      SetCapture(fl_capture);
+      return 0;
+    }
+    break;
+  case WM_ACTIVATE:
+    if (fl_capture && wParam && hWnd!=fl_capture) {
+      SetActiveWindow(fl_capture);
+      return 0;
+    }
+    break;
+
+  case WM_SETFOCUS:
+    Fl::handle(FL_FOCUS, window);
+    break;
+
+  case WM_KILLFOCUS:
+    Fl::handle(FL_UNFOCUS, window);
+    Fl::flush(); // it never returns to main loop when deactivated...
+    break;
+
+  case WM_SHOWWINDOW:
+    if (!window->parent())
+      Fl::handle(wParam ? FL_SHOW : FL_HIDE, window);
+    break;
+
+  case WM_KEYDOWN:
+  case WM_SYSKEYDOWN:
+    // save the keysym until we figure out the characters:
+    Fl::e_keysym = ms2fltk(wParam,lParam&(1<<24));
+  case WM_KEYUP:
+  case WM_SYSKEYUP:
+    TranslateMessage(&fl_msg); // always returns 1!!!
+    // TranslateMessage is supposed to return true only if it turns
+    // into another message, but it seems to always return 1 on my
+    // NT machine.  So I will instead peek to see if there is a
+    // character message in the queue, I hope this can only happen
+    // if the translation worked:
+    if (PeekMessage(&fl_msg, hWnd, WM_CHAR, WM_SYSDEADCHAR, 1)) {
+      uMsg = fl_msg.message;
+      wParam = fl_msg.wParam;
+      lParam = fl_msg.lParam;
+      goto STUPID_MICROSOFT;
+    }
+    // otherwise use it as a 0-character key...
+  case WM_DEADCHAR:
+  case WM_SYSDEADCHAR:
+    buffer[0] = 0;
+    Fl::e_text = buffer;
+    Fl::e_length = 0;
+    goto GETSTATE;
+  case WM_CHAR:
+  case WM_SYSCHAR:
+    buffer[0] = char(wParam);
+    Fl::e_text = buffer;
+    Fl::e_length = 1;
+  GETSTATE:
+    {ulong state = Fl::e_state & 0xff000000; // keep the mouse button state
+     // if GetKeyState is expensive we might want to comment some of these out:
+      if (GetKeyState(VK_SHIFT)&~1) state |= FL_SHIFT;
+      if (GetKeyState(VK_CAPITAL)) state |= FL_CAPS_LOCK;
+      if (GetKeyState(VK_CONTROL)&~1) state |= FL_CTRL;
+      // Alt gets reported for the Alt-GR switch on foreign keyboards.
+      // so we need to check the event as well to get it right:
+      if ((lParam&(1<<29)) //same as GetKeyState(VK_MENU)
+	&& uMsg != WM_CHAR) state |= FL_ALT;
+      if (GetKeyState(VK_NUMLOCK)) state |= FL_NUM_LOCK;
+      if (GetKeyState(VK_LWIN)&~1 || GetKeyState(VK_RWIN)&~1) state |= FL_META;
+      if (GetKeyState(VK_SCROLL)) state |= FL_SCROLL_LOCK;
+      Fl::e_state = state;}
+    if (lParam & (1<<31)) goto DEFAULT; // ignore up events after fixing shift
+    // for (int i = lParam&0xff; i--;)
+    while (window->parent()) window = window->window();
+    if (Fl::handle(FL_KEYBOARD,window)) return 0;
+    break;
+
+  case WM_GETMINMAXINFO:
+    Fl_X::i(window)->set_minmax((LPMINMAXINFO)lParam);
+    break;
+
+  case WM_SIZE:
+    if (!window->parent()) {
+      if (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXHIDE) {
+	Fl::handle(FL_HIDE, window);
+      } else {
+	Fl::handle(FL_SHOW, window);
+	resize_bug_fix = window;
+	window->size(LOWORD(lParam), HIWORD(lParam));
+      }
+    }
+    break;
+
+  case WM_MOVE:
+    resize_bug_fix = window;
+    window->position(LOWORD(lParam), HIWORD(lParam));
+    break;
+
+  case WM_SETCURSOR:
+    if (LOWORD(lParam) == HTCLIENT) {
+      while (window->parent()) window = window->window();
+      SetCursor(Fl_X::i(window)->cursor);
+      return 0;
+    }
+    break;
+
+#if USE_COLORMAP
+  case WM_QUERYNEWPALETTE :
+    fl_GetDC(hWnd);
+    if (fl_select_palette()) InvalidateRect(hWnd, NULL, FALSE);
+    break;
+       
+  case WM_PALETTECHANGED:
+    fl_GetDC(hWnd);
+    if ((HWND)wParam != hWnd && fl_select_palette()) UpdateColors(fl_gc);
+    break;
+
+  case WM_CREATE :
+    fl_GetDC(hWnd);
+    fl_select_palette();
+    break;
+#endif
+
+  default:
+  DEFAULT:
+    if (Fl::handle(0,0)) return 0;
+    break;
+  }
+
+  return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+////////////////////////////////////////////////////////////////
+
+void Fl_Window::resize(int X,int Y,int W,int H) {
+  int resize_from_program = 1;
+  if (this == resize_bug_fix) {
+    resize_from_program = 0;
+    resize_bug_fix = 0;
+  }
+  if (X==x() && Y==y() && W==w() && H==h()) return;
+  if (X != x() || Y != y()) set_flag(FL_FORCE_POSITION);
+  if (W != w() || H != h()) Fl_Group::resize(X,Y,W,H); else {x(X); y(Y);}
+  if (resize_from_program && shown()) {
+    if (border() && !parent()) {
+      X -= GetSystemMetrics(SM_CXFRAME);
+      Y -= GetSystemMetrics(SM_CYFRAME)+GetSystemMetrics(SM_CYCAPTION);
+      W += 2*GetSystemMetrics(SM_CXFRAME);
+      H += 2*GetSystemMetrics(SM_CYFRAME)+GetSystemMetrics(SM_CYCAPTION);
+    }
+    MoveWindow(i->xid, X, Y, W, H, TRUE);
+    //if (!parent()) redraw();
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+char fl_show_iconic;	// hack for Fl_Window::iconic()
+// int fl_background_pixel = -1; // color to use for background
+HCURSOR fl_default_cursor;
+int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR
+
+Fl_X* Fl_X::make(Fl_Window* w) {
+  Fl_Group::current(0); // get rid of very common user bug: forgot end()
+  w->clear_damage(); // wait for expose events
+
+  static char* class_name;
+  if (!class_name) {	// create a single WNDCLASS used for everything:
+    class_name = "FLTK";
+    WNDCLASSEX wc;
+    wc.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC | CS_DBLCLKS;
+    wc.lpfnWndProc = (WNDPROC)WndProc;
+    wc.cbClsExtra = wc.cbWndExtra = 0;
+    wc.hInstance = fl_display;
+    wc.hIcon = wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
+    wc.hCursor = fl_default_cursor = LoadCursor(NULL, IDC_ARROW);
+    //uchar r,g,b; Fl::get_color(FL_GRAY,r,g,b);
+    //wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(r,g,b));
+    wc.hbrBackground = NULL;
+    wc.lpszMenuName = NULL;
+    wc.lpszClassName = class_name;
+    wc.cbSize = sizeof(WNDCLASSEX);
+    RegisterClassEx(&wc);
+  }
+
+  HWND parent;
+  DWORD style;
+  DWORD styleEx;
+  int xp = w->x();
+  int yp = w->y();
+  int wp = w->w();
+  int hp = w->h();
+
+  if (w->parent()) {
+    style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+    styleEx = WS_EX_LEFT | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT;
+    parent = fl_xid(w->window());
+  } else {
+    if (!w->size_range_set) {
+      if (w->resizable()) {
+	Fl_Widget *o = w->resizable();
+	int minw = o->w(); if (minw > 100) minw = 100;
+	int minh = o->h(); if (minh > 100) minh = 100;
+	w->size_range(w->w() - o->w() + minw, w->h() - o->h() + minh, 0, 0);
+      } else {
+	w->size_range(w->w(), w->h(), w->w(), w->h());
+      }
+    }
+    if (w->border()) {
+      style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
+	| WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+      styleEx = WS_EX_LEFT | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT;
+      if (w->maxw != w->minw || w->maxh != w->minh)
+	style |= WS_THICKFRAME | WS_MAXIMIZEBOX;
+      if (!w->modal()) style |= WS_MINIMIZEBOX;
+      xp -= GetSystemMetrics(SM_CXFRAME);
+      yp -= GetSystemMetrics(SM_CYFRAME)+GetSystemMetrics(SM_CYCAPTION);
+      wp += 2*GetSystemMetrics(SM_CXFRAME);
+      hp += 2*GetSystemMetrics(SM_CYFRAME)+GetSystemMetrics(SM_CYCAPTION);
+    } else {
+      style = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPED;
+      styleEx = WS_EX_LEFT | WS_EX_TOPMOST | WS_EX_TOOLWINDOW;
+    }
+    if (!(w->flags() & Fl_Window::FL_FORCE_POSITION)) {
+      xp = yp = CW_USEDEFAULT;
+    }
+    parent = 0;
+    if (w->non_modal() && !fl_disable_transient_for) {
+      // find some other window to be "transient for":
+      for (Fl_X* y = Fl_X::first; y; y = y->next) {
+	Fl_Window* w = y->w;
+	while (w->parent()) w = w->window();
+	if (!w->non_modal()) {
+	  parent = fl_xid(w);
+	  break;
+	}
+      }
+    }
+  }
+
+  Fl_X* x = new Fl_X;
+  x->other_xid = 0;
+  x->setwindow(w);
+  x->region = 0;
+  x->private_dc = 0;
+  x->cursor = fl_default_cursor;
+  x->xid = CreateWindowEx(
+    styleEx,
+    class_name, w->label(), style,
+    xp, yp, wp, hp,
+    parent,
+    NULL, // menu
+    fl_display,
+    NULL // creation parameters
+    );
+  x->next = Fl_X::first;
+  Fl_X::first = x;
+
+  // use w->xclass() to set the icon...
+
+  w->set_visible();
+  w->handle(FL_SHOW); // get child windows to appear
+  ShowWindow(x->xid, fl_show_iconic ? SW_MINIMIZE : SW_SHOW);
+  fl_show_iconic = 0;
+  fl_fix_focus();
+  return x;
+}
+
+////////////////////////////////////////////////////////////////
+
+HINSTANCE fl_display;
+
+int Fl_WinMain(HINSTANCE hInstance, LPSTR lpCmdLine, int nCmdShow,
+	       int (*mainp)(int, char**)) {
+  fl_display = hInstance;
+
+  int argc;
+  char **argv;
+  // test version for now:
+  argc = 1; char* testargv[] = {"test", 0}; argv = testargv;
+
+  return mainp(argc, argv);
+}
+
+////////////////////////////////////////////////////////////////
+
+void Fl_Window::size_range_() {
+  size_range_set = 1;
+}
+
+void Fl_X::set_minmax(LPMINMAXINFO minmax)
+{
+  int wd, hd;
+  if (w->border()) {
+    wd = 2*GetSystemMetrics(SM_CXFRAME);
+    hd = 2*GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
+  } else {
+    wd = hd = 0;
+  }
+  minmax->ptMinTrackSize.x = w->minw + wd;
+  minmax->ptMinTrackSize.y = w->minh + hd;
+  if (w->maxw) {
+    minmax->ptMaxTrackSize.x = w->maxw + wd;
+    minmax->ptMaxSize.x = w->maxw + wd;
+  }
+  if (w->maxh) {
+    minmax->ptMaxTrackSize.y = w->maxh + hd;
+    minmax->ptMaxSize.y = w->maxh + hd;
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+// returns pointer to the filename, or null if name ends with '/'
+const char *filename_name(const char *name) {
+  const char *p,*q;
+  q = name;
+  if (q[0] && q[1]==':') q += 2; // skip leading drive letter
+  for (p = q; *p; p++) if (*p == '/' || *p == '\\') q = p+1;
+  return q;
+}
+
+void Fl_Window::label(const char *name,const char *iname) {
+  Fl_Widget::label(name);
+  iconlabel_ = iname;
+  if (shown() && !parent()) {
+    if (!name) name = "";
+    SetWindowText(i->xid, name);
+    // if (!iname) iname = filename_name(name);
+    // should do something with iname here...
+  }
+}
+
+////////////////////////////////////////////////////////////////
+// Implement the virtual functions for the base Fl_Window class:
+
+// If the box is a filled rectangle, we can make the redisplay *look*
+// faster by using X's background pixel erasing.  We can make it
+// actually *be* faster by drawing the frame only, this is done by
+// setting fl_boxcheat, which is seen by code in fl_drawbox.C:
+// For WIN32 it looks like all windows share a background color, so
+// I use FL_GRAY for this and only do this cheat for windows that are
+// that color.
+// Actually it is totally disabled.
+// Fl_Widget *fl_boxcheat;
+//static inline int can_boxcheat(uchar b) {return (b==1 || (b&2) && b<=15);}
+
+void Fl_Window::show() {
+  if (!shown()) {
+    // if (can_boxcheat(box())) fl_background_pixel = fl_xpixel(color());
+    Fl_X::make(this);
+  } else {
+    ShowWindow(i->xid, SW_RESTORE);
+    SetActiveWindow(i->xid);
+  }
+}
+
+Fl_Window *Fl_Window::current_;
+HDC fl_gc; // the current context
+HWND fl_window; // the current window
+
+// Make sure we always ReleaseDC every DC we allocate...
+HDC fl_GetDC(HWND w) {
+  if (fl_gc) {
+    if (w == fl_window) return fl_gc;
+    ReleaseDC(fl_window, fl_gc);
+  }
+  fl_gc = fl_direct_paint ? direct_paint_dc : GetDC(w);
+  fl_window = w;
+  // calling GetDC seems to always reset these: (?)
+  SetTextAlign(fl_gc, TA_BASELINE|TA_LEFT);
+  SetBkMode(fl_gc, TRANSPARENT);
+  return fl_gc;
+}
+
+// make X drawing go into this window (called by subclass flush() impl.)
+void Fl_Window::make_current() {
+  fl_GetDC(fl_xid(this));
+  current_ = this;
+}
+
+// WM_PAINT events and cropped damage call this:
+void Fl_Window::expose(uchar flags,int X,int Y,int W,int H) {
+  if (i) {
+    if (!i->region.r) {
+      i->region.x = X;
+      i->region.y = Y;
+      i->region.r = X+W;
+      i->region.b = Y+H;
+    } else {
+      if (X < i->region.x) i->region.x = X;
+      if (Y < i->region.y) i->region.y = Y;
+      if (X+W > i->region.r) i->region.r = X+W;
+      if (Y+H > i->region.b) i->region.b = Y+H;
+    }
+  }
+  damage(flags);
+}
+
+#include 
+
+void Fl_Window::flush() {
+  make_current();
+  if (damage() & ~6) {
+    draw();
+  } else {
+    fl_clip_region(i->region);
+    draw();
+    fl_pop_clip();
+  }
+}
+
+// End of Fl_win32.C //
diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx
new file mode 100644
index 000000000..2d5a5ab46
--- /dev/null
+++ b/src/Fl_x.cxx
@@ -0,0 +1,807 @@
+// Fl_x.C
+
+// fltk (Fast Light Tool Kit) version 0.99
+// Copyright (C) 1998 Bill Spitzak
+
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library 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
+// Library General Public License for more details.
+
+// You should have received a copy of the GNU Library 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.
+
+// Written by Bill Spitzak spitzak@d2.com
+
+#ifdef WIN32
+#include "Fl_win32.C"
+#else
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+////////////////////////////////////////////////////////////////
+// interface to poll/select call:
+
+#if HAVE_POLL
+#include 
+#else
+struct pollfd {int fd; short events; short revents;};
+#define POLLIN 1
+#define POLLOUT 4
+#define POLLERR 8
+#ifdef __sgi // fix bugs in Irix's select header:
+//inline static void bzero(void *b, int l) {memset(b,0,l);}
+extern "C" int	select( int, fd_set *, fd_set *, fd_set *, struct timeval * );
+#endif
+#ifdef hpux // fix from wm2:
+#define select(a,b,c,d,e) select((a),(int *)(b),(int *)(c),(int *)(d),(e))
+#endif
+#ifdef __EMX__
+#include 
+#endif
+#endif
+
+#define MAXFD 8
+#if !HAVE_POLL
+static fd_set fdsets[3];
+static int maxfd;
+#endif
+static int nfds;
+static struct pollfd fds[MAXFD];
+static struct {
+  void (*cb)(int, void*);
+  void* arg;
+} fd[MAXFD];
+
+void Fl::add_fd(int n, int events, void (*cb)(int, void*), void *v) {
+  int i;
+  if (nfds < MAXFD) {i = nfds; nfds++;} else {i = MAXFD-1;}
+  fds[i].fd = n;
+  fds[i].events = events;
+#if !HAVE_POLL
+  if (events & POLLIN) FD_SET(n, &fdsets[0]);
+  if (events & POLLOUT) FD_SET(n, &fdsets[1]);
+  if (events & POLLERR) FD_SET(n, &fdsets[2]);
+  if (n > maxfd) maxfd = n;
+#endif
+  fd[i].cb = cb;
+  fd[i].arg = v;
+}
+
+void Fl::add_fd(int fd, void (*cb)(int, void*), void* v) {
+  Fl::add_fd(fd,POLLIN,cb,v);
+}
+
+void Fl::remove_fd(int n) {
+  int i,j;
+  for (i=j=0; i 0.0 ? int(time*1000) : 0);
+#else
+    timeval t;
+    if (time <= 0.0) {
+      t.tv_sec = 0;
+      t.tv_usec = 0;
+    } else {
+      t.tv_sec = int(time);
+      t.tv_usec = int(1000000 * (time-t.tv_sec));
+    }
+    n = ::select(maxfd+1,&fdt[0],&fdt[1],&fdt[2],&t);
+#endif
+  }
+  if (n > 0) {
+    for (int i=0; irequest_code);
+  XGetErrorDatabaseText(d,"",buf1,buf1,buf2,128);
+  XGetErrorText(d, e->error_code, buf1, 128);
+  Fl::warning("%s: %s 0x%lx", buf2, buf1, e->resourceid);
+  return 0;
+}
+
+void fl_open_display() {
+  if (fl_display) return;
+
+  XSetIOErrorHandler(io_error_handler);
+  XSetErrorHandler(xerror_handler);
+
+  Display *d = XOpenDisplay(0);
+  if (!d) Fl::fatal("Can't open display: %s",XDisplayName(0));
+
+  fl_display = d;
+
+  wm_delete_window = XInternAtom(d,"WM_DELETE_WINDOW",0);
+  wm_protocols = XInternAtom(d,"WM_PROTOCOLS",0);
+  _motif_wm_hints = XInternAtom(d,"_MOTIF_WM_HINTS",0);
+  Fl::add_fd(ConnectionNumber(d), POLLIN, fd_callback);
+
+  fl_screen = DefaultScreen(fl_display);
+// construct an XVisualInfo that matches the default Visual:
+  XVisualInfo templt; int num;
+  templt.visualid = XVisualIDFromVisual(DefaultVisual(fl_display,fl_screen));
+  fl_visual = XGetVisualInfo(fl_display, VisualIDMask, &templt, &num);
+  fl_colormap = DefaultColormap(fl_display,fl_screen);
+}
+
+void fl_close_display() {
+  Fl::remove_fd(ConnectionNumber(fl_display));
+  XCloseDisplay(fl_display);
+}
+
+int Fl::h() {
+  fl_open_display();
+  return DisplayHeight(fl_display,fl_screen);
+}
+
+int Fl::w() {
+  fl_open_display();
+  return DisplayWidth(fl_display,fl_screen);
+}
+
+void Fl::get_mouse(int &x, int &y) {
+  fl_open_display();
+  Window root = RootWindow(fl_display, fl_screen);
+  Window c; int mx,my,cx,cy; unsigned int mask;
+  XQueryPointer(fl_display,root,&root,&c,&mx,&my,&cx,&cy,&mask);
+  x = mx;
+  y = my;
+}
+
+////////////////////////////////////////////////////////////////
+
+extern Fl_Window *fl_xfocus;	// in Fl.C
+extern Fl_Window *fl_xmousewin; // in Fl.C
+void fl_fix_focus(); // in Fl.C
+
+////////////////////////////////////////////////////////////////
+
+const XEvent* fl_xevent; // the current x event
+ulong fl_event_time; // the last timestamp from an x event
+
+char fl_key_vector[32]; // used by Fl::get_key()
+
+// Record event mouse position and state from an XEvent:
+
+static int px, py;
+static ulong ptime;
+
+static void set_event_xy() {
+  Fl::e_x_root = fl_xevent->xbutton.x_root;
+  Fl::e_x = fl_xevent->xbutton.x;
+  Fl::e_y_root = fl_xevent->xbutton.y_root;
+  Fl::e_y = fl_xevent->xbutton.y;
+  Fl::e_state = fl_xevent->xbutton.state << 16;
+  fl_event_time = fl_xevent->xbutton.time;
+#ifdef __sgi
+  // get the meta key off PC keyboards:
+  if (fl_key_vector[18]&0x18) Fl::e_state |= FL_META;
+#endif
+  // turn off is_click if enough time or mouse movement has passed:
+  if (abs(Fl::e_x_root-px)+abs(Fl::e_y_root-py) > 3 
+      || fl_event_time >= ptime+1000)
+    Fl::e_is_click = 0;
+}
+
+// if this is same event as last && is_click, increment click count:
+static inline void checkdouble() {
+  if (Fl::e_is_click == Fl::e_keysym)
+    Fl::e_clicks++;
+  else {
+    Fl::e_clicks = 0;
+    Fl::e_is_click = Fl::e_keysym;
+  }
+  px = Fl::e_x_root;
+  py = Fl::e_y_root;
+  ptime = fl_event_time;
+}
+
+static Fl_Window* resize_bug_fix;
+
+////////////////////////////////////////////////////////////////
+
+int fl_handle(const XEvent& xevent)
+{
+  fl_xevent = &xevent;
+
+  switch (xevent.type) { // events where we don't care about window
+
+  case KeymapNotify:
+    memcpy(fl_key_vector, xevent.xkeymap.key_vector, 32);
+    return 0;
+
+  case MappingNotify:
+    XRefreshKeyboardMapping((XMappingEvent*)&xevent.xmapping);
+    return 0;
+  }
+
+  int event = 0;
+  Fl_Window* window = fl_find(xevent.xany.window);
+
+  if (window) switch (xevent.type) {
+
+  case ClientMessage:
+    if ((Atom)(xevent.xclient.data.l[0]) == wm_delete_window) event = FL_CLOSE;
+    break;
+
+  case MapNotify:
+    event = FL_SHOW;
+    break;
+
+  case UnmapNotify:
+    event = FL_HIDE;
+    break;
+
+  case Expose:
+  case GraphicsExpose:
+#if 1	// try to keep windows on top even if WM_TRANSIENT_FOR does not work:
+    if (Fl::first_window()->non_modal() && window != Fl::first_window())
+      Fl::first_window()->show();
+#endif
+    window->damage(2, xevent.xexpose.x, xevent.xexpose.y,
+		   xevent.xexpose.width, xevent.xexpose.height);
+    return 1;
+
+  case ButtonPress:
+    Fl::e_keysym = FL_Button + xevent.xbutton.button;
+    set_event_xy(); checkdouble();
+    // fix buggy window managers that position window wrong:
+    Fl_X::x(window,Fl::e_x_root-Fl::e_x);
+    Fl_X::y(window,Fl::e_y_root-Fl::e_y);
+    Fl::e_state |= (FL_BUTTON1 << (xevent.xbutton.button-1));
+    event = FL_PUSH;
+    break;
+
+  case MotionNotify:
+    set_event_xy();
+    event = FL_MOVE;
+    break;
+
+  case ButtonRelease:
+    Fl::e_keysym = FL_Button + xevent.xbutton.button;
+    set_event_xy();
+    Fl::e_state &= ~(FL_BUTTON1 << (xevent.xbutton.button-1));
+    event = FL_RELEASE;
+    break;
+
+  case FocusIn:
+    event = FL_FOCUS;
+    break;
+
+  case FocusOut:
+    event = FL_UNFOCUS;
+    break;
+
+  case KeyPress: {
+    static int got_backspace;
+    static char buffer[21];
+    KeySym keysym;
+    int i = xevent.xkey.keycode; fl_key_vector[i/8] |= (1 << (i%8));
+    int len = XLookupString((XKeyEvent*)&(xevent.xkey),buffer,20,&keysym,0);
+    if (!len && keysym < 0x400) {
+      // turn all latin-2,3,4 characters into 8-bit codes:
+      buffer[0] = char(keysym);
+      len = 1;
+    }
+    // ignore all effects of shift on the keysyms (makes it a lot
+    // easier to program shortcuts!)
+    keysym = XKeycodeToKeysym(fl_display, i, 0);
+#ifdef __sgi
+    // get some missing PC keyboard keys:
+    if (!keysym) switch(i) {
+    case 147: keysym = FL_Meta_L; break;
+    case 148: keysym = FL_Meta_R; break;
+    case 149: keysym = FL_Menu; break;
+    }
+#endif
+    if (!got_backspace) {
+      // Backspace kludge: until user hits the backspace key, assumme
+      // it is missing and use the Delete key for that purpose:
+      if (keysym == FL_Delete) keysym = FL_BackSpace;
+      else if (keysym == FL_BackSpace) got_backspace = 1;
+    }
+    if (keysym >= 0xff95 && keysym < 0xffa0) {
+      // Make NumLock irrelevant (always on):
+      // This lookup table turns the XK_KP_* functions back into the
+      // ascii characters.  This won't work on non-PC layout keyboards,
+      // but are there any of those left??
+      buffer[0] = "7486293150."[keysym-0xff95];
+      len = 1;
+      keysym = FL_KP+buffer[0];
+    }
+    buffer[len] = 0;
+    Fl::e_keysym = int(keysym);
+    Fl::e_text = buffer;
+    Fl::e_length = len;
+    set_event_xy(); Fl::e_is_click = 0;
+    if (Fl::event_state(FL_CTRL) && keysym == '-') buffer[0] = 0x1f; // ^_
+    event = FL_KEYBOARD;
+    break;}
+
+  case KeyRelease: {
+    int i = xevent.xkey.keycode; fl_key_vector[i/8] &= ~(1 << (i%8));
+    set_event_xy();}
+    break;
+
+  case EnterNotify:
+    if (xevent.xcrossing.detail == NotifyInferior) break;
+    // XInstallColormap(fl_display, Fl_X::i(window)->colormap);
+    set_event_xy();
+    Fl::e_state = xevent.xcrossing.state << 16;
+    event = FL_ENTER;
+    break;
+
+  case LeaveNotify:
+    if (xevent.xcrossing.detail == NotifyInferior) break;
+    set_event_xy();
+    Fl::e_state = xevent.xcrossing.state << 16;
+    event = FL_LEAVE;
+    break;
+
+  case ConfigureNotify: {
+    int x = xevent.xconfigure.x;
+    int y = xevent.xconfigure.y;
+    // avoid bug (?) in 4DWM, it reports position of 0,0 on resize:
+    if (!x && !y) {
+      Window r, c; int X, Y; unsigned int m;
+      XQueryPointer(fl_display, fl_xid(window), &r, &c, &x, &y, &X, &Y, &m);
+      x = x-X; y = y-Y;
+    }
+    resize_bug_fix = window;
+    window->resize(x, y,
+		   xevent.xconfigure.width, xevent.xconfigure.height);
+    return 1;}
+  }
+
+  return Fl::handle(event, window);
+}
+
+////////////////////////////////////////////////////////////////
+
+void Fl_Window::resize(int X,int Y,int W,int H) {
+  if (resize_bug_fix == this)
+    resize_bug_fix = 0;
+  else if (shown()) {
+    // tell X window manager to change window size:
+    if (!(flags()&FL_FORCE_POSITION) && X == x() && Y == y())
+      XResizeWindow(fl_display, i->xid, W>0 ? W : 1, H>0 ? H : 1);
+    else if (W != w() || H != h())
+      XMoveResizeWindow(fl_display, i->xid, X, Y, W>0 ? W : 1, H>0 ? H : 1);
+    else
+      XMoveWindow(fl_display, i->xid, X, Y);
+  }
+  if (X != x() || Y != y()) set_flag(FL_FORCE_POSITION);
+  if (W != w() || H != h()) Fl_Group::resize(X,Y,W,H); else {x(X); y(Y);}
+  // Notice that this does *not* set any redraw bits.  I assumme
+  // I will receive damage for the whole window from X.  I think
+  // that "ForgetGravity" forces the expose event for the entire
+  // window, but this may not be true on some implementations.
+}
+
+////////////////////////////////////////////////////////////////
+
+// A subclass of Fl_Window may call this to associate an X window it
+// creates with the Fl_Window:
+
+Fl_X* Fl_X::set_xid(Fl_Window* w, Window xid) {
+  Fl_X* x = new Fl_X;
+  x->xid = xid;
+  x->other_xid = 0;
+  x->setwindow(w);
+  x->next = Fl_X::first;
+  x->region = 0;
+  Fl_X::first = x;
+  w->set_visible();
+  w->handle(FL_SHOW); // get child windows to appear
+  fl_fix_focus(); // if this is modal we must fix focus now
+  return x;
+}
+
+// More commonly a subclass calls this, because it hides the really
+// ugly parts of X and sets all the stuff for a window that is set
+// normally.  The global variables like fl_show_iconic are so that
+// subclasses of *that* class may change the behavior...
+
+char fl_show_iconic;	// hack for iconize()
+int fl_background_pixel = -1; // hack to speed up bg box drawing
+int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR
+
+static const int childEventMask = ExposureMask;
+
+static const int XEventMask =
+ExposureMask|StructureNotifyMask
+|KeyPressMask|KeyReleaseMask|KeymapStateMask|FocusChangeMask
+|ButtonPressMask|ButtonReleaseMask
+|EnterWindowMask|LeaveWindowMask
+|PointerMotionMask;
+
+void Fl_X::make_xid(Fl_Window* w, XVisualInfo *visual, Colormap colormap)
+{
+  Fl_Group::current(0); // get rid of very common user bug: forgot end()
+
+  ulong root = w->parent() ?
+    fl_xid(w->window()) : RootWindow(fl_display, fl_screen);
+
+  XSetWindowAttributes attr;
+  int mask = CWBorderPixel|CWColormap|CWEventMask|CWBitGravity;
+  attr.event_mask = w->parent() ? childEventMask : XEventMask;
+  attr.colormap = colormap;
+  attr.border_pixel = 0;
+  attr.bit_gravity = 0; // StaticGravity;
+  attr.override_redirect = 0;
+  if (Fl::grab()) {
+    attr.save_under = 1; mask |= CWSaveUnder;
+    if (!w->border()) {attr.override_redirect = 1; mask |= CWOverrideRedirect;}
+  }
+  if (fl_background_pixel >= 0) {
+    attr.background_pixel = fl_background_pixel;
+    fl_background_pixel = -1;
+    mask |= CWBackPixel;
+  }
+  Fl_X* x =
+    set_xid(w, XCreateWindow(fl_display,
+			     root,
+			     w->x(), w->y(),
+			     w->w()>0 ? w->w() : 1,
+			     w->h()>0 ? w->h() : 1,
+			     0, // borderwidth
+			     visual->depth,
+			     InputOutput,
+			     visual->visual,
+			     mask, &attr));
+  //XInstallColormap(fl_display, colormap);
+
+  if (!w->parent() && !attr.override_redirect) {
+    // Communicate all kinds 'o junk to the X Window Manager:
+
+    w->label(w->label(), w->iconlabel());
+
+    XChangeProperty(fl_display, x->xid, wm_protocols,
+ 		    XA_ATOM, 32, 0, (uchar*)&wm_delete_window, 1);
+
+    // send size limits and border:
+    x->sendxjunk();
+
+    // set the class property, which controls the icon used:
+    if (w->xclass()) {
+      char buffer[1024];
+      char *p; const char *q;
+      // truncate on any punctuation, because they break XResource lookup:
+      for (p = buffer, q = w->xclass(); isalnum(*q)||(*q&128);) *p++ = *q++;
+      *p++ = 0;
+      // create the capitalized version:
+      q = buffer;
+      *p = toupper(*q++); if (*p++ == 'X') *p++ = toupper(*q++);
+      while ((*p++ = *q++));
+      XChangeProperty(fl_display, x->xid, XA_WM_CLASS, XA_STRING, 8, 0,
+		      (unsigned char *)buffer, p-buffer-1);
+    }
+
+    if (w->non_modal() && x->next && !fl_disable_transient_for) {
+      // find some other window to be "transient for":
+      Fl_Window* w = x->next->w;
+      while (w->parent()) w = w->window();
+      XSetTransientForHint(fl_display, x->xid, fl_xid(w));
+    }
+
+    if (fl_show_iconic) {
+      XWMHints hints;
+      hints.flags = StateHint;
+      hints.initial_state = 3;
+      XSetWMHints(fl_display, x->xid, &hints);
+      fl_show_iconic = 0;
+    }
+  }
+
+  XMapWindow(fl_display, x->xid);
+}
+
+////////////////////////////////////////////////////////////////
+// Send X window stuff that can be changed over time:
+
+void Fl_X::sendxjunk() {
+  if (w->parent()) return; // it's not a window manager window!
+
+  if (!w->size_range_set) { // default size_range based on resizable():
+    if (w->resizable()) {
+      Fl_Widget *o = w->resizable();
+      int minw = o->w(); if (minw > 100) minw = 100;
+      int minh = o->h(); if (minh > 100) minh = 100;
+      w->size_range(w->w() - o->w() + minw, w->h() - o->h() + minh, 0, 0);
+    } else {
+      w->size_range(w->w(), w->h(), w->w(), w->h());
+    }
+    return; // because this recursively called here
+  }
+
+  XSizeHints hints;
+  hints.min_width = w->minw;
+  hints.min_height = w->minh;
+  hints.max_width = w->maxw;
+  hints.max_height = w->maxh;
+  hints.width_inc = w->dw;
+  hints.height_inc = w->dh;
+
+  // see the file /usr/include/X11/Xm/MwmUtil.h:
+  // fill all fields to avoid bugs in kwm and perhaps other window managers:
+  // 0, MWM_FUNC_ALL, MWM_DECOR_ALL
+  long prop[5] = {0, 1, 1, 0, 0};
+
+  if (hints.min_width != hints.max_width ||
+      hints.min_height != hints.max_height) { // resizable
+    hints.flags = PMinSize;
+    if (hints.max_width >= hints.min_width ||
+	hints.max_height >= hints.min_height) {
+      hints.flags = PMinSize|PMaxSize;
+      // unfortunately we can't set just one maximum size.  Guess a
+      // value for the other one.  Some window managers will make the
+      // window fit on screen when maximized, others will put it off screen:
+      if (hints.max_width < hints.min_width) hints.max_width = Fl::w();
+      if (hints.max_height < hints.min_height) hints.max_height = Fl::h();
+    }
+    if (hints.width_inc && hints.height_inc) hints.flags |= PResizeInc;
+    if (w->aspect) {
+      // stupid X!  It could insist that the corner go on the
+      // straight line between min and max...
+      hints.min_aspect.x = hints.max_aspect.x = hints.min_width;
+      hints.min_aspect.y = hints.max_aspect.y = hints.min_height;
+      hints.flags |= PAspect;
+    }
+  } else { // not resizable:
+    hints.flags = PMinSize|PMaxSize;
+    prop[0] = 1; // MWM_HINTS_FUNCTIONS
+    prop[1] = 1|2|16; // MWM_FUNC_ALL | MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE
+  }
+  if (w->non_modal()) {
+    prop[0] = 1; // MWM_HINTS_FUNCTIONS
+    prop[1] |= 8; // turn off MWM_FUNC_MINIMIZE in 4Dwm
+  }
+
+  if (w->flags() & Fl_Window::FL_FORCE_POSITION) {
+    hints.flags |= USPosition;
+    hints.x = w->x();
+    hints.y = w->y();
+  }
+
+  if (!w->border()) {
+    prop[0] |= 2; // MWM_HINTS_DECORATIONS
+    prop[2] = 0; // no decorations
+  }
+
+  XSetWMNormalHints(fl_display, xid, &hints);
+  XChangeProperty(fl_display, xid,
+		  _motif_wm_hints, _motif_wm_hints,
+		  32, 0, (unsigned char *)prop, 5);
+}
+
+void Fl_Window::size_range_() {
+  size_range_set = 1;
+  if (shown()) i->sendxjunk();
+}
+
+////////////////////////////////////////////////////////////////
+
+// returns pointer to the filename, or null if name ends with '/'
+const char *filename_name(const char *name) {
+  const char *p,*q;
+  for (p=q=name; *p;) if (*p++ == '/') q = p;
+  return q;
+}
+
+void Fl_Window::label(const char *name,const char *iname) {
+  Fl_Widget::label(name);
+  iconlabel_ = iname;
+  if (shown() && !parent()) {
+    if (!name) name = "";
+    XChangeProperty(fl_display, i->xid, XA_WM_NAME,
+		    XA_STRING, 8, 0, (uchar*)name, strlen(name));
+    if (!iname) iname = filename_name(name);
+    XChangeProperty(fl_display, i->xid, XA_WM_ICON_NAME, 
+		    XA_STRING, 8, 0, (uchar*)iname, strlen(iname));
+  }
+}
+
+////////////////////////////////////////////////////////////////
+// Implement the virtual functions for the base Fl_Window class:
+
+// If the box is a filled rectangle, we can make the redisplay *look*
+// faster by using X's background pixel erasing.  We can make it
+// actually *be* faster by drawing the frame only, this is done by
+// setting fl_boxcheat, which is seen by code in fl_drawbox.C:
+//
+// On XFree86 (and prehaps all X's) this has a problem if the window
+// is resized while a save-behind window is atop it.  The previous
+// contents are restored to the area, but this assummes the area
+// is cleared to background color.  So this is disabled in this version.
+// Fl_Window *fl_boxcheat;
+static inline int can_boxcheat(uchar b) {return (b==1 || (b&2) && b<=15);}
+
+void Fl_Window::show() {
+  if (!shown()) {
+    fl_open_display();
+    if (can_boxcheat(box())) fl_background_pixel = int(fl_xpixel(color()));
+    Fl_X::make_xid(this);
+  } else {
+    XMapRaised(fl_display, i->xid);
+  }
+}
+
+Window fl_window;
+Fl_Window *Fl_Window::current_;
+GC fl_gc;
+
+// make X drawing go into this window (called by subclass flush() impl.)
+void Fl_Window::make_current() {
+  static GC gc;	// the GC used by all X windows
+  if (!gc) gc = XCreateGC(fl_display, i->xid, 0, 0);
+  fl_window = i->xid;
+  fl_gc = gc;
+  current_ = this;
+  fl_clip_region(0);
+}
+
+#include 
+
+// Current meaning of damage() bits on a window:
+// 1 = a child needs redrawing
+// 2 = expose events
+// 128 = redraw everything
+
+void Fl_Widget::damage(uchar flags) {
+  if (type() < FL_WINDOW) {
+    damage(flags, x(), y(), w(), h());
+  } else {
+    Fl_X* i = Fl_X::i((Fl_Window*)this);
+    if (i) {
+      if (i->region) {XDestroyRegion(i->region); i->region = 0;}
+      damage_ |= flags;
+      Fl::damage(1);
+    }
+  }
+}
+
+void Fl_Widget::redraw() {damage(~0);}
+
+Region XRectangleRegion(int x, int y, int w, int h); // in fl_rect.C
+
+void Fl_Widget::damage(uchar flags, int X, int Y, int W, int H) {
+  if (type() < FL_WINDOW) {
+    damage_ |= flags;
+    if (parent()) parent()->damage(1,X,Y,W,H);
+  } else {
+    // see if damage covers entire window:
+    if (X<=0 && Y<=0 && W>=w() && H>=h()) {damage(flags); return;}
+    Fl_X* i = Fl_X::i((Fl_Window*)this);
+    if (i) {
+      if (damage()) {
+	// if we already have damage we must merge with existing region:
+	if (i->region) {
+	  XRectangle R;
+	  R.x = X; R.y = Y; R.width = W; R.height = H;
+	  XUnionRectWithRegion(&R, i->region, i->region);
+	}
+	damage_ |= flags;
+      } else {
+	// create a new region:
+	if (i->region) XDestroyRegion(i->region);
+	i->region = XRectangleRegion(X,Y,W,H);
+	damage_ = flags;
+      }
+      Fl::damage(1);
+    }
+  }
+}
+
+void Fl_Window::flush() {
+  make_current();
+//if (damage() == 2 && can_boxcheat(box())) fl_boxcheat = this;
+  fl_clip_region(i->region); i->region = 0;
+  draw();
+}
+
+#endif
+// End of Fl_x.C
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 000000000..1de491e1e
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,215 @@
+CPPFILES = \
+	Fl.C \
+	Fl_Adjuster.C \
+	Fl_Bitmap.C \
+	Fl_Browser.C \
+	Fl_Browser_.C \
+	Fl_Browser_load.C \
+	Fl_Box.C \
+	Fl_Button.C \
+	Fl_Chart.C \
+	Fl_Check_Button.C \
+	Fl_Choice.C \
+	Fl_Clock.C \
+	Fl_Color_Chooser.C \
+	Fl_Counter.C \
+	Fl_Dial.C \
+	Fl_Double_Window.C \
+	Fl_Gl_Choice.C \
+	Fl_Gl_Overlay.C \
+	Fl_Gl_Window.C \
+	Fl_Group.C \
+	Fl_Image.C \
+	Fl_Input.C \
+	Fl_Input_.C \
+	Fl_Light_Button.C \
+	Fl_Menu.C \
+	Fl_Menu_.C \
+	Fl_Menu_Bar.C \
+	Fl_Menu_Button.C \
+	Fl_Menu_Window.C \
+	Fl_Menu_add.C \
+	Fl_Menu_global.C \
+	Fl_Multi_Label.C \
+	Fl_Output.C \
+	Fl_Overlay_Window.C \
+	Fl_Pack.C \
+	Fl_Pixmap.C \
+	Fl_Positioner.C \
+	Fl_Repeat_Button.C \
+	Fl_Return_Button.C \
+	Fl_Roller.C \
+	Fl_Round_Button.C \
+	Fl_Scroll.C \
+	Fl_Scrollbar.C \
+	Fl_Single_Window.C \
+	Fl_Slider.C \
+	Fl_Tabs.C \
+	Fl_Tile.C \
+	Fl_Valuator.C \
+	Fl_Value_Input.C \
+	Fl_Value_Output.C \
+	Fl_Value_Slider.C \
+	Fl_Widget.C \
+	Fl_Window.C \
+	Fl_Window_fullscreen.C \
+	Fl_Window_hotspot.C \
+	Fl_Window_iconize.C \
+	Fl_abort.C \
+	Fl_add_idle.C \
+	Fl_arg.C \
+	Fl_cutpaste.C \
+	Fl_display.C \
+	Fl_get_key.C \
+	Fl_get_system_colors.C \
+	Fl_own_colormap.C \
+	Fl_visual.C \
+	Fl_x.C \
+	filename_absolute.C \
+	filename_expand.C \
+	filename_ext.C \
+	filename_isdir.C \
+	filename_list.C \
+	filename_match.C \
+	filename_setext.C \
+	fl_arc.C \
+	fl_arci.C \
+	fl_ask.C \
+	fl_boxtype.C \
+	fl_color.C \
+	fl_cursor.C \
+	fl_curve.C \
+	fl_diamond_box.C \
+	fl_draw.C \
+	fl_draw_image.C \
+	fl_draw_pixmap.C \
+	fl_engraved_label.C \
+	fl_file_chooser.C \
+	fl_font.C \
+	fl_labeltype.C \
+	fl_oval_box.C \
+	fl_overlay.C \
+	fl_overlay_visual.C \
+	fl_rect.C \
+	fl_round_box.C \
+	fl_rounded_box.C \
+	fl_set_font.C \
+	fl_set_fonts.C \
+	fl_scroll_area.C \
+	fl_shadow_box.C \
+	fl_shortcut.C \
+	fl_show_colormap.C \
+	fl_symbols.C \
+	fl_vertex.C \
+	forms_compatability.C \
+	forms_bitmap.C \
+	forms_free.C \
+	forms_fselect.C \
+	forms_pixmap.C \
+	forms_timer.C \
+	gl_draw.C \
+	gl_start.C \
+	glut_compatability.C \
+	glut_font.C
+
+CFILES = scandir.c numericsort.c
+
+CLEAN =
+
+################################################################
+
+include ../makeinclude
+
+LIBRARY = ../lib/$(LIBNAME)
+
+OBJECTS = $(CPPFILES:.C=.o) $(CFILES:.c=.o)
+
+$(LIBRARY) : $(OBJECTS)
+	@echo Building $(LIBRARY)
+	@$(AR) $(LIBRARY) $(OBJECTS)
+	@$(RANLIB) $(LIBRARY)
+
+.C.o :
+	@echo $<:
+	@$(CXX) -I.. $(CXXFLAGS) -c $<
+.c.o :
+	@echo $<:
+	@$(CC) -I.. $(CFLAGS) -c -o $@ $<
+
+clean :
+	-@ rm -f *.o *.do $(LIBRARY) $(CLEAN) core *~ makedepend
+	@touch makedepend
+
+depend:
+	@echo Making makedepend
+	@$(MAKEDEPEND) -I.. $(CXXFLAGS) $(CPPFILES) $(CFILES) > makedepend
+include makedepend
+
+################################################################
+
+LIBRARY_D = ../lib/$(LIBNAME_D)
+
+debug: $(LIBRARY_D)
+
+OBJECTS_D = $(CPPFILES:.C=.do) $(CFILES:.c=.do)
+
+.SUFFIXES : .C .c .o .do
+
+.C.do :
+	@echo $<:
+	@$(CXX) -I.. $(CXXFLAGS_D) -c -o $@ $<
+.c.do :
+	@echo $<:
+	@$(CC) -I.. $(CFLAGS) -c -o $@ $<
+
+$(LIBRARY_D) : $(OBJECTS_D)
+	@echo building $(LIBRARY_D):
+	@$(AR) $(LIBRARY_D) $(OBJECTS_D)
+	@$(RANLIB) $(LIBRARY_D)
+
+################################################################
+# Linux-specific shared libraries:
+
+include ../version
+
+SHBASENAME  = libfltk.so
+SONAME      = $(SHBASENAME).$(VERSION)
+SHLIBNAME   = $(SHBASENAME).$(VERSION).$(REVISION)
+PICOBJECTS   = $(CPPFILES:.C=.pic.o) $(CFILES:.c=.pic.o)
+
+shared: ../lib/$(SHLIBNAME) ../lib/$(SONAME) ../lib/$(SHBASENAME)
+	touch ../lib/$(LIBNAME)
+
+../lib/$(SHLIBNAME): $(PICOBJECTS)
+	@echo building $@:
+	@$(CXX) -shared -Wl,-soname,$(SONAME) $(GLDLIBS) -o $@ $(PICOBJECTS)
+
+../lib/$(SONAME): ../lib/$(SHLIBNAME)
+	ln -nsf $(SHLIBNAME) $@
+
+../lib/$(SHBASENAME): ../lib/$(SHLIBNAME)
+	ln -nsf $(SHLIBNAME) $@
+
+%.pic.o: %.C
+	@echo $<:
+	@$(CXX) -fPIC -I.. $(CXXFLAGS) -c -o $@ $<
+%.pic.o: %.c
+	@echo $<:
+	@$(CC) -fPIC -I.. $(CFLAGS) -c -o $@ $<
+
+################################################################
+
+install: ../lib/$(LIBNAME)
+	cp -f ../lib/$(LIBNAME) $(libdir)
+	-cp -f ../lib/$(SHLIBNAME) $(libdir)
+	@chmod a+r,u+w,g-w,o-w $(libdir)/$(LIBNAME)*
+	cp -rf ../FL $(includedir)
+	@chmod -R a+r,u+w,g-w,o-w $(includedir)/FL
+
+# it used to do this, but it was recommended that I take it out
+#	@chown root $(libdir)/$(LIBNAME)*
+#	@chown -R root $(includedir)/FL
+
+uninstall:
+	-@ rm -f $(libdir)/libfltk*
+	-@ rm -rf $(includedir)/FL
diff --git a/src/cmap.cxx b/src/cmap.cxx
new file mode 100644
index 000000000..e98b765b5
--- /dev/null
+++ b/src/cmap.cxx
@@ -0,0 +1,120 @@
+// This program produces the contents of "fl_cmap.h" as stdout
+
+// #include 
+#include 
+
+// This table is initialized with color values I got by reading the
+// colormap on an IRIX 4.3 machine:
+
+// "full intensity colors" have been turned down some to make white
+// background less intense by default.  The hope is that this will make
+// fltk programs more friendly on color-adjusted screens.  If you want
+// pure colors you should get them out of the colormap.
+
+#define III 244 // maximum intensity of the basic colors
+
+static short cmap[256][3] = {
+// 3-bit colormap:
+  {  0,  0,  0},	// black
+  {III,  0,  0},	// red
+  {  0,III,  0},	// green
+  {III,III,  0},	// yellow
+  {  0,  0,III},	// blue
+  {III,  0,III},	// magenta
+  {  0,III,III},	// cyan
+  {III,III,III},	// white
+// pastel versions of those colors:
+  { 85, 85, 85},	// 1/3 gray
+  {198,113,113},	// salmon? pale red?
+  {113,198,113},	// pale green
+  {142,142, 56},	// khaki
+  {113,113,198},	// pale blue
+  {142, 56,142},	// purple, orchid, pale magenta
+  { 56,142,142},	// cadet blue, aquamarine, pale cyan
+  {170,170,170},	// 2/3 gray
+// These next 16 are the FL_FREE_COLOR area.  For compatability with
+// some existing DD programs, I prefill them with the random colors
+// you get on a 5.3 machine:
+  { 16, 16, 16},
+  {128, 40,128},
+  {198, 30, 30},
+  { 66, 30, 30},
+  {176,140,140},
+  {  0, 20, 20},
+  { 20, 10, 10},
+  { 40, 20, 20},
+  { 60, 30, 30},
+  {  0, 80, 80},
+  {  0, 40, 40},
+  { 20, 20,  0},
+  { 40, 40,  0},
+  { 80, 80, 10},
+  {150,150, 20},
+  {160, 10, 10},
+// The rest of the colormap is a gray ramp and table, filled in below:
+};
+
+// This is Fl::background from Fl_get_system_colors.C, with modifications:
+
+#define FL_GRAY_RAMP 32
+#define FL_NUM_GRAY  24
+#define FL_GRAY 49 // old value is 47
+typedef unsigned char uchar;
+#include 
+
+void background(uchar r, uchar g, uchar b) {
+  // replace the gray ramp so that color 47 (by default 2/3) is this color
+  if (!r) r = 1; else if (r==255) r = 254;
+  double powr = log(r/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0));
+  if (!g) g = 1; else if (g==255) g = 254;
+  double powg = log(g/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0));
+  if (!b) b = 1; else if (b==255) b = 254;
+  double powb = log(b/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0));
+  for (int i = 0; i < FL_NUM_GRAY; i++) {
+    double gray = i/(FL_NUM_GRAY-1.0);
+    cmap[i+FL_GRAY_RAMP][0] = uchar(pow(gray,powr)*255+.5);
+    cmap[i+FL_GRAY_RAMP][1] = uchar(pow(gray,powg)*255+.5);
+    cmap[i+FL_GRAY_RAMP][2] = uchar(pow(gray,powb)*255+.5);
+  }
+}
+
+int main() {
+  int i,r,g,b;
+#if 0
+  /* Read colormap colors into internal table */
+  long cmwin;
+  noport();
+  cmwin = winopen("CM");
+  for (i=0; i<256; i++)
+    getmcolor(i,&cmap[i][0],&cmap[i][1],&cmap[i][2]);
+  winclose(cmwin);
+#endif
+// overwrite the X allocation area with one color so people are
+// discouraged from using it:
+  for (i=16; i<32; i++) {cmap[i][0]=cmap[i][1]=cmap[i][2] = 85;}
+
+  // fill in the gray ramp:
+  background(0xc0, 0xc0, 0xc0); // microsoft colors
+  // background(cmap[15][0],cmap[15][1],cmap[15][2]); // old fltk colors
+  // copy the 1/3 and 2/3 gray to the closest locations in gray ramp:
+  cmap[39][0] = cmap[39][1] = cmap[39][2] = cmap[8][0];
+  cmap[47][0] = cmap[47][1] = cmap[47][2] = cmap[15][0];
+
+  // fill in the color cube
+  i = 56;
+  for (b=0; b<5; b++)
+    for (r=0; r<5; r++)
+      for (g=0; g<8; g++) {
+	cmap[i][0] = r*255/4;
+	cmap[i][1] = g*255/7;
+	cmap[i][2] = b*255/4;
+	i++;
+      }
+
+  for (i=0; i<256; i++) {
+    printf("\t0x%02x%02x%02x00",cmap[i][0],cmap[i][1],cmap[i][2]);
+    if (i < 255) printf(",\n");
+  }
+  printf("\n");
+  return 0;
+}
diff --git a/src/d1.xbm b/src/d1.xbm
new file mode 100644
index 000000000..a0e67f029
--- /dev/null
+++ b/src/d1.xbm
@@ -0,0 +1,6 @@
+#define d1_width 16
+#define d1_height 16
+static unsigned char d1_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x38, 0x00, 0x78, 0x00,
+   0xe8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x1c,
+   0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/src/d1_mask.xbm b/src/d1_mask.xbm
new file mode 100644
index 000000000..6b1e14dac
--- /dev/null
+++ b/src/d1_mask.xbm
@@ -0,0 +1,6 @@
+#define d1_mask_width 16
+#define d1_mask_height 16
+static unsigned char d1_mask_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x7c, 0x00, 0xfc, 0x00,
+   0xfc, 0x01, 0xec, 0x03, 0xc0, 0x37, 0x80, 0x3f, 0x00, 0x3f, 0x00, 0x3e,
+   0x00, 0x3f, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00};
diff --git a/src/dump_compose.c b/src/dump_compose.c
new file mode 100644
index 000000000..fe41991cf
--- /dev/null
+++ b/src/dump_compose.c
@@ -0,0 +1,26 @@
+/* write out the documentation for the compose key */
+
+/* copy the string from Fl_Input.C */
+static const char* const compose_pairs =
+"  ! @ # $ y=| & : c a <<~ - r _ * +-2 3 ' u p . , 1 o >>141234? "
+"A`A'A^A~A:A*AEC,E`E'E^E:I`I'I^I:D-N~O`O'O^O~O:x O/U`U'U^U:Y'DDss"
+"a`a'a^a~a:a*aec,e`e'e^e:i`i'i^i:d-n~o`o'o^o~o:-:o/u`u'u^u:y'ddy:";
+
+#include 
+
+int main() {
+  int x,y;
+  for (x = 0; x<16; x++) {
+    for (y = 0; y<6; y++) {
+      const char *p = compose_pairs + (16*y+x)*2;
+      if (p[1] == ' ')
+	printf("%c    %c\n",
+	       p[0],(p-compose_pairs)/2+0xA0);
+      else
+	printf("%c%c   %c\n",
+	       p[0],p[1],(p-compose_pairs)/2+0xA0);
+    }
+    printf("");
+  }
+  return 0;
+}
diff --git a/src/ew.xbm b/src/ew.xbm
new file mode 100644
index 000000000..1ff835cd5
--- /dev/null
+++ b/src/ew.xbm
@@ -0,0 +1,8 @@
+#define ew_width 16
+#define ew_height 16
+#define ew_x_hot 8
+#define ew_y_hot 8
+static unsigned char ew_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10,
+   0x0c, 0x30, 0xfe, 0x7f, 0xfe, 0x7f, 0x0c, 0x30, 0x08, 0x10, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/src/ew_mask.xbm b/src/ew_mask.xbm
new file mode 100644
index 000000000..49dc1df88
--- /dev/null
+++ b/src/ew_mask.xbm
@@ -0,0 +1,8 @@
+#define ew_mask_width 16
+#define ew_mask_height 16
+#define ew_mask_x_hot 8
+#define ew_mask_y_hot 8
+static unsigned char ew_mask_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1c, 0x38,
+   0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x1c, 0x38, 0x18, 0x18,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/src/fastarrow.h b/src/fastarrow.h
new file mode 100644
index 000000000..e381acdce
--- /dev/null
+++ b/src/fastarrow.h
@@ -0,0 +1,6 @@
+#define fastarrow_width 16
+#define fastarrow_height 16
+static unsigned char fastarrow_bits[] = {
+   0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xfc, 0x03, 0xff, 0xff, 0xfc, 0x03,
+   0xe0, 0x07, 0x00, 0x07, 0xe0, 0x00, 0xe0, 0x07, 0xc0, 0x3f, 0xff, 0xff,
+   0xc0, 0x3f, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x00};
diff --git a/src/filename_absolute.cxx b/src/filename_absolute.cxx
new file mode 100644
index 000000000..d5a937539
--- /dev/null
+++ b/src/filename_absolute.cxx
@@ -0,0 +1,67 @@
+/* expand a file name by prepending current directory, deleting . and
+   .. (not really correct for symbolic links) between the prepended
+   current directory.  Use $PWD if it exists.
+   Returns true if any changes were made.
+*/
+
+#include 
+#include 
+#include 
+#if defined(WIN32) && !defined(CYGNUS)
+# include 
+# define getcwd(a,b) _getdcwd(0,a,b)
+#else
+# include 
+# ifdef __EMX__
+#  define getcwd _getcwd2
+# endif
+#endif
+
+#if defined(WIN32) || defined(__EMX__)
+inline int isdirsep(char c) {return c=='/' || c=='\\';}
+#else
+#define isdirsep(c) ((c)=='/')
+#endif
+
+int filename_absolute(char *to,const char *from) {
+
+  if (isdirsep(*from) || *from == '|'
+#if defined(WIN32) || defined(__EMX__)
+      || from[1]==':'
+#endif
+      ) {
+    strcpy(to,from);
+    return 0;
+  }
+
+  char *a,temp[FL_PATH_MAX];
+  const char *start = from;
+
+  a = getenv("PWD");
+  if (a) strncpy(temp,a,FL_PATH_MAX);
+  else {a = getcwd(temp,FL_PATH_MAX); if (!a) return 0;}
+#if defined(WIN32) || defined(__EMX__)
+  for (a = temp; *a; a++) if (*a=='\\') *a = '/'; // ha ha
+#else
+  a = temp+strlen(temp);
+#endif
+  if (isdirsep(*(a-1))) a--;
+  /* remove intermediate . and .. names: */
+  while (*start == '.') {
+    if (start[1]=='.' && isdirsep(start[2])) {
+      char *b;
+      for (b = a-1; b >= temp && !isdirsep(*b); b--);
+      if (b < temp) break;
+      a = b;
+      start += 3;
+    } else if (isdirsep(start[1])) {
+      start += 2;
+    } else
+      break;
+  }
+  *a++ = '/';
+  strcpy(a,start);
+  strcpy(to,temp);
+  return 1;
+
+}
diff --git a/src/filename_expand.cxx b/src/filename_expand.cxx
new file mode 100644
index 000000000..27e593389
--- /dev/null
+++ b/src/filename_expand.cxx
@@ -0,0 +1,72 @@
+/* expand a file name by substuting environment variables and
+   home directories.  Returns true if any changes were made.
+   to & from may be the same buffer.
+*/
+
+#include 
+#include 
+#include 
+#ifdef WIN32
+#else
+# include 
+# include 
+#endif
+
+#if defined(WIN32) || defined(__EMX__)
+static inline int isdirsep(char c) {return c=='/' || c=='\\';}
+#else
+#define isdirsep(c) ((c)=='/')
+#endif
+
+int filename_expand(char *to,const char *from) {
+
+  char temp[FL_PATH_MAX];
+  strcpy(temp,from);
+  const char *start = temp;
+  const char *end = temp+strlen(temp);
+
+  int ret = 0;
+
+  for (char *a=temp; apw_dir;
+#endif
+      }
+      break;
+    case '$':		/* an environment variable */
+      {char t = *e; *(char *)e = 0; value = getenv(a+1); *(char *)e = t;}
+      break;
+    }
+    if (value) {
+      // substitutions that start with slash delete everything before them:
+      if (isdirsep(value[0])) start = a;
+#if defined(WIN32) || defined(__EMX__)
+      // also if it starts with "A:"
+      if (value[0] && value[1]==':') start = a;
+#endif
+      int t = strlen(value); if (isdirsep(value[t-1])) t--;
+      memmove(a+t, e, end+1-e);
+      end = a+t+(end-e);
+      memcpy(a, value, t);
+      ret++;
+    } else {
+      a = e+1;
+#if defined(WIN32) || defined(__EMX__)
+      if (*e == '\\') {*e = '/'; ret++;} // ha ha!
+#endif
+    }
+  }
+  strcpy(to,start);
+  return ret;
+}
diff --git a/src/filename_ext.cxx b/src/filename_ext.cxx
new file mode 100644
index 000000000..9fcd67096
--- /dev/null
+++ b/src/filename_ext.cxx
@@ -0,0 +1,17 @@
+// returns pointer to the last '.' or to the null if none:
+
+#include 
+
+const char *filename_ext(const char *buf) {
+  const char *q = 0;
+  const char *p = buf;
+  for (p=buf; *p; p++) {
+    if (*p == '/') q = 0;
+#if defined(WIN32) || defined(__EMX__)
+    else if (*p == '\\') q = 0;
+#endif
+    else if (*p == '.') q = p;
+  }
+  return q ? q : p;
+}
+
diff --git a/src/filename_isdir.cxx b/src/filename_isdir.cxx
new file mode 100644
index 000000000..ce02d2302
--- /dev/null
+++ b/src/filename_isdir.cxx
@@ -0,0 +1,12 @@
+// filename_isdir.C
+
+// Used by fl_file_chooser
+
+#include 
+#include 
+#include 
+
+int filename_isdir(const char* n) {
+  struct stat s;
+  return !stat(n, &s) && (s.st_mode&0170000)==0040000;
+}
diff --git a/src/filename_list.cxx b/src/filename_list.cxx
new file mode 100644
index 000000000..31fd52eea
--- /dev/null
+++ b/src/filename_list.cxx
@@ -0,0 +1,36 @@
+// filename_list.C
+
+// Wrapper for scandir with const-correct function prototypes.
+
+#include 
+#include 
+
+#if !defined(WIN32) || defined(__GNUC__)
+extern "C" {
+#endif
+  int numericsort(const dirent **, const dirent **);
+#if HAVE_SCANDIR
+#else
+  int alphasort(const dirent **, const dirent **);
+  int scandir (const char *dir, dirent ***namelist,
+	       int (*select)(const dirent *),
+	       int (*compar)(const dirent **, const dirent **));
+#endif
+#if !defined(WIN32) || defined(__GNUC__)
+}
+#endif
+
+int filename_list(const char *d, dirent ***list) {
+#if defined(_AIX) || defined(CRAY)
+  // on some systems you may need to do this, due to a rather common
+  // error in the prototype for the sorting function, where a level
+  // of pointer indirection is missing:
+  return scandir(d, list, 0, (int(*)(const void*,const void*))numericsort);
+#else
+#if HAVE_SCANDIR
+  return scandir(d, list, 0, (int(*)(dirent**,dirent**))numericsort);
+#else // built-in scandir is const-correct:
+  return scandir(d, list, 0, numericsort);
+#endif
+#endif
+}
diff --git a/src/filename_match.cxx b/src/filename_match.cxx
new file mode 100644
index 000000000..ba8ad4aad
--- /dev/null
+++ b/src/filename_match.cxx
@@ -0,0 +1,74 @@
+/*------------------- Pattern matching --------------------------*/
+/* Adapted from Rich Salz. */
+#include 
+
+int filename_match(const char *s, const char *p) {
+  int matched;
+
+  for (;;) {
+    switch(*p++) {
+
+    case '?' :	// match any single character
+      if (!*s++) return 0;
+      break;
+
+    case '*' :	// match 0-n of any characters
+      if (!*p) return 1; // do trailing * quickly
+      while (!filename_match(s, p)) if (!*s++) return 0;
+      return 1;
+
+    case '[': {	// match one character in set of form [abc-d] or [^a-b]
+      if (!*s) return 0;
+      int reverse = (*p=='^' || *p=='!'); if (reverse) p++;
+      matched = 0;
+      char last = 0;
+      while (*p) {
+	if (*p=='-' && last) {
+	  if (*s <= *++p && *s >= last ) matched = 1;
+	  last = 0;
+	} else {
+	  if (*s == *p) matched = 1;
+	}
+	last = *p++;
+	if (*p==']') break;
+      }
+      if (matched == reverse) return 0;
+      s++; p++;}
+    break;
+
+    case '{' : // {pattern1|pattern2|pattern3}
+    NEXTCASE:
+    if (filename_match(s,p)) return 1;
+    for (matched = 0;;) {
+      switch (*p++) {
+      case '\\': if (*p) p++; break;
+      case '{': matched++; break;
+      case '}': if (!matched--) return 0; break;
+      case '|': case ',': if (matched==0) goto NEXTCASE;
+      case 0: return 0;
+      }
+    }
+    case '|':	// skip rest of |pattern|pattern} when called recursively
+    case ',':
+      for (matched = 0; *p && matched >= 0;) {
+	switch (*p++) {
+	case '\\': if (*p) p++; break;
+	case '{': matched++; break;
+	case '}': matched--; break;
+	}
+      }
+      break;
+    case '}':
+      break;
+
+    case 0:	// end of pattern
+      return !*s;
+
+    case '\\':	// quote next character
+      if (*p) p++;
+    default  :	// other characters
+      if (*s++ != *(p-1)) return 0;
+      break;
+    }
+  }
+}
diff --git a/src/filename_setext.cxx b/src/filename_setext.cxx
new file mode 100644
index 000000000..2e9ca128c
--- /dev/null
+++ b/src/filename_setext.cxx
@@ -0,0 +1,12 @@
+// Replace .ext with new extension
+// If no . in name, append new extension
+// If new extension is null, act like it is ""
+
+#include 
+#include 
+
+char *filename_setext(char *buf, const char *ext) {
+  char *q = (char *)filename_ext(buf);
+  if (ext) strcpy(q,ext); else *q = 0;
+  return(buf);
+}
diff --git a/src/fl_arc.cxx b/src/fl_arc.cxx
new file mode 100644
index 000000000..756c2a4bb
--- /dev/null
+++ b/src/fl_arc.cxx
@@ -0,0 +1,50 @@
+// fl_arc.C
+
+// Utility for drawing arcs and circles.  They are added to
+// the current fl_begin/fl_vertex/fl_end path.
+// Incremental math implementation:
+
+#include 
+#include 
+
+void fl_arc(double x, double y, double r, double start, double end) {
+
+  // draw start point accurately:
+  double A = start*(M_PI/180);
+  double X = r*cos(A);
+  double Y = -r*sin(A);
+  fl_vertex(x+X,y+Y);
+
+  // number of segments per radian:
+  int n; {
+    double x1 = fl_transform_dx(r,0);
+    double y1 = fl_transform_dy(r,0);
+    double r1 = x1*x1+y1*y1;
+    x1 = fl_transform_dx(0,r);
+    y1 = fl_transform_dy(0,r);
+    double r2 = x1*x1+y1*y1;
+    if (r2 < r1) r1 = r2;
+    n = int(sqrt(r1)*.841471);
+    if (n < 2) n = 2;
+  }
+  double epsilon = 1.0/n;
+  double E = end*(M_PI/180);
+  int i = int((E-A)*n);
+  if (i < 0) {i = -i; epsilon = -epsilon;}
+  double epsilon2 = epsilon/2;
+  for (; i>1; i--) {
+    X += epsilon*Y;
+    Y -= epsilon2*X;
+    fl_vertex(x+X,y+Y);
+    Y -= epsilon2*X;
+  }
+
+  // draw the end point accurately:
+  fl_vertex(x+r*cos(E), y-r*sin(E));
+}
+
+#if 0 // portable version.  X-specific one in fl_vertex.C
+void fl_circle(double x,double y,double r) {
+  _fl_arc(x, y, r, r, 0, 360);
+}
+#endif
diff --git a/src/fl_arci.cxx b/src/fl_arci.cxx
new file mode 100644
index 000000000..1a96535c6
--- /dev/null
+++ b/src/fl_arci.cxx
@@ -0,0 +1,45 @@
+// fl_arci.C
+
+// "integer" circle drawing functions.  These draw the limited
+// circle types provided by X and NT graphics.  The advantage of
+// these is that small ones draw quite nicely (probably due to stored
+// hand-drawn bitmaps of small circles!) and may be implemented by
+// hardware and thus are fast.
+
+// Probably should add fl_chord.
+
+// 3/10/98: created
+
+#include 
+#include 
+#ifdef WIN32
+#include 
+#endif
+
+void fl_arc(int x,int y,int w,int h,double a1,double a2) {
+  if (w <= 0 || h <= 0) return;
+#ifdef WIN32
+  int xa = x+w/2+int(w*cos(a1/180.0*M_PI));
+  int ya = y+h/2-int(h*sin(a1/180.0*M_PI));
+  int xb = x+w/2+int(w*cos(a2/180.0*M_PI));
+  int yb = y+h/2-int(h*sin(a2/180.0*M_PI));
+  Arc(fl_gc, x, y, x+w, y+h, xa, ya, xb, yb); 
+#else
+  XDrawArc(fl_display, fl_window, fl_gc, x,y,w-1,h-1, int(a1*64),int((a2-a1)*64));
+#endif
+}
+
+void fl_pie(int x,int y,int w,int h,double a1,double a2) {
+  if (w <= 0 || h <= 0) return;
+#ifdef WIN32
+  if (a1 == a2) return;
+  int xa = x+w/2+int(w*cos(a1/180.0*M_PI));
+  int ya = y+h/2-int(h*sin(a1/180.0*M_PI));
+  int xb = x+w/2+int(w*cos(a2/180.0*M_PI));
+  int yb = y+h/2-int(h*sin(a2/180.0*M_PI));
+  SelectObject(fl_gc, fl_brush());
+  Pie(fl_gc, x, y, x+w, y+h, xa, ya, xb, yb); 
+#else
+  XFillArc(fl_display, fl_window, fl_gc, x,y,w,h, int(a1*64),int((a2-a1)*64));
+#endif
+}
diff --git a/src/fl_ask.cxx b/src/fl_ask.cxx
new file mode 100644
index 000000000..8d92fe482
--- /dev/null
+++ b/src/fl_ask.cxx
@@ -0,0 +1,165 @@
+// fl_ask.C
+
+// Implementation of fl_message, fl_ask, fl_choice, fl_input
+
+// The three-message fl_show_x functions are for forms compatibility
+// mostly.  In most cases it is easier to get a multi-line message
+// by putting newlines in the message.
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+static Fl_Window *message_form;
+static Fl_Box *message[3];
+static Fl_Box *icon;
+static Fl_Button *button[3];
+static Fl_Input *input;
+static char *iconlabel;
+uchar fl_message_font_ = 0;
+uchar fl_message_size_ = FL_NORMAL_SIZE;
+
+static Fl_Window *makeform() {
+ if (message_form) return message_form;
+ Fl_Window *w = message_form = new Fl_Window(410,105);
+ // w->clear_border();
+ // w->box(FL_UP_BOX);
+ (message[0] = new Fl_Box(60, 9, 340, 20))
+   ->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
+ (message[1] = new Fl_Box(60, 25, 340, 20))
+   ->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
+ (message[2] = new Fl_Box(60, 41, 340, 20))
+   ->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
+ (input = new Fl_Input(60,32,340,30))->hide();
+ {Fl_Box* o = icon = new Fl_Box(10, 10, 50, 50);
+  o->box(FL_THIN_UP_BOX);
+  o->labelfont(FL_TIMES_BOLD);
+  o->labelsize(34);
+  o->color(FL_WHITE);
+  o->labelcolor(FL_BLUE);
+ }
+ (button[0] = new Fl_Button(310, 70, 90, 25))->shortcut("^[");
+ button[1] = new Fl_Return_Button(210, 70, 90, 25);
+ button[2] = new Fl_Button(110, 70, 90, 25);
+ w->end();
+ w->set_modal();
+ return w;
+}
+
+// back-compatable functions:
+
+int fl_show_choice(
+  const char *m0,
+  const char *m1,
+  const char *m2,
+  int, // number of buttons, ignored
+  const char *b0,
+  const char *b1,
+  const char *b2)
+{
+  makeform();
+  message[0]->label(m0);
+  message[1]->label(m1);
+  message[2]->label(m2);
+  Fl_Font f = (Fl_Font)fl_message_font_;
+  if (!f) f = Fl_Input_::default_font();
+  int s = fl_message_size_ + Fl_Input::default_size();
+  for (int i=0; i<3; i++) {
+    message[i]->labelfont(f);
+    message[i]->labelsize(s);
+  }
+  if (b0) {button[0]->show();button[0]->label(b0);button[1]->position(210,70);}
+  else {button[0]->hide(); button[1]->position(310,70);}
+  if (b1) {button[1]->show(); button[1]->label(b1);}
+  else button[1]->hide();
+  if (b2) {button[2]->show(); button[2]->label(b2);}
+  else button[2]->hide();
+  const char* prev_icon_label = icon->label();
+  if (!prev_icon_label) icon->label(iconlabel);
+  message_form->hotspot(button[0]);
+  message_form->show();
+  int r;
+  for (;;) {
+    Fl_Widget *o = Fl::readqueue();
+    if (!o) Fl::wait();
+    else if (o == button[0]) {r = 0; break;}
+    else if (o == button[1]) {r = 1; break;}
+    else if (o == button[2]) {r = 2; break;}
+    else if (o == message_form) {r = 0; break;}
+  }
+  message_form->hide();
+  icon->label(prev_icon_label);
+  return r+1;
+}
+
+// pointers you can use to change fltk to a foreign language:
+const char* fl_no = "No";
+const char* fl_yes= "Yes";
+const char* fl_ok = "OK";
+const char* fl_cancel= "Cancel";
+
+// back-compatable XForms functions:
+
+void fl_show_message(const char *q1,const char *q2,const char *q3) {
+  iconlabel = "i";
+  fl_show_choice(q1, q2, q3, 1, 0, fl_ok, 0);
+}
+
+void fl_show_alert(const char *q1,const char *q2,const char *q3) {
+  iconlabel = "!";
+  fl_show_choice(q1, q2, q3, 1, 0, fl_ok, 0);
+}
+
+int fl_show_question(const char *q1,const char *q2,const char *q3) {
+  iconlabel = "?";
+  return fl_show_choice(q1, q2, q3, 2, fl_no, fl_yes, 0) - 1;
+}
+
+// fltk functions:
+
+void fl_message(const char *question) {
+  fl_show_message(0, question, 0);
+}
+
+void fl_alert(const char *question) {
+  fl_show_alert(0, question, 0);
+}
+
+int fl_ask(const char *question) {
+  return fl_show_question(0, question, 0);
+}
+
+int fl_choice(const char *q,const char *b0,const char *b1,const char *b2) {
+  iconlabel = "?";
+  return fl_show_choice(0,q,0,3,b0,b1,b2) - 1;
+}
+
+Fl_Widget *fl_message_icon() {makeform(); return icon;}
+
+const char *fl_input(const char *str1, const char *defstr, uchar type) {
+  makeform();
+  input->type(type);
+  input->show();
+  input->value(defstr);
+  iconlabel = "?";
+  int r = fl_show_choice(str1,0,0,2,fl_cancel,fl_ok,0);
+  input->hide();
+  return r==2 ? input->value() : 0;
+}
+
+const char *fl_input(const char *str1, const char *defstr) {
+  return fl_input(str1, defstr, FL_NORMAL_INPUT);
+}
+
+char *fl_show_simple_input(const char *str1, const char *defstr) {
+  const char *r = fl_input(str1, defstr, FL_NORMAL_INPUT);
+  return (char *)(r ? r : defstr);
+}
+
+// end of fl_ask.C
diff --git a/src/fl_boxtype.cxx b/src/fl_boxtype.cxx
new file mode 100644
index 000000000..8bfa7dd71
--- /dev/null
+++ b/src/fl_boxtype.cxx
@@ -0,0 +1,256 @@
+// fl_boxtype.c
+
+// Box drawing code for the common box types and the table of
+// boxtypes.  Other box types are in seperate files so they are not
+// linked in if not used.
+
+#include 
+#include 
+#include 
+#include 
+
+////////////////////////////////////////////////////////////////
+
+static uchar active_ramp[24] = {
+  FL_GRAY_RAMP+0, FL_GRAY_RAMP+1, FL_GRAY_RAMP+2, FL_GRAY_RAMP+3,
+  FL_GRAY_RAMP+4, FL_GRAY_RAMP+5, FL_GRAY_RAMP+6, FL_GRAY_RAMP+7,
+  FL_GRAY_RAMP+8, FL_GRAY_RAMP+9, FL_GRAY_RAMP+10,FL_GRAY_RAMP+11,
+  FL_GRAY_RAMP+12,FL_GRAY_RAMP+13,FL_GRAY_RAMP+14,FL_GRAY_RAMP+15,
+  FL_GRAY_RAMP+16,FL_GRAY_RAMP+17,FL_GRAY_RAMP+18,FL_GRAY_RAMP+19,
+  FL_GRAY_RAMP+20,FL_GRAY_RAMP+21,FL_GRAY_RAMP+22,FL_GRAY_RAMP+23};
+static uchar inactive_ramp[24] = {
+  43, 43, 44, 44,
+  44, 45, 45, 46,
+  46, 46, 47, 47,
+  48, 48, 48, 49,
+  49, 49, 50, 50,
+  51, 51, 52, 52};
+uchar* Fl_Gray_Ramp = (uchar*)active_ramp-'A';
+
+void fl_frame(const char* s, int x, int y, int w, int h) {
+  if (h > 0 && w > 0) for (;*s;) {
+    // draw top line:
+    fl_color(Fl_Gray_Ramp[*s++]);
+    fl_xyline(x, y, x+w-1);
+    y++; if (--h <= 0) break;
+    // draw left line:
+    fl_color(Fl_Gray_Ramp[*s++]);
+    fl_yxline(x, y+h-1, y);
+    x++; if (--w <= 0) break;
+    // draw bottom line:
+    fl_color(Fl_Gray_Ramp[*s++]);
+    fl_xyline(x, y+h-1, x+w-1);
+    if (--h <= 0) break;
+    // draw right line:
+    fl_color(Fl_Gray_Ramp[*s++]);
+    fl_yxline(x+w-1, y+h-1, y);
+    if (--w <= 0) break;
+  }
+}
+
+void fl_frame2(const char* s, int x, int y, int w, int h) {
+  if (h > 0 && w > 0) for (;*s;) {
+    // draw bottom line:
+    fl_color(Fl_Gray_Ramp[*s++]);
+    fl_xyline(x, y+h-1, x+w-1);
+    if (--h <= 0) break;
+    // draw right line:
+    fl_color(Fl_Gray_Ramp[*s++]);
+    fl_yxline(x+w-1, y+h-1, y);
+    if (--w <= 0) break;
+    // draw top line:
+    fl_color(Fl_Gray_Ramp[*s++]);
+    fl_xyline(x, y, x+w-1);
+    y++; if (--h <= 0) break;
+    // draw left line:
+    fl_color(Fl_Gray_Ramp[*s++]);
+    fl_yxline(x, y+h-1, y);
+    x++; if (--w <= 0) break;
+  }
+}
+
+void fl_no_box(int, int, int, int, Fl_Color) {}
+
+void fl_thin_down_frame(int x, int y, int w, int h, Fl_Color) {
+  fl_frame2("WWHH",x,y,w,h);
+}
+
+void fl_thin_down_box(int x, int y, int w, int h, Fl_Color c) {
+  fl_thin_down_frame(x,y,w,h,c);
+  fl_color(c); fl_rectf(x+1, y+1, w-2, h-2);
+}
+
+void fl_thin_up_frame(int x, int y, int w, int h, Fl_Color) {
+  fl_frame2("HHWW",x,y,w,h);
+}
+
+void fl_thin_up_box(int x, int y, int w, int h, Fl_Color c) {
+  fl_thin_up_frame(x,y,w,h,c);
+  fl_color(c); fl_rectf(x+1, y+1, w-2, h-2);
+}
+
+void fl_up_frame(int x, int y, int w, int h, Fl_Color) {
+#if BORDER_WIDTH == 1
+  fl_frame2("HHWW",x,y,w,h);
+#else
+#if BORDER_WIDTH == 2
+  fl_frame2("AAPPMMWU",x,y,w,h);
+#else
+  fl_frame("AAAAWUJJUSNN",x,y,w,h);
+#endif
+#endif
+}
+
+#define D1 BORDER_WIDTH
+#define D2 (BORDER_WIDTH+BORDER_WIDTH)
+
+void fl_up_box(int x, int y, int w, int h, Fl_Color c) {
+  fl_up_frame(x,y,w,h,c);
+  fl_color(c); fl_rectf(x+D1, y+D1, w-D2, h-D2);
+}
+
+void fl_down_frame(int x, int y, int w, int h, Fl_Color) {
+#if BORDER_WIDTH == 1
+  fl_frame2("WWHH",x,y,w,h);
+#else
+#if BORDER_WIDTH == 2
+  fl_frame2("UWMMPPAA",x,y,w,h);
+#else
+  fl_frame("NNSUJJUWAAAA",x,y,w,h);
+#endif
+#endif
+}
+
+void fl_down_box(int x, int y, int w, int h, Fl_Color c) {
+  fl_down_frame(x,y,w,h,c);
+  fl_color(c); fl_rectf(x+D1, y+D1, w-D2, h-D2);
+}
+
+void fl_engraved_frame(int x, int y, int w, int h, Fl_Color) {
+  fl_frame("HHWWWWHH",x,y,w,h);
+}
+
+void fl_engraved_box(int x, int y, int w, int h, Fl_Color c) {
+  fl_engraved_frame(x,y,w,h,c);
+  fl_color(c); fl_rectf(x+2, y+2, w-4, h-4);
+}
+
+void fl_embossed_frame(int x, int y, int w, int h, Fl_Color) {
+  fl_frame("WWHHHHWW",x,y,w,h);
+}
+
+void fl_embossed_box(int x, int y, int w, int h, Fl_Color c) {
+  fl_embossed_frame(x,y,w,h,c);
+  fl_color(c); fl_rectf(x+2, y+2, w-4, h-4);
+}
+
+void fl_rectbound(int x, int y, int w, int h, Fl_Color bgcolor) {
+  fl_color(FL_BLACK); fl_rect(x, y, w, h);
+  fl_color(bgcolor); fl_rectf(x+1, y+1, w-2, h-2);
+}
+#define fl_border_box fl_rectbound
+
+void fl_rectf(int x, int y, int w, int h, Fl_Color c) {
+  fl_color(c);
+  fl_rectf(x, y, w, h);
+}
+
+void fl_border_frame(int x, int y, int w, int h, Fl_Color c) {
+  fl_color(c);
+  fl_rect(x, y, w, h);
+}
+
+////////////////////////////////////////////////////////////////
+
+static struct {
+  Fl_Box_Draw_F *f;
+  uchar dx, dy, dw, dh;
+} fl_box_table[] = {
+// must match list in Enumerations.H!!!
+  {fl_no_box,		0,0,0,0},		
+  {fl_rectf,		0,0,0,0}, // FL_FLAT_BOX
+  {fl_up_box,		D1,D1,D2,D2},
+  {fl_down_box,		D1,D1,D2,D2},
+  {fl_up_frame,		D1,D1,D2,D2},
+  {fl_down_frame,	D1,D1,D2,D2},
+  {fl_thin_up_box,	1,1,2,2},
+  {fl_thin_down_box,	1,1,2,2},
+  {fl_thin_up_frame,	1,1,2,2},
+  {fl_thin_down_frame,	1,1,2,2},
+  {fl_engraved_box,	2,2,4,4},
+  {fl_embossed_box,	2,2,4,4},
+  {fl_engraved_frame,	2,2,4,4},
+  {fl_embossed_frame,	2,2,4,4},
+  {fl_border_box,	1,1,2,2},
+  {fl_border_box,	1,1,2,2}, // _FL_SHADOW_BOX,
+  {fl_border_frame,	1,1,2,2},
+  {fl_border_frame,	1,1,2,2}, // _FL_SHADOW_FRAME,
+  {fl_border_box,	1,1,2,2}, // _FL_ROUNDED_BOX,
+  {fl_border_box,	1,1,2,2}, // _FL_RSHADOW_BOX,
+  {fl_border_frame,	1,1,2,2}, // _FL_ROUNDED_FRAME
+  {fl_rectf,		0,0,0,0}, // _FL_RFLAT_BOX,
+  {fl_up_box,		3,3,6,6}, // _FL_ROUND_UP_BOX
+  {fl_down_box,		3,3,6,6}, // _FL_ROUND_DOWN_BOX,
+  {fl_up_box,		0,0,0,0}, // _FL_DIAMOND_UP_BOX
+  {fl_down_box,		0,0,0,0}, // _FL_DIAMOND_DOWN_BOX
+  {fl_border_box,	1,1,2,2}, // _FL_OVAL_BOX,
+  {fl_border_box,	1,1,2,2}, // _FL_OVAL_SHADOW_BOX,
+  {fl_border_frame,	1,1,2,2}, // _FL_OVAL_FRAME
+  {fl_rectf,		0,0,0,0}, // _FL_OVAL_FLAT_BOX,
+  {fl_up_box,		3,3,6,6}, // FL_FREE_BOX+0
+  {fl_down_box,		3,3,6,6}, // FL_FREE_BOX+1
+  {fl_up_box,		3,3,6,6}, // FL_FREE_BOX+2
+  {fl_down_box,		3,3,6,6}, // FL_FREE_BOX+3
+  {fl_up_box,		3,3,6,6}, // FL_FREE_BOX+4
+  {fl_down_box,		3,3,6,6}, // FL_FREE_BOX+5
+  {fl_up_box,		3,3,6,6}, // FL_FREE_BOX+6
+  {fl_down_box,		3,3,6,6}, // FL_FREE_BOX+7
+};
+
+int Fl::box_dx(Fl_Boxtype t) {return fl_box_table[t].dx;}
+int Fl::box_dy(Fl_Boxtype t) {return fl_box_table[t].dy;}
+int Fl::box_dw(Fl_Boxtype t) {return fl_box_table[t].dw;}
+int Fl::box_dh(Fl_Boxtype t) {return fl_box_table[t].dh;}
+
+void fl_internal_boxtype(Fl_Boxtype t, Fl_Box_Draw_F* f) {fl_box_table[t].f=f;}
+
+void Fl::set_boxtype(Fl_Boxtype t, Fl_Box_Draw_F* f,
+		      uchar a, uchar b, uchar c, uchar d) {
+  fl_box_table[t].f=f;
+  fl_box_table[t].dx = a;
+  fl_box_table[t].dy = b;
+  fl_box_table[t].dw = c;
+  fl_box_table[t].dh = d;
+}
+
+void Fl::set_boxtype(Fl_Boxtype t, Fl_Boxtype f) {
+  fl_box_table[t] = fl_box_table[f];
+}
+
+void fl_draw_box(Fl_Boxtype t, int x, int y, int w, int h, Fl_Color c) {
+  if (t) fl_box_table[t].f(x,y,w,h,c);
+}
+
+//extern Fl_Widget *fl_boxcheat; // hack set by Fl_Window.C
+
+void Fl_Widget::draw_box() const {
+  int t = box_;
+  if (!t) return;
+//   if (this == fl_boxcheat) {
+//     fl_boxcheat = 0;
+//     if (t == FL_FLAT_BOX) return;
+//     t += 2; // convert box to frame
+//   }
+  draw_box((Fl_Boxtype)t, x_, y_, w_, h_, (Fl_Color)color_);
+}
+
+void Fl_Widget::draw_box(Fl_Boxtype b, Fl_Color c) const {
+  draw_box(b, x_, y_, w_, h_, c);
+}
+
+void Fl_Widget::draw_box(Fl_Boxtype b, int x, int y, int w, int h, Fl_Color c)
+const {
+  if (!active_r()) Fl_Gray_Ramp = inactive_ramp-'A';
+  fl_box_table[b].f(x, y, w, h, c);
+  Fl_Gray_Ramp = active_ramp-'A';
+}
diff --git a/src/fl_cmap.h b/src/fl_cmap.h
new file mode 100644
index 000000000..934172440
--- /dev/null
+++ b/src/fl_cmap.h
@@ -0,0 +1,256 @@
+	0x00000000,
+	0xf4000000,
+	0x00f40000,
+	0xf4f40000,
+	0x0000f400,
+	0xf400f400,
+	0x00f4f400,
+	0xf4f4f400,
+	0x55555500,
+	0xc6717100,
+	0x71c67100,
+	0x8e8e3800,
+	0x7171c600,
+	0x8e388e00,
+	0x388e8e00,
+	0xaaaaaa00,
+	0x55555500,
+	0x55555500,
+	0x55555500,
+	0x55555500,
+	0x55555500,
+	0x55555500,
+	0x55555500,
+	0x55555500,
+	0x55555500,
+	0x55555500,
+	0x55555500,
+	0x55555500,
+	0x55555500,
+	0x55555500,
+	0x55555500,
+	0x55555500,
+	0x00000000,
+	0x0d0d0d00,
+	0x1a1a1a00,
+	0x26262600,
+	0x31313100,
+	0x3d3d3d00,
+	0x48484800,
+	0x55555500,
+	0x5f5f5f00,
+	0x6a6a6a00,
+	0x75757500,
+	0x80808000,
+	0x8a8a8a00,
+	0x95959500,
+	0xa0a0a000,
+	0xaaaaaa00,
+	0xb5b5b500,
+	0xc0c0c000,
+	0xcbcbcb00,
+	0xd5d5d500,
+	0xe0e0e000,
+	0xeaeaea00,
+	0xf5f5f500,
+	0xffffff00,
+	0x00000000,
+	0x00240000,
+	0x00480000,
+	0x006d0000,
+	0x00910000,
+	0x00b60000,
+	0x00da0000,
+	0x00ff0000,
+	0x3f000000,
+	0x3f240000,
+	0x3f480000,
+	0x3f6d0000,
+	0x3f910000,
+	0x3fb60000,
+	0x3fda0000,
+	0x3fff0000,
+	0x7f000000,
+	0x7f240000,
+	0x7f480000,
+	0x7f6d0000,
+	0x7f910000,
+	0x7fb60000,
+	0x7fda0000,
+	0x7fff0000,
+	0xbf000000,
+	0xbf240000,
+	0xbf480000,
+	0xbf6d0000,
+	0xbf910000,
+	0xbfb60000,
+	0xbfda0000,
+	0xbfff0000,
+	0xff000000,
+	0xff240000,
+	0xff480000,
+	0xff6d0000,
+	0xff910000,
+	0xffb60000,
+	0xffda0000,
+	0xffff0000,
+	0x00003f00,
+	0x00243f00,
+	0x00483f00,
+	0x006d3f00,
+	0x00913f00,
+	0x00b63f00,
+	0x00da3f00,
+	0x00ff3f00,
+	0x3f003f00,
+	0x3f243f00,
+	0x3f483f00,
+	0x3f6d3f00,
+	0x3f913f00,
+	0x3fb63f00,
+	0x3fda3f00,
+	0x3fff3f00,
+	0x7f003f00,
+	0x7f243f00,
+	0x7f483f00,
+	0x7f6d3f00,
+	0x7f913f00,
+	0x7fb63f00,
+	0x7fda3f00,
+	0x7fff3f00,
+	0xbf003f00,
+	0xbf243f00,
+	0xbf483f00,
+	0xbf6d3f00,
+	0xbf913f00,
+	0xbfb63f00,
+	0xbfda3f00,
+	0xbfff3f00,
+	0xff003f00,
+	0xff243f00,
+	0xff483f00,
+	0xff6d3f00,
+	0xff913f00,
+	0xffb63f00,
+	0xffda3f00,
+	0xffff3f00,
+	0x00007f00,
+	0x00247f00,
+	0x00487f00,
+	0x006d7f00,
+	0x00917f00,
+	0x00b67f00,
+	0x00da7f00,
+	0x00ff7f00,
+	0x3f007f00,
+	0x3f247f00,
+	0x3f487f00,
+	0x3f6d7f00,
+	0x3f917f00,
+	0x3fb67f00,
+	0x3fda7f00,
+	0x3fff7f00,
+	0x7f007f00,
+	0x7f247f00,
+	0x7f487f00,
+	0x7f6d7f00,
+	0x7f917f00,
+	0x7fb67f00,
+	0x7fda7f00,
+	0x7fff7f00,
+	0xbf007f00,
+	0xbf247f00,
+	0xbf487f00,
+	0xbf6d7f00,
+	0xbf917f00,
+	0xbfb67f00,
+	0xbfda7f00,
+	0xbfff7f00,
+	0xff007f00,
+	0xff247f00,
+	0xff487f00,
+	0xff6d7f00,
+	0xff917f00,
+	0xffb67f00,
+	0xffda7f00,
+	0xffff7f00,
+	0x0000bf00,
+	0x0024bf00,
+	0x0048bf00,
+	0x006dbf00,
+	0x0091bf00,
+	0x00b6bf00,
+	0x00dabf00,
+	0x00ffbf00,
+	0x3f00bf00,
+	0x3f24bf00,
+	0x3f48bf00,
+	0x3f6dbf00,
+	0x3f91bf00,
+	0x3fb6bf00,
+	0x3fdabf00,
+	0x3fffbf00,
+	0x7f00bf00,
+	0x7f24bf00,
+	0x7f48bf00,
+	0x7f6dbf00,
+	0x7f91bf00,
+	0x7fb6bf00,
+	0x7fdabf00,
+	0x7fffbf00,
+	0xbf00bf00,
+	0xbf24bf00,
+	0xbf48bf00,
+	0xbf6dbf00,
+	0xbf91bf00,
+	0xbfb6bf00,
+	0xbfdabf00,
+	0xbfffbf00,
+	0xff00bf00,
+	0xff24bf00,
+	0xff48bf00,
+	0xff6dbf00,
+	0xff91bf00,
+	0xffb6bf00,
+	0xffdabf00,
+	0xffffbf00,
+	0x0000ff00,
+	0x0024ff00,
+	0x0048ff00,
+	0x006dff00,
+	0x0091ff00,
+	0x00b6ff00,
+	0x00daff00,
+	0x00ffff00,
+	0x3f00ff00,
+	0x3f24ff00,
+	0x3f48ff00,
+	0x3f6dff00,
+	0x3f91ff00,
+	0x3fb6ff00,
+	0x3fdaff00,
+	0x3fffff00,
+	0x7f00ff00,
+	0x7f24ff00,
+	0x7f48ff00,
+	0x7f6dff00,
+	0x7f91ff00,
+	0x7fb6ff00,
+	0x7fdaff00,
+	0x7fffff00,
+	0xbf00ff00,
+	0xbf24ff00,
+	0xbf48ff00,
+	0xbf6dff00,
+	0xbf91ff00,
+	0xbfb6ff00,
+	0xbfdaff00,
+	0xbfffff00,
+	0xff00ff00,
+	0xff24ff00,
+	0xff48ff00,
+	0xff6dff00,
+	0xff91ff00,
+	0xffb6ff00,
+	0xffdaff00,
+	0xffffff00
diff --git a/src/fl_color.cxx b/src/fl_color.cxx
new file mode 100644
index 000000000..d17cfafc9
--- /dev/null
+++ b/src/fl_color.cxx
@@ -0,0 +1,309 @@
+// fl_color.C
+
+// Implementation of fl_color(i), fl_color(r,g,b).
+
+#ifdef WIN32
+#include "fl_color_win32.C"
+#else
+
+// Also code to look at the X visual and figure out the best way to turn
+// a color into a pixel value.
+
+// SGI compiler seems to have problems with unsigned char arguments
+// being used to index arrays.  So I always copy them to an integer
+// before use.
+
+#include "Fl_XColor.H"
+#include 
+#include 
+#include 
+
+////////////////////////////////////////////////////////////////
+// figure_out_visual() calculates masks & shifts for generating
+// pixels in true-color visuals:
+
+uchar fl_redmask, fl_greenmask, fl_bluemask;
+int fl_redshift, fl_greenshift, fl_blueshift, fl_extrashift;
+static uchar beenhere;
+
+static void figure_out_visual() {
+  beenhere = 1;
+  if (!fl_visual->red_mask || !fl_visual->green_mask || !fl_visual->blue_mask){
+#if USE_COLORMAP
+    fl_redmask = 0;
+    return;
+#else
+    Fl::fatal("Requires true color visual");
+#endif
+  }
+
+  // get the bit masks into a more useful form:
+  int i,j,m;
+
+  for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->red_mask & m) break;
+  for (j = i; m; j++, m<<=1) if (!(fl_visual->red_mask & m)) break;
+  fl_redshift = j-8;
+  fl_redmask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i));
+
+  for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->green_mask & m) break;
+  for (j = i; m; j++, m<<=1) if (!(fl_visual->green_mask & m)) break;
+  fl_greenshift = j-8;
+  fl_greenmask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i));
+
+  for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->blue_mask & m) break;
+  for (j = i; m; j++, m<<=1) if (!(fl_visual->blue_mask & m)) break;
+  fl_blueshift = j-8;
+  fl_bluemask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i));
+
+  i = fl_redshift;
+  if (fl_greenshift < i) i = fl_greenshift;
+  if (fl_blueshift < i) i = fl_blueshift;
+  if (i < 0) {
+    fl_extrashift = -i;
+    fl_redshift -= i; fl_greenshift -= i; fl_blueshift -= i;
+  } else
+    fl_extrashift = 0;
+
+}
+
+////////////////////////////////////////////////////////////////
+// Get an rgb color.  This is easy for a truecolor visual.  For
+// colormapped it picks the closest color out of the fltk colormap
+// but be warned that this results in *two* approximations: one
+// to the fltk colormap, and another to whatever colors X allocates.
+
+ulong fl_xpixel(uchar r,uchar g,uchar b) {
+  if (!beenhere) figure_out_visual();
+#if USE_COLORMAP
+  if (!fl_redmask) {
+    Fl_Color i;
+    if (r == g && r == b) { // get it out of gray ramp
+      i = fl_gray_ramp(r*FL_NUM_GRAY/256);
+    } else {		// get it out of color cube:
+      i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256);
+    }
+    return fl_xpixel(i);
+  }
+#endif
+  return
+    (((r&fl_redmask) << fl_redshift)+
+     ((g&fl_greenmask)<> fl_extrashift;
+}
+
+void fl_color(uchar r,uchar g,uchar b) {
+  XSetForeground(fl_display, fl_gc, fl_xpixel(r,g,b));
+}
+
+////////////////////////////////////////////////////////////////
+// Get a color out of the the fltk colormap.  Again for truecolor
+// visuals this is easy.  For colormap this actually tries to allocate
+// an X color, and does a least-squares match to find the closest
+// color if X cannot allocate that color.
+
+static unsigned fl_cmap[256] = {
+#include "fl_cmap.h" // this is a file produced by "cmap.C":
+};
+
+#if HAVE_OVERLAY
+Fl_XColor fl_xmap[2][256];
+uchar fl_overlay;
+Colormap fl_overlay_colormap;
+XVisualInfo* fl_overlay_visual;
+ulong fl_transparent_pixel;
+#else
+Fl_XColor fl_xmap[1][256];
+#endif
+
+// calculate what color is actually on the screen for a mask:
+static inline uchar realcolor(uchar color, uchar mask) {
+#if 1
+  // accurate version if the display has linear gamma, but fl_draw_image
+  // works better with the simpler version on most screens...
+  uchar m = mask;
+  uchar result = color&m;
+  for (;;) {
+    while (m&mask) {m>>=1; color>>=1;}
+    if (!m) break;
+    mask = m;
+    result |= color&m;
+  }
+  return result;
+#else
+  return (color&mask) | (~mask)&(mask>>1);
+#endif
+}
+
+ulong fl_xpixel(Fl_Color i) {
+
+#if HAVE_OVERLAY
+  Fl_XColor &xmap = fl_xmap[fl_overlay][i];
+#else
+  Fl_XColor &xmap = fl_xmap[0][i];
+#endif
+  if (xmap.mapped) return xmap.pixel;
+
+  if (!beenhere) figure_out_visual();
+  uchar r,g,b;
+  {unsigned c = fl_cmap[i]; r=uchar(c>>24); g=uchar(c>>16); b=uchar(c>>8);}
+
+#if USE_COLORMAP
+  Colormap colormap;
+#if HAVE_OVERLAY
+  if (fl_overlay) {colormap = fl_overlay_colormap; goto J1;}
+#endif
+  if (!fl_redmask) {
+    colormap = fl_colormap;
+#if HAVE_OVERLAY
+  J1:
+    static XColor* ac[2];
+    XColor*& allcolors = ac[fl_overlay];
+    static int nc[2];
+    int& numcolors = nc[fl_overlay];
+#else
+    static XColor *allcolors;
+    static int numcolors;
+#endif
+
+    // I don't try to allocate colors with XAllocColor once it fails
+    // with any color.  It is possible that it will work, since a color
+    // may have been freed, but some servers are extremely slow and this
+    // avoids one round trip:
+    if (!numcolors) { // don't try after a failure
+      XColor xcol;
+      xcol.red = r<<8; xcol.green = g<<8; xcol.blue = b<<8;
+      if (XAllocColor(fl_display, colormap, &xcol)) {
+	xmap.mapped = 1;
+	xmap.r = xcol.red>>8;
+	xmap.g = xcol.green>>8;
+	xmap.b = xcol.blue>>8;
+	return xmap.pixel = xcol.pixel;
+      }
+
+      // I only read the colormap once.  Again this is due to the slowness
+      // of round-trips to the X server, even though other programs may alter
+      // the colormap after this and make decisions here wrong.
+#if HAVE_OVERLAY
+      if (fl_overlay) numcolors = fl_overlay_visual->colormap_size; else
+#endif
+	numcolors = fl_visual->colormap_size;
+      if (!allcolors) allcolors = new XColor[numcolors];
+      for (int p = numcolors; p--;) allcolors[p].pixel = p;
+      XQueryColors(fl_display, colormap, allcolors, numcolors);
+    }
+
+    // find least-squares match:
+    int mindist = 0x7FFFFFFF;
+    unsigned int bestmatch = 0;
+    for (unsigned int n = numcolors; n--;) {
+#if HAVE_OVERLAY
+      if (fl_overlay && n == fl_transparent_pixel) continue;
+#endif
+      XColor &a = allcolors[n];
+      int d, t;
+      t = int(r)-int(a.red>>8); d = t*t;
+      t = int(g)-int(a.green>>8); d += t*t;
+      t = int(b)-int(a.blue>>8); d += t*t;
+      if (d <= mindist) {bestmatch = n; mindist = d;}
+    }
+    XColor &p = allcolors[bestmatch];
+
+    // It appears to "work" to not call this XAllocColor, which will
+    // avoid another round-trip to the server.  But then X does not
+    // know that this program "owns" this value, and can (and will)
+    // change it when the program that did allocate it exits:
+    if (XAllocColor(fl_display, colormap, &p)) {
+      xmap.mapped = 1;
+      xmap.pixel = p.pixel;
+    } else {
+      // However, if that XAllocColor fails, I have to give up and
+      // assumme the pixel is ok for the duration of the program.  This
+      // is due to bugs (?) in the Solaris X and some X terminals
+      // where XAllocColor *always* fails when the colormap is full,
+      // even if we ask for a color already in it...
+      xmap.mapped = 2; // 2 prevents XFreeColor from being called
+      xmap.pixel = bestmatch;
+    }
+    xmap.r = p.red>>8;
+    xmap.g = p.green>>8;
+    xmap.b = p.blue>>8;
+    return xmap.pixel;
+  }
+#endif
+  // return color for a truecolor visual:
+  xmap.mapped = 2; // 2 prevents XFreeColor from being called
+  xmap.r = realcolor(r, fl_redmask);
+  xmap.g = realcolor(g, fl_greenmask);
+  xmap.b = realcolor(b, fl_bluemask);
+  return xmap.pixel = fl_xpixel(r,g,b);
+}
+
+Fl_Color fl_color_;
+
+void fl_color(Fl_Color i) {
+  fl_color_ = i;
+  XSetForeground(fl_display, fl_gc, fl_xpixel(i));
+}
+
+////////////////////////////////////////////////////////////////
+// Ways to modify the fltk colormap:
+
+Fl_Color contrast(Fl_Color fg, Fl_Color bg) {
+  // bright/dark is decided based on high bit of green:
+  if (fl_cmap[bg] & 0x800000) {
+    if (fl_cmap[fg] & 0x800000) return FL_GRAY_RAMP; // black from gray ramp
+  } else {
+    if (!(fl_cmap[fg] & 0x800000))
+      return (Fl_Color)(FL_COLOR_CUBE-1); // white from gray ramp
+  }
+  return fg; // this color is ok
+}
+
+void Fl::free_color(Fl_Color i, int overlay) {
+#if HAVE_OVERLAY
+#else
+  if (overlay) return;
+#endif
+  if (fl_xmap[overlay][i].mapped) {
+#if USE_COLORMAP
+#if HAVE_OVERLAY
+    Colormap colormap = overlay ? fl_overlay_colormap : fl_colormap;
+#else
+    Colormap colormap = fl_colormap;
+#endif
+    if (fl_xmap[overlay][i].mapped == 1)
+      XFreeColors(fl_display, colormap, &(fl_xmap[overlay][i].pixel), 1, 0);
+#endif
+    fl_xmap[overlay][i].mapped = 0;
+  }
+}
+
+void Fl::set_color(Fl_Color i, unsigned c) {
+  if (fl_cmap[i] != c) {
+    free_color(i,0);
+#if HAVE_OVERLAY
+    free_color(i,1);
+#endif
+    fl_cmap[i] = c;
+  }
+}
+
+unsigned Fl::get_color(Fl_Color i) {
+  return fl_cmap[i];
+}
+
+void Fl::set_color(Fl_Color i, uchar red, uchar green, uchar blue) {
+  Fl::set_color(i,
+	((unsigned)red<<24)+((unsigned)green<<16)+((unsigned)blue<<8));
+}
+
+void Fl::get_color(Fl_Color i, uchar &red, uchar &green, uchar &blue) {
+  unsigned c = fl_cmap[i];
+  red   = uchar(c>>24);
+  green = uchar(c>>16);
+  blue  = uchar(c>>8);
+}
+
+#endif
+// end of fl_color.C
diff --git a/src/fl_color_win32.cxx b/src/fl_color_win32.cxx
new file mode 100644
index 000000000..360bc1b96
--- /dev/null
+++ b/src/fl_color_win32.cxx
@@ -0,0 +1,204 @@
+// fl_color_win32.C
+
+// The fltk "colormap".  This allows ui colors to be stored in 8-bit
+// locations, and provides a level of indirection so that global color
+// changes can be made.  Not to be confused with the X colormap, which
+// I try to hide completely.
+
+// SGI compiler seems to have problems with unsigned char arguments
+// being used to index arrays.  So I always copy them to an integer
+// before use.
+
+#include 
+#include 
+#include 
+#include 
+
+static unsigned fl_cmap[256] = {
+#include "fl_cmap.h" // this is a file produced by "cmap.C":
+};
+
+// Translations to win32 data structures:
+Fl_XMap fl_xmap[256];
+
+Fl_XMap* fl_current_xmap;
+
+HPALETTE fl_palette;
+
+static void clear_xmap(Fl_XMap& xmap) {
+  if (xmap.pen) {
+    DeleteObject((HGDIOBJ)(xmap.pen));
+    xmap.pen = 0;
+    xmap.brush = -1;
+  }
+}
+
+static void set_xmap(Fl_XMap& xmap, COLORREF c) {
+  xmap.rgb = c;
+  xmap.pen = CreatePen(PS_SOLID, 1, xmap.rgb);
+  xmap.brush = -1;
+}
+
+Fl_Color fl_color_;
+
+void fl_color(Fl_Color i) {
+  fl_color_ = i;
+  Fl_XMap &xmap = fl_xmap[i];
+  if (!xmap.pen) {
+#if USE_COLORMAP
+    if (fl_palette) {
+      set_xmap(xmap, PALETTEINDEX(i));
+    } else {
+#endif
+      unsigned c = fl_cmap[i];
+      set_xmap(xmap, RGB(uchar(c>>24), uchar(c>>16), uchar(c>>8)));
+#if USE_COLORMAP
+    }
+#endif
+  }
+  fl_current_xmap = ⟼
+  SelectObject(fl_gc, (HGDIOBJ)(xmap.pen));
+}
+
+void fl_color(uchar r, uchar g, uchar b) {
+  static Fl_XMap xmap;
+  COLORREF c = RGB(r,g,b);
+  if (!xmap.pen || c != xmap.rgb) {
+    clear_xmap(xmap);
+    set_xmap(xmap, c);
+  }
+  fl_current_xmap = ⟼
+  SelectObject(fl_gc, (HGDIOBJ)(xmap.pen));
+}
+
+HBRUSH fl_brush() {
+  Fl_XMap *xmap = fl_current_xmap;
+  // Wonko: we use some statistics to cache only a limited number
+  // of brushes:
+#define FL_N_BRUSH 16
+  static struct Fl_Brush {
+    HBRUSH brush;
+    unsigned short usage;
+    Fl_XMap* backref;
+  } brushes[FL_N_BRUSH];
+
+  int i = xmap->brush; // find the associated brush
+  if (i != -1) { // if the brush was allready allocated
+    if (brushes[i].brush == NULL) goto CREATE_BRUSH;
+    if ( (++brushes[i].usage) > 32000 ) { // keep a usage statistic
+      for (int j=0; j16000)
+	  brushes[j].usage -= 16000;
+	else 
+	  brushes[j].usage = 0;
+      }
+    }
+    return brushes[i].brush;
+  } else {
+    int umin = 32000, imin = 0;
+    for (i=0; ibrush = -1;
+  }
+CREATE_BRUSH:
+  brushes[i].brush = CreateSolidBrush(xmap->rgb);
+  brushes[i].usage = 0;
+  brushes[i].backref = xmap;
+  xmap->brush = i;
+  return brushes[i].brush;
+}
+
+Fl_Color contrast(Fl_Color fg, Fl_Color bg) {
+  // bright/dark is decided based on high bit of green:
+  if (fl_cmap[bg] & 0x800000) {
+    if (fl_cmap[fg] & 0x800000) return FL_GRAY_RAMP; // black from gray ramp
+  } else {
+    if (!(fl_cmap[fg] & 0x800000))
+      return (Fl_Color)(FL_COLOR_CUBE-1); // white from gray ramp
+  }
+  return fg; // this color is ok
+}
+
+void Fl::free_color(Fl_Color i, int overlay) {
+  if (overlay) return; // do something about GL overlay?
+  clear_xmap(fl_xmap[i]);
+}
+
+void Fl::set_color(Fl_Color i, unsigned c) {
+  if (fl_cmap[i] != c) {
+    clear_xmap(fl_xmap[i]);
+    fl_cmap[i] = c;
+  }
+}
+
+unsigned Fl::get_color(Fl_Color i) {
+  return fl_cmap[i];
+}
+
+void Fl::set_color(Fl_Color i, uchar red, uchar green, uchar blue) {
+  Fl::set_color(i,
+	((unsigned)red<<24)+((unsigned)green<<16)+((unsigned)blue<<8));
+}
+
+void Fl::get_color(Fl_Color i, uchar &red, uchar &green, uchar &blue) {
+  unsigned c = fl_cmap[i];
+  red   = uchar(c>>24);
+  green = uchar(c>>16);
+  blue  = uchar(c>>8);
+}
+
+#if USE_COLORMAP
+
+// 'fl_select_palette()' - Make a color palette for 8-bit displays if necessary
+// Thanks to Michael Sweet @ Easy Software Products for this
+
+HPALETTE
+fl_select_palette(void)
+{
+  static char beenhere;
+  if (!beenhere) {
+    beenhere = 1;
+
+    //if (GetDeviceCaps(fl_gc, BITSPIXEL) > 8) return NULL;
+    int nColors = GetDeviceCaps(fl_gc, SIZEPALETTE);
+    if (nColors <= 0 || nColors > 256) return NULL;
+    // this will try to work on < 256 color screens, but will probably
+    // come out quite badly.
+
+    // I lamely try to get this variable-sized object allocated on stack:
+    ulong foo[(sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY))/sizeof(ulong)+1];
+    LOGPALETTE *pPal = (LOGPALETTE*)foo;
+
+    pPal->palVersion    = 0x300;
+    pPal->palNumEntries = nColors;
+
+    // Build 256 colors from the standard FLTK colormap...
+
+    for (int i = 0; i < nColors; i ++) {
+      pPal->palPalEntry[i].peRed   = (fl_cmap[i] >> 24) & 255;
+      pPal->palPalEntry[i].peGreen = (fl_cmap[i] >> 16) & 255;
+      pPal->palPalEntry[i].peBlue  = (fl_cmap[i] >>  8) & 255;
+      pPal->palPalEntry[i].peFlags = 0;
+    };
+
+    // Create the palette:
+    fl_palette = CreatePalette(pPal);
+  }
+  if (fl_palette) {
+    SelectPalette(fl_gc, fl_palette, FALSE);
+    RealizePalette(fl_gc);
+  }
+  return fl_palette;
+}
+
+#endif
+
+// end of fl_color_win32.C
diff --git a/src/fl_cursor.cxx b/src/fl_cursor.cxx
new file mode 100644
index 000000000..e058c3f7c
--- /dev/null
+++ b/src/fl_cursor.cxx
@@ -0,0 +1,145 @@
+// fl_cursor.C
+
+// Change the current cursor.
+
+// Under X the cursor is attached to the X window.  I tried to hide
+// this and pretend that changing the cursor is a drawing function.
+// This avoids a field in the Fl_Window, and I suspect is more
+// portable to other systems.
+
+#include 
+#include 
+#include 
+#ifndef WIN32
+#include 
+#endif
+#include 
+
+void fl_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) {
+  if (Fl::first_window()) Fl::first_window()->cursor(c,fg,bg);
+}
+
+#ifdef WIN32
+
+void Fl_Window::cursor(Fl_Cursor c, Fl_Color, Fl_Color) {
+  if (!shown()) return;
+  if (c > FL_CURSOR_NESW) {
+    i->cursor = 0;
+  } else if (c == FL_CURSOR_DEFAULT) {
+    i->cursor = fl_default_cursor;
+  } else {
+    LPSTR n;
+    switch (c) {
+    case FL_CURSOR_ARROW:	n = IDC_ARROW; break;
+    case FL_CURSOR_CROSS:	n = IDC_CROSS; break;
+    case FL_CURSOR_WAIT:	n = IDC_WAIT; break;
+    case FL_CURSOR_INSERT:	n = IDC_IBEAM; break;
+    case FL_CURSOR_HELP:	n = IDC_HELP; break;
+    case FL_CURSOR_HAND:	n = IDC_UPARROW; break;
+    case FL_CURSOR_MOVE:	n = IDC_SIZEALL; break;
+    case FL_CURSOR_N:
+    case FL_CURSOR_S:
+    case FL_CURSOR_NS:		n = IDC_SIZENS; break;
+    case FL_CURSOR_NE:
+    case FL_CURSOR_SW:
+    case FL_CURSOR_NESW:	n = IDC_SIZENESW; break;
+    case FL_CURSOR_E:
+    case FL_CURSOR_W:
+    case FL_CURSOR_WE:		n = IDC_SIZEWE; break;
+    case FL_CURSOR_SE:
+    case FL_CURSOR_NW:
+    case FL_CURSOR_NWSE:	n = IDC_SIZENWSE; break;
+    default:			n = IDC_NO; break;
+    }
+    i->cursor = LoadCursor(NULL, n);
+  }
+  SetCursor(i->cursor);
+}
+
+#else
+
+// I like the MSWindows resize cursors, so I duplicate them here:
+
+#define CURSORSIZE 16
+#define HOTXY 7
+struct TableEntry {
+  uchar bits[CURSORSIZE*CURSORSIZE/8];
+  uchar mask[CURSORSIZE*CURSORSIZE/8];
+  Cursor cursor;
+} table[] = {
+  {{	// FL_CURSOR_NS
+   0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0x80, 0x01, 0x80, 0x01,
+   0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
+   0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00},
+   {
+   0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xc0, 0x03,
+   0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xf0, 0x0f,
+   0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01}},
+  {{	// FL_CURSOR_EW
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10,
+   0x0c, 0x30, 0xfe, 0x7f, 0xfe, 0x7f, 0x0c, 0x30, 0x08, 0x10, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+   {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1c, 0x38,
+   0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x1c, 0x38, 0x18, 0x18,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+  {{	// FL_CURSOR_NWSE
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x38, 0x00, 0x78, 0x00,
+   0xe8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x1c,
+   0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+   {
+   0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x7c, 0x00, 0xfc, 0x00,
+   0xfc, 0x01, 0xec, 0x03, 0xc0, 0x37, 0x80, 0x3f, 0x00, 0x3f, 0x00, 0x3e,
+   0x00, 0x3f, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00}},
+  {{	// FL_CURSOR_NESW
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1c, 0x00, 0x1e,
+   0x00, 0x17, 0x80, 0x03, 0xc0, 0x01, 0xe8, 0x00, 0x78, 0x00, 0x38, 0x00,
+   0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+   {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3f,
+   0x80, 0x3f, 0xc0, 0x37, 0xec, 0x03, 0xfc, 0x01, 0xfc, 0x00, 0x7c, 0x00,
+   0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00}},
+  {{0}, {0}} // FL_CURSOR_NONE & unknown
+};
+
+void Fl_Window::cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) {
+  if (!shown()) return;
+  Cursor cursor;
+  int deleteit = 0;
+  if (!c) {
+    cursor = None;
+  } else {
+    if (c >= FL_CURSOR_NS) {
+      TableEntry *q = (c > FL_CURSOR_NESW) ? table+4 : table+(c-FL_CURSOR_NS);
+      if (!(q->cursor)) {
+	XColor dummy;
+	Pixmap p = XCreateBitmapFromData(fl_display,
+	  RootWindow(fl_display, fl_screen), (const char*)(q->bits),
+	  CURSORSIZE, CURSORSIZE);
+	Pixmap m = XCreateBitmapFromData(fl_display,
+	  RootWindow(fl_display, fl_screen), (const char*)(q->mask),
+	  CURSORSIZE, CURSORSIZE);
+	q->cursor = XCreatePixmapCursor(fl_display, p,m,&dummy, &dummy,
+					HOTXY, HOTXY);
+	XFreePixmap(fl_display, m);
+	XFreePixmap(fl_display, p);
+      }
+      cursor = q->cursor;
+    } else {
+      cursor = XCreateFontCursor(fl_display, (c-1)*2);
+      deleteit = 1;
+    }
+    XColor fgc;
+    uchar r,g,b;
+    Fl::get_color(fg,r,g,b);
+    fgc.red = r<<8; fgc.green = g<<8; fgc.blue = b<<8;
+    XColor bgc;
+    Fl::get_color(bg,r,g,b);
+    bgc.red = r<<8; bgc.green = g<<8; bgc.blue = b<<8;
+    XRecolorCursor(fl_display, cursor, &fgc, &bgc);
+  }
+  XDefineCursor(fl_display, fl_xid(this), cursor);
+  if (deleteit) XFreeCursor(fl_display, cursor);
+}
+
+#endif
diff --git a/src/fl_curve.cxx b/src/fl_curve.cxx
new file mode 100644
index 000000000..0fc125e89
--- /dev/null
+++ b/src/fl_curve.cxx
@@ -0,0 +1,73 @@
+// fl_curve.C
+
+// Utility for drawing Bezier curves, adding the points to
+// the current fl_begin/fl_vertex/fl_end path.
+
+// Incremental math implementation:
+// I very much doubt this is optimal!  From Foley/vanDam page 511.
+// If anybody has a better algorithim, please send it!
+
+#include 
+#include 
+
+void fl_curve(double X0, double Y0,
+	      double X1, double Y1,
+	      double X2, double Y2,
+	      double X3, double Y3) {
+  double x = fl_transform_x(X0,Y0);
+  double y = fl_transform_y(X0,Y0);
+  double x1 = fl_transform_x(X1,Y1);
+  double y1 = fl_transform_y(X1,Y1);
+  double x2 = fl_transform_x(X2,Y2);
+  double y2 = fl_transform_y(X2,Y2);
+  double x3 = fl_transform_x(X3,Y3);
+  double y3 = fl_transform_y(X3,Y3);
+
+  int n; { // find smaller size of bounding box
+    double lx = x; if (x1rx) rx=x1; if (x2>rx) rx=x2; if (x3>rx) rx=x3;
+    double ly = y; if (y1ry) ry=y1; if (y2>ry) ry=y2; if (y3>ry) ry=y3;
+    // calculate number of pieces to cut curve into:
+    n = int((rx-lx+ry-ly)/8); if (n < 3) n = 3;
+  }
+  double e = 1.0/n;
+
+  // calculate the coefficients of 3rd order equation:
+  double xa = (x3-3*x2+3*x1-x);
+  double xb = 3*(x2-2*x1+x);
+  double xc = 3*(x1-x);
+  // calculate the forward differences:
+  double dx1 = ((xa*e+xb)*e+xc)*e;
+  double dx3 = 6*xa*e*e*e;
+  double dx2 = dx3 + 2*xb*e*e;
+
+  // calculate the coefficients of 3rd order equation:
+  double ya = (y3-3*y2+3*y1-y);
+  double yb = 3*(y2-2*y1+y);
+  double yc = 3*(y1-y);
+  // calculate the forward differences:
+  double dy1 = ((ya*e+yb)*e+yc)*e;
+  double dy3 = 6*ya*e*e*e;
+  double dy2 = dy3 + 2*yb*e*e;
+
+  // draw point 0:
+  fl_transformed_vertex(x,y);
+
+  // draw points 1 .. n-2:
+  for (int m=2; m
+#include 
+
+extern uchar* Fl_Gray_Ramp;
+
+static void fl_diamond_up_box(int x,int y,int w,int h,Fl_Color bgcolor) {
+  w &= -2;
+  h &= -2;
+  int x1 = x+w/2;
+  int y1 = y+h/2;
+  fl_color(bgcolor); fl_polygon(x+3, y1, x1,y+3, x+w-3,y1, x1,y+h-3);
+  fl_color(Fl_Gray_Ramp['W']); fl_line(x+1, y1, x1, y+1, x+w-1, y1);
+  fl_color(Fl_Gray_Ramp['U']); fl_line(x+2, y1, x1, y+2, x+w-2, y1);
+  fl_color(Fl_Gray_Ramp['S']); fl_line(x+3, y1, x1, y+3, x+w-3, y1);
+  fl_color(Fl_Gray_Ramp['P']); fl_line(x+3, y1, x1, y+h-3, x+w-3, y1);
+  fl_color(Fl_Gray_Ramp['N']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1);
+  fl_color(Fl_Gray_Ramp['H']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1);
+  fl_color(Fl_Gray_Ramp['A']); fl_loop(x, y1, x1, y, x+w, y1, x1, y+h);
+}
+
+static void fl_diamond_down_box(int x,int y,int w,int h,Fl_Color bgcolor) {
+  w &= -2;
+  h &= -2;
+  int x1 = x+w/2;
+  int y1 = y+h/2;
+  fl_color(Fl_Gray_Ramp['P']); fl_line(x+0, y1, x1, y+0, x+w-0, y1);
+  fl_color(Fl_Gray_Ramp['N']); fl_line(x+1, y1, x1, y+1, x+w-1, y1);
+  fl_color(Fl_Gray_Ramp['H']); fl_line(x+2, y1, x1, y+2, x+w-2, y1);
+  fl_color(Fl_Gray_Ramp['W']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1);
+  fl_color(Fl_Gray_Ramp['U']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1);
+  fl_color(Fl_Gray_Ramp['S']); fl_line(x+0, y1, x1, y+h-0, x+w-0, y1);
+  fl_color(bgcolor); fl_polygon(x+3, y1, x1,y+3, x+w-3,y1, x1,y+h-3);
+  fl_color(Fl_Gray_Ramp['A']); fl_loop(x+3, y1, x1, y+3, x+w-3, y1, x1, y+h-3);
+}
+
+extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*);
+Fl_Boxtype define_FL_DIAMOND_BOX() {
+  fl_internal_boxtype(_FL_DIAMOND_DOWN_BOX, fl_diamond_down_box);
+  fl_internal_boxtype(_FL_DIAMOND_UP_BOX,fl_diamond_up_box);
+  return _FL_DIAMOND_UP_BOX;
+}
diff --git a/src/fl_draw.cxx b/src/fl_draw.cxx
new file mode 100644
index 000000000..eda4bff29
--- /dev/null
+++ b/src/fl_draw.cxx
@@ -0,0 +1,175 @@
+// fl_draw.C
+
+// Implementation of fl_draw(const char*,int,int,int,int,Fl_Align)
+
+// Used to draw all the labels and text, this routine:
+
+// Word wraps the labels to fit into their bounding box.
+// Breaks them into lines at the newlines.
+// Expands all unprintable characters to ^X or \nnn notation
+// Aligns them against the inside of the box.
+
+#include 
+#include 
+
+#define MAXBUF 1024
+
+char fl_draw_shortcut;	// set by fl_labeltypes.C
+static char* underline_at;
+
+// Copy p to buf, replacing unprintable characters with ^X and \nnn
+// Stop at a newline of if MAXBUF characters written to buffer.
+// Also word-wrap if width exceeds maxw.
+// Returns a pointer to the start of the next line of caharcters.
+// Sets n to the number of characters put into the buffer.
+// Sets width to the width of the string in the current font.
+
+static const char*
+expand(const char* from, char* buf, double maxw, int& n, double &width, int wrap) {
+
+  char* o = buf;
+  char* e = buf+(MAXBUF-4);
+  underline_at = 0;
+  char* word_end = o;
+  const char* word_start = from;
+  double w = 0;
+
+  const char* p = from;
+  for (;; p++) {
+
+    int c = *p & 255;
+
+    if (!c || c == ' ' || c == '\n') {
+      // test for word-wrap:
+      if (word_start < p && wrap) {
+	double newwidth = w + fl_width(word_end, o-word_end);
+	if (word_end > buf && newwidth > maxw) { // break before this word
+	  o = word_end;
+	  p = word_start;
+	  break;
+	}
+	word_end = o;
+	w = newwidth;
+      }
+      if (!c) break;
+      else if (c == '\n') {p++; break;}
+      word_start = p+1;
+    }
+
+    if (o > e) break; // don't overflow buffer
+
+    if (c == '\t') {
+      for (c = (o-buf)%8; c<8 && o= 128 && c < 0xA0) { // \nnn
+      *o++ = '\\';
+      *o++ = (c>>6)+'0';
+      *o++ = ((c>>3)&7)+'0';
+      *o++ = (c&7)+'0';
+
+    } else if (c == 0xA0) { // non-breaking space
+      *o++ = ' ';
+
+    } else {
+      *o++ = c;
+
+    }
+  }
+
+  width = w + fl_width(word_end, o-word_end);
+  *o = 0;
+  n = o-buf;
+  return p;
+}
+
+void fl_draw(
+    const char* str,	// the (multi-line) string
+    int x, int y, int w, int h,	// bounding box
+    Fl_Align align,
+    void (*callthis)(const char*,int,int,int)
+) {
+  if (!str || !*str) return;
+
+  // clip:
+  if (w && h && !fl_not_clipped(x, y, w, h)) return;
+  if (align & FL_ALIGN_CLIP) fl_clip(x, y, w, h);
+
+  const char* p;
+  const char* e;
+  char buf[MAXBUF];
+  int buflen;
+
+  // count how many lines and put the last one into the buffer:
+  int lines;
+  double width;
+  for (p=str,lines=0; ;) {
+    e = expand(p, buf, w, buflen, width, align&FL_ALIGN_WRAP);
+    lines++;
+    if (!*e) break;
+    p = e;
+  }
+
+  // figure out vertical position of the first line:
+  int ypos;
+  int height = fl_height();
+  if (align & FL_ALIGN_BOTTOM) ypos = y+h-(lines-1)*height;
+  else if (align & FL_ALIGN_TOP) ypos = y+height;
+  else ypos = y+(h-lines*height)/2+height;
+
+  // now draw all the lines:
+  int desc = fl_descent();
+  for (p=str; ; ypos += height) {
+    if (lines>1) e = expand(p, buf, w, buflen, width, align&FL_ALIGN_WRAP);
+
+    int xpos;
+    if (align & FL_ALIGN_LEFT) xpos = x;
+    else if (align & FL_ALIGN_RIGHT) xpos = x+w-int(width+.5);
+    else xpos = x+int((w-width)/2);
+
+    callthis(buf,buflen,xpos,ypos-desc);
+
+    if (underline_at)
+      callthis("_",1,xpos+int(fl_width(buf,underline_at-buf)),ypos-desc);
+
+    if (!*e) break;
+    p = e;
+  }
+
+  if (align & FL_ALIGN_CLIP) fl_pop_clip();
+}
+
+void fl_draw(
+  const char* str,	// the (multi-line) string
+  int x, int y, int w, int h,	// bounding box
+  Fl_Align align) {
+  fl_draw(str, x, y, w, h, align, fl_draw);
+}
+
+void fl_measure(const char* str, int& w, int& h) {
+  h = fl_height();
+  if (!str || !*str) {w = 0; return;}
+  const char* p;
+  const char* e;
+  char buf[MAXBUF];
+  int buflen;
+  int lines;
+  double width;
+  int W = 0;
+  for (p=str,lines=0; ;) {
+    e = expand(p, buf, w, buflen, width, w!=0);
+    if (int(width) > W) W = int(width);
+    lines++;
+    if (!*e) break;
+    p = e;
+  }
+  w = W;
+  h = lines*h;
+}
diff --git a/src/fl_draw_image.cxx b/src/fl_draw_image.cxx
new file mode 100644
index 000000000..e66384c56
--- /dev/null
+++ b/src/fl_draw_image.cxx
@@ -0,0 +1,605 @@
+// fl_draw_image.C
+
+// I hope a simple and portable method of drawing color and monochrome
+// images.  To keep this simple, only a single storage type is
+// supported: 8 bit unsigned data, byte order RGB, and pixels are
+// stored packed into rows with the origin at the top-left.  It is
+// possible to alter the size of pixels with the "delta" argument, to
+// add alpha or other information per pixel.  It is also possible to
+// change the origin and direction of the image data by messing with
+// the "delta" and "linedelta", making them negative, though this may
+// defeat some of the shortcuts in translating the image for X.
+
+#ifdef WIN32
+#include "fl_draw_image_win32.C"
+#else
+
+// A list of assumptions made about the X display:
+
+// bits_per_pixel must be one of 8, 16, 24, 32.
+
+// scanline_pad must be a power of 2 and greater or equal to 8.
+
+// PsuedoColor visuals must have 8 bits_per_pixel (although the depth
+// may be less than 8).  This is the only limitation that affects any
+// modern X displays, you can't use 12 or 16 bit colormaps.
+
+// The mask bits in TrueColor visuals for each color are
+// contiguous and have at least one bit of each color.  This
+// is not checked for.
+
+// For 24 and 32 bit visuals there must be at least 8 bits of each color.
+
+////////////////////////////////////////////////////////////////
+
+#include 
+#include 
+#include 
+#include "Fl_XColor.H"
+
+static XImage i;	// template used to pass info to X
+static int bytes_per_pixel;
+static int scanline_add;
+static int scanline_mask;
+
+static void (*converter)(const uchar *from, uchar *to, int w, int delta);
+static void (*mono_converter)(const uchar *from, uchar *to, int w, int delta);
+
+static int dir;		// direction-alternator
+static int ri,gi,bi;	// saved error-diffusion value
+
+#if USE_COLORMAP
+////////////////////////////////////////////////////////////////
+// 8-bit converter with error diffusion
+
+// I make a 16x16x16 cube of the closest colors in the fltk colormap
+// we could allocate to each of the colors in a 4-bit image.  This is
+// then used to find the pixel values and actual colors for error diffusion.
+static uchar cube[16*16*16];
+
+// calculate sum-of-squares error between 4-bit index and pixel colors:
+static int calc_error(int r, int g, int b, int i) {
+  int t; int s;
+  t = ((r<<4)+8)-fl_xmap[0][i].r; s = t*t;
+  t = ((g<<4)+8)-fl_xmap[0][i].g; s += t*t;
+  t = ((b<<4)+8)-fl_xmap[0][i].b; s += t*t;
+  return s;
+}
+
+// replace the color stored at a location with a better one:
+static void improve(uchar *p, int& e, int r, int g, int b, int i) {
+  if (i < FL_GRAY_RAMP || i > 255) return;
+  int e1 = calc_error(r,g,b,i);
+  if (e1 < e) {*p = i; e = e1;}
+}
+
+static int filled_color_cube;
+static void fill_color_cube() {
+  filled_color_cube = 1;
+  int i;
+  // allocate all the colors in the fltk color cube and gray ramp:
+  // allocate widely seperated values first so that the bad ones are
+  // distributed evenly through the colormap:
+  for (i=0;;) {
+    fl_xpixel((Fl_Color)(i+FL_COLOR_CUBE));
+    i = (i+109)%(FL_NUM_RED*FL_NUM_GREEN*FL_NUM_BLUE); if (!i) break;
+  }
+  for (i=0;;) {
+    fl_xpixel((Fl_Color)(i+FL_GRAY_RAMP));
+    i = (i+7)%FL_NUM_GRAY; if (!i) break;
+  }
+  // fill in the 16x16x16 cube:
+  uchar *p = cube;
+  for (int r = 0; r<16; r++) {
+    for (int g = 0; g<16; g++) {
+      for (int b = 0; b<16; b++, p++) {
+	// initial try is value from color cube:
+	Fl_Color i = fl_color_cube(r*FL_NUM_RED/16, g*FL_NUM_GREEN/16,
+				   b*FL_NUM_BLUE/16);
+	int e = calc_error(r,g,b,i);
+	*p = uchar(i);
+	// try neighbor pixels in the cube to see if they are better:
+	improve(p,e,r,g,b,i+FL_NUM_RED*FL_NUM_GREEN);
+	improve(p,e,r,g,b,i-FL_NUM_RED*FL_NUM_GREEN);
+	improve(p,e,r,g,b,i+FL_NUM_GREEN);
+	improve(p,e,r,g,b,i-FL_NUM_GREEN);
+	improve(p,e,r,g,b,i+1);
+	improve(p,e,r,g,b,i-1);
+	// try the gray ramp:
+	i = fl_gray_ramp(g*FL_NUM_GRAY/15);
+	improve(p,e,r,g,b,i);
+	improve(p,e,r,g,b,i+1);
+	improve(p,e,r,g,b,i-1);
+      }
+    }
+  }
+}
+
+static void color8_converter(const uchar *from, uchar *to, int w, int delta) {
+  if (!filled_color_cube) fill_color_cube();
+  int r=ri, g=gi, b=bi;
+  int d, td;
+  if (dir) {
+    dir = 0;
+    from = from+(w-1)*delta;
+    to = to+(w-1);
+    d = -delta;
+    td = -1;
+  } else {
+    dir = 1;
+    d = delta;
+    td = 1;
+  }
+  for (; w--; from += d, to += td) {
+    r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255;
+    g += from[1]; if (g < 0) g = 0; else if (g>255) g = 255;
+    b += from[2]; if (b < 0) b = 0; else if (b>255) b = 255;
+    Fl_XColor* x = fl_xmap[0] + cube[((r<<4)&0xf00)+(g&0xf0)+(b>>4)];
+    r -= x->r;
+    g -= x->g;
+    b -= x->b;
+    *to = uchar(x->pixel);
+  }
+  ri = r; gi = g; bi = b;
+}
+
+static void mono8_converter(const uchar *from, uchar *to, int w, int delta) {
+  if (!filled_color_cube) fill_color_cube();
+  int r=ri;
+  int d, td;
+  if (dir) {
+    dir = 0;
+    from = from+(w-1)*delta;
+    to = to+(w-1);
+    d = -delta;
+    td = -1;
+  } else {
+    dir = 1;
+    d = delta;
+    td = 1;
+  }
+  for (; w--; from += d, to += td) {
+    r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255;
+    Fl_XColor* x = fl_xmap[0] + cube[(r>>4)*0x111];
+    r -= x->g;
+    *to = uchar(x->pixel);
+  }
+  ri = r;
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////
+// 16 bit TrueColor converters with error diffusion
+// Cray computers have no 16-bit type, so we use character pointers
+// (which may be slow)
+
+#ifdef U16
+#define OUTTYPE U16
+#define OUTSIZE 1
+#define OUTASSIGN(v) *t = v
+#else
+#define OUTTYPE uchar
+#define OUTSIZE 2
+#define OUTASSIGN(v) int tt=v; t[0] = uchar(tt>>8); t[1] = uchar(tt)
+#endif
+
+static void color16_converter(const uchar *from, uchar *to, int w, int delta) {
+  OUTTYPE *t = (OUTTYPE *)to;
+  int d, td;
+  if (dir) {
+    dir = 0;
+    from = from+(w-1)*delta;
+    t = t+(w-1)*OUTSIZE;
+    d = -delta;
+    td = -OUTSIZE;
+  } else {
+    dir = 1;
+    d = delta;
+    td = OUTSIZE;
+  }
+  int r=ri, g=gi, b=bi;
+  for (; w--; from += d, t += td) {
+    r = (r&~fl_redmask)  +from[0]; if (r>255) r = 255;
+    g = (g&~fl_greenmask)+from[1]; if (g>255) g = 255;
+    b = (b&~fl_bluemask) +from[2]; if (b>255) b = 255;
+    OUTASSIGN((
+      ((r&fl_redmask)<> fl_extrashift);
+  }
+  ri = r; gi = g; bi = b;
+}
+
+static void mono16_converter(const uchar *from,uchar *to,int w, int delta) {
+  OUTTYPE *t = (OUTTYPE *)to;
+  int d, td;
+  if (dir) {
+    dir = 0;
+    from = from+(w-1)*delta;
+    t = t+(w-1)*OUTSIZE;
+    d = -delta;
+    td = -OUTSIZE;
+  } else {
+    dir = 1;
+    d = delta;
+    td = OUTSIZE;
+  }
+  uchar mask = fl_redmask & fl_greenmask & fl_bluemask;
+  int r=ri;
+  for (; w--; from += d, t += td) {
+    r = (r&~mask) + *from; if (r > 255) r = 255;
+    uchar m = r&mask;
+    OUTASSIGN((
+      (m<> fl_extrashift);
+  }
+  ri = r;
+}
+
+// special-case the 5r6g5b layout used by XFree86:
+
+static void c565_converter(const uchar *from, uchar *to, int w, int delta) {
+  OUTTYPE *t = (OUTTYPE *)to;
+  int d, td;
+  if (dir) {
+    dir = 0;
+    from = from+(w-1)*delta;
+    t = t+(w-1)*OUTSIZE;
+    d = -delta;
+    td = -OUTSIZE;
+  } else {
+    dir = 1;
+    d = delta;
+    td = OUTSIZE;
+  }
+  int r=ri, g=gi, b=bi;
+  for (; w--; from += d, t += td) {
+    r = (r&7)+from[0]; if (r>255) r = 255;
+    g = (g&3)+from[1]; if (g>255) g = 255;
+    b = (b&7)+from[2]; if (b>255) b = 255;
+    OUTASSIGN(((r&0xf8)<<8) + ((g&0xfc)<<3) + (b>>3));
+  }
+  ri = r; gi = g; bi = b;
+}
+
+static void m565_converter(const uchar *from,uchar *to,int w, int delta) {
+  OUTTYPE *t = (OUTTYPE *)to;
+  int d, td;
+  if (dir) {
+    dir = 0;
+    from = from+(w-1)*delta;
+    t = t+(w-1)*OUTSIZE;
+    d = -delta;
+    td = -OUTSIZE;
+  } else {
+    dir = 1;
+    d = delta;
+    td = OUTSIZE;
+  }
+  int r=ri;
+  for (; w--; from += d, t += td) {
+    r = (r&7) + *from; if (r > 255) r = 255;
+    OUTASSIGN((r>>3) * 0x841);
+  }
+  ri = r;
+}
+
+////////////////////////////////////////////////////////////////
+// 24bit TrueColor converters:
+
+static void rgb_converter(const uchar *from, uchar *to, int w, int delta) {
+  int d = delta-3;
+  for (; w--; from += d) {
+    *to++ = *from++;
+    *to++ = *from++;
+    *to++ = *from++;
+  }
+}
+
+static void bgr_converter(const uchar *from, uchar *to, int w, int delta) {
+  for (; w--; from += delta) {
+    uchar r = from[0];
+    uchar g = from[1];
+    *to++ = from[2];
+    *to++ = g;
+    *to++ = r;
+  }
+}
+
+static void rrr_converter(const uchar *from, uchar *to, int w, int delta) {
+  for (; w--; from += delta) {
+    *to++ = *from;
+    *to++ = *from;
+    *to++ = *from;
+  }
+}
+
+////////////////////////////////////////////////////////////////
+// 32bit TrueColor converters on a 32 or 64-bit machine:
+
+#ifdef U64
+#define STORETYPE U64
+#if WORDS_BIGENDIAN
+#define INNARDS32(f) \
+  U64 *t = (U64*)to; \
+  int w1 = (w+1)/2; \
+  for (; w1--; from += delta) {U64 i = f; from += delta; *t++ = (i<<32)|(f);}
+#else
+#define INNARDS32(f) \
+  U64 *t = (U64*)to; \
+  int w1 = (w+1)/2; \
+  for (; w1--; from += delta) {U64 i=f; from+= delta; *t++ = ((U64)(f)<<32)|i;}
+#endif
+#else
+#define STORETYPE U32
+#define INNARDS32(f) \
+  U32 *t = (U32*)to; for (; w--; from += delta) *t++ = f
+#endif
+
+static void rgbx_converter(const uchar *from, uchar *to, int w, int delta) {
+  INNARDS32((unsigned(from[0])<<24)+(from[1]<<16)+(from[2]<<8));
+}
+
+static void xbgr_converter(const uchar *from, uchar *to, int w, int delta) {
+  INNARDS32((from[0])+(from[1]<<8)+(from[2]<<16));
+}
+
+static void xrgb_converter(const uchar *from, uchar *to, int w, int delta) {
+  INNARDS32((from[0]<<16)+(from[1]<<8)+(from[2]));
+}
+
+static void bgrx_converter(const uchar *from, uchar *to, int w, int delta) {
+  INNARDS32((from[0]<<8)+(from[1]<<16)+(unsigned(from[2])<<24));
+}
+
+static void rrrx_converter(const uchar *from, uchar *to, int w, int delta) {
+  INNARDS32(unsigned(*from) * 0x1010100U);
+}
+
+static void xrrr_converter(const uchar *from, uchar *to, int w, int delta) {
+  INNARDS32(*from * 0x10101U);
+}
+
+static void
+color32_converter(const uchar *from, uchar *to, int w, int delta) {
+  INNARDS32(
+    (from[0]<depth == fl_visual->depth) break;
+  i.format = ZPixmap;
+  i.byte_order = ImageByteOrder(fl_display);
+//i.bitmap_unit = 8;
+//i.bitmap_bit_order = MSBFirst;
+//i.bitmap_pad = 8;
+  i.depth = fl_visual->depth;
+  i.bits_per_pixel = pfv->bits_per_pixel;
+
+  if (i.bits_per_pixel & 7) bytes_per_pixel = 0; // produce fatal error
+  else bytes_per_pixel = i.bits_per_pixel/8;
+
+  unsigned int n = pfv->scanline_pad/8;
+  if (pfv->scanline_pad & 7 || (n&(n-1)))
+    Fl::fatal("Can't do scanline_pad of %d",pfv->scanline_pad);
+  if (n < sizeof(STORETYPE)) n = sizeof(STORETYPE);
+  scanline_add = n-1;
+  scanline_mask = -n;
+
+#if USE_COLORMAP
+  if (bytes_per_pixel == 1) {
+    converter = color8_converter;
+    mono_converter = mono8_converter;
+    return;
+  }
+  if (!fl_visual->red_mask)
+    Fl::fatal("Can't do %d bits_per_pixel colormap",i.bits_per_pixel);
+#endif
+
+  // otherwise it is a TrueColor visual:
+  fl_xpixel(0,0,0); // setup fl_redmask, etc, in fl_color.C
+
+  int rs = fl_redshift;
+  int gs = fl_greenshift;
+  int bs = fl_blueshift;
+
+  switch (bytes_per_pixel) {
+
+  case 2:
+    // All 16-bit TrueColor visuals are supported on any machine with
+    // 24 or more bits per integer.
+#ifdef U16
+    ::i.byte_order = WORDS_BIGENDIAN;
+#else
+    ::i.byte_order = 1;
+#endif
+    if (rs == 11 && gs == 6 && bs == 0 && fl_extrashift == 3) {
+      converter = c565_converter;
+      mono_converter = m565_converter;
+    } else {
+      converter = color16_converter;
+      mono_converter = mono16_converter;
+    }
+    break;
+
+  case 3:
+    if (::i.byte_order) {rs = 16-rs; gs = 16-gs; bs = 16-bs;}
+    if (rs == 0 && gs == 8 && bs == 16) {
+      converter = rgb_converter;
+      mono_converter = rrr_converter;
+    } else if (rs == 16 && gs == 8 && bs == 0) {
+      converter = bgr_converter;
+      mono_converter = rrr_converter;
+    } else {
+      Fl::fatal("Can't do arbitrary 24bit color");
+    }
+    break;
+
+  case 4:
+    if ((::i.byte_order!=0) != WORDS_BIGENDIAN)
+      {rs = 24-rs; gs = 24-gs; bs = 24-bs;}
+    if (rs == 0 && gs == 8 && bs == 16) {
+      converter = xbgr_converter;
+      mono_converter = xrrr_converter;
+    } else if (rs == 24 && gs == 16 && bs == 8) {
+      converter = rgbx_converter;
+      mono_converter = rrrx_converter;
+    } else if (rs == 8 && gs == 16 && bs == 24) {
+      converter = bgrx_converter;
+      mono_converter = rrrx_converter;
+    } else if (rs == 16 && gs == 8 && bs == 0) {
+      converter = xrgb_converter;
+      mono_converter = xrrr_converter;
+    } else {
+      ::i.byte_order = WORDS_BIGENDIAN;
+      converter = color32_converter;
+      mono_converter = mono32_converter;
+    }
+    break;
+
+  default:
+    Fl::fatal("Can't do %d bits_per_pixel",i.bits_per_pixel);
+  }
+
+}
+
+#define MAXBUFFER 0x40000 // 256k
+
+static void innards(const uchar *buf, int X, int Y, int W, int H,
+		    int delta, int linedelta, int mono,
+		    Fl_Draw_Image_Cb cb, void* userdata)
+{
+  if (!linedelta) linedelta = W*delta;
+
+  int dx, dy, w, h;
+  fl_clip_box(X,Y,W,H,dx,dy,w,h);
+  if (w<=0 || h<=0) return;
+  dx -= X;
+  dy -= Y;
+
+  if (!bytes_per_pixel) figure_out_visual();
+  i.width = w;
+  i.height = h;
+
+  void (*conv)(const uchar *from, uchar *to, int w, int delta) = converter;
+  if (mono) conv = mono_converter;
+
+  // See if the data is already in the right format.  Unfortunately
+  // some 32-bit x servers (XFree86) care about the unknown 8 bits
+  // and they must be zero.  I can't confirm this for user-supplied
+  // data, so the 32-bit shortcut is disabled...
+  // This can set bytes_per_line negative if image is bottom-to-top
+  // I tested it on Linux, but it may fail on other Xlib implementations:
+  if (buf && (
+#if 0	// set this to 1 to allow 32-bit shortcut
+      delta == 4 &&
+#if WORDS_BIGENDIAN
+      conv == rgbx_converter
+#else
+      conv == xbgr_converter
+#endif
+      ||
+#endif
+      conv == rgb_converter && delta==3
+      ) && !(linedelta&scanline_add)) {
+    i.data = (char *)(buf+delta*dx+linedelta*dy);
+    i.bytes_per_line = linedelta;
+
+  } else {
+    int linesize = ((w*bytes_per_pixel+scanline_add)&scanline_mask)/sizeof(STORETYPE);
+    int blocking = h;
+    static STORETYPE *buffer;	// our storage, always word aligned
+    static long buffer_size;
+    {int size = linesize*h;
+    if (size > MAXBUFFER) {
+      size = MAXBUFFER;
+      blocking = MAXBUFFER/linesize;
+    }
+    if (size > buffer_size) {
+      delete[] buffer;
+      buffer_size = size;
+      buffer = new STORETYPE[size];
+    }}
+    i.data = (char *)buffer;
+    i.bytes_per_line = linesize*sizeof(STORETYPE);
+    if (buf) {
+      buf += delta*dx+linedelta*dy;
+      for (int j=0; j-3),0,0);
+}
+void fl_draw_image(Fl_Draw_Image_Cb cb, void* data,
+		   int x, int y, int w, int h,int d) {
+  innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data);
+}
+void fl_draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){
+  innards(buf,x,y,w,h,d,l,1,0,0);
+}
+void fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data,
+		   int x, int y, int w, int h,int d) {
+  innards(0,x,y,w,h,d,0,1,cb,data);
+}
+
+void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
+  if (fl_visual->depth > 16) {
+    fl_color(r,g,b);
+    fl_rectf(x,y,w,h);
+  } else {
+    uchar c[3];
+    c[0] = r; c[1] = g; c[2] = b;
+    innards(c,x,y,w,h,0,0,0,0,0);
+  }
+}
+
+#endif
+// End of fl_draw_image.C
diff --git a/src/fl_draw_image_win32.cxx b/src/fl_draw_image_win32.cxx
new file mode 100644
index 000000000..ec58452c1
--- /dev/null
+++ b/src/fl_draw_image_win32.cxx
@@ -0,0 +1,237 @@
+// fl_draw_image_win32.C
+
+// I hope a simple and portable method of drawing color and monochrome
+// images.  To keep this simple, only a single storage type is
+// supported: 8 bit unsigned data, byte order RGB, and pixels are
+// stored packed into rows with the origin at the top-left.  It is
+// possible to alter the size of pixels with the "delta" argument, to
+// add alpha or other information per pixel.  It is also possible to
+// change the origin and direction of the image data by messing with
+// the "delta" and "linedelta", making them negative, though this may
+// defeat some of the shortcuts in translating the image for X.
+
+// Unbelievably (since it conflicts with how most PC software works)
+// Micro$oft picked a bottom-up and BGR storage format for their
+// DIB images.  I'm pretty certain there is a way around this, but
+// I can't find any other than the brute-force method of drawing
+// each line as a seperate image.  This may also need to be done
+// if the delta is any amount other than 1, 3, or 4.
+
+////////////////////////////////////////////////////////////////
+
+#include 
+#include 
+#include 
+#include 
+
+#define MAXBUFFER 0x40000 // 256k
+
+#if USE_COLORMAP
+
+// error-diffusion dither into the fltk colormap
+static void dither(uchar* to, const uchar* from, int w, int delta) {
+  static int ri, gi, bi, dir;
+  int r=ri, g=gi, b=bi;
+  int d, td;
+  if (dir) {
+    dir = 0;
+    from = from+(w-1)*delta;
+    to = to+(w-1);
+    d = -delta;
+    td = -1;
+  } else {
+    dir = 1;
+    d = delta;
+    td = 1;
+  }
+  for (; w--; from += d, to += td) {
+    r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255;
+    int rr = r*FL_NUM_RED/256;
+    r -= rr*255/(FL_NUM_RED-1);
+    g += from[1]; if (g < 0) g = 0; else if (g>255) g = 255;
+    int gg = g*FL_NUM_GREEN/256;
+    g -= gg*255/(FL_NUM_GREEN-1);
+    b += from[2]; if (b < 0) b = 0; else if (b>255) b = 255;
+    int bb = b*FL_NUM_BLUE/256;
+    b -= bb*255/(FL_NUM_BLUE-1);
+    *to = uchar(FL_COLOR_CUBE+(bb*FL_NUM_RED+rr)*FL_NUM_GREEN+gg);
+  }
+  ri = r; gi = g; bi = b;
+}
+
+// error-diffusion dither into the fltk colormap
+static void monodither(uchar* to, const uchar* from, int w, int delta) {
+  static int ri,dir;
+  int r=ri;
+  int d, td;
+  if (dir) {
+    dir = 0;
+    from = from+(w-1)*delta;
+    to = to+(w-1);
+    d = -delta;
+    td = -1;
+  } else {
+    dir = 1;
+    d = delta;
+    td = 1;
+  }
+  for (; w--; from += d, to += td) {
+    r += *from; if (r < 0) r = 0; else if (r>255) r = 255;
+    int rr = r*FL_NUM_GRAY/256;
+    r -= rr*255/(FL_NUM_GRAY-1);
+    *to = uchar(FL_GRAY_RAMP+rr);
+  }
+  ri = r;
+}
+
+#endif // USE_COLORMAP
+
+static void innards(const uchar *buf, int X, int Y, int W, int H,
+		    int delta, int linedelta, int mono,
+		    Fl_Draw_Image_Cb cb, void* userdata)
+{
+#if USE_COLORMAP
+  char indexed = (fl_palette != 0);
+#endif
+
+  if (!linedelta) linedelta = W*delta;
+
+  int x, y, w, h;
+  fl_clip_box(X,Y,W,H,x,y,w,h);
+  if (w<=0 || h<=0) return;
+  if (buf) buf += (x-X)*delta + (y-Y)*linedelta;
+
+  static U32 bmibuffer[256+12];
+  BITMAPINFO &bmi = *((BITMAPINFO*)bmibuffer);
+  if (!bmi.bmiHeader.biSize) {
+    bmi.bmiHeader.biSize = sizeof(bmi)-4; // does it use this to determine type?
+    bmi.bmiHeader.biPlanes = 1;
+    bmi.bmiHeader.biCompression = BI_RGB;
+    bmi.bmiHeader.biXPelsPerMeter = 0;
+    bmi.bmiHeader.biYPelsPerMeter = 0;
+    bmi.bmiHeader.biClrUsed = 0;
+    bmi.bmiHeader.biClrImportant = 0;
+  }
+#if USE_COLORMAP
+  if (indexed) {
+    for (int i=0; i<256; i++) {
+      *((short*)(bmi.bmiColors)+i) = i;
+    }
+  } else
+#endif
+  if (mono) {
+    for (int i=0; i<256; i++) {
+      bmi.bmiColors[i].rgbBlue = i;
+      bmi.bmiColors[i].rgbGreen = i;
+      bmi.bmiColors[i].rgbRed = i;
+      bmi.bmiColors[i].rgbReserved = i;
+    }
+  }
+  bmi.bmiHeader.biWidth = w;
+#if USE_COLORMAP
+  bmi.bmiHeader.biBitCount = mono|indexed ? 8 : 24;
+  int pixelsize = mono|indexed ? 1 : 3;
+#else
+  bmi.bmiHeader.biBitCount = mono ? 8 : 24;
+  int pixelsize = mono ? 1 : 3;
+#endif
+  int linesize = (pixelsize*w+3)&~3;
+  
+  static U32* buffer;
+  int blocking = h;
+  {int size = linesize*h;
+  if (size > MAXBUFFER) {
+    size = MAXBUFFER;
+    blocking = MAXBUFFER/linesize;
+  }
+  static long buffer_size;
+  if (size > buffer_size) {
+    delete[] buffer;
+    buffer_size = size;
+    buffer = new U32[(size+3)/4];
+  }}
+  bmi.bmiHeader.biHeight = blocking;
+  static U32* line_buffer;
+  if (!buf) {
+    int size = W*delta;
+    static int line_buf_size;
+    if (size > line_buf_size) {
+      delete[] line_buffer;
+      line_buf_size = size;
+      line_buffer = new U32[(size+3)/4];
+    }
+  }
+  for (int j=0; j-3),0,0);
+}
+void fl_draw_image(Fl_Draw_Image_Cb cb, void* data,
+		   int x, int y, int w, int h,int d) {
+  innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data);
+}
+void fl_draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){
+  innards(buf,x,y,w,h,d,l,1,0,0);
+}
+void fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data,
+		   int x, int y, int w, int h,int d) {
+  innards(0,x,y,w,h,d,0,1,cb,data);
+}
+
+void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
+#if USE_COLORMAP
+  // use the error diffusion dithering code to produce a much nicer block:
+  if (fl_palette) {
+    uchar c[3];
+    c[0] = r; c[1] = g; c[2] = b;
+    innards(c,x,y,w,h,0,0,0,0,0);
+    return;
+  }
+#endif
+  fl_color(r,g,b);
+  fl_rectf(x,y,w,h);
+}
+
+// End of fl_draw_image_win32.C
diff --git a/src/fl_draw_pixmap.cxx b/src/fl_draw_pixmap.cxx
new file mode 100644
index 000000000..2522093c0
--- /dev/null
+++ b/src/fl_draw_pixmap.cxx
@@ -0,0 +1,224 @@
+// fl_draw_pixmap.C
+
+// Implemented without using the xpm library (which I can't use because
+// it interferes with the color cube used by fl_draw_image).
+
+// Current implementation is cheap and slow, and works best on a full-color
+// display.  Transparency is not handled, and colors are dithered to
+// the color cube.  Color index is achieved by adding the id
+// characters together!  Also mallocs a lot of temporary memory!
+
+// Notice that there is no pixmap file interface.  This is on purpose,
+// as I want to discourage programs that require support files to work.
+// All data needed by a program ui should be compiled in!!!
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int ncolors, chars_per_pixel;
+
+int fl_measure_pixmap(/*const*/char * const *data, int &w, int &h) {
+  int i = sscanf(data[0],"%d %d %d %d",&w,&h,&ncolors,&chars_per_pixel);
+  if (i<4 || w<=0 || h<=0 ||
+      chars_per_pixel!=1 && chars_per_pixel!=2) return w=0;
+  return 1;
+}
+
+#ifdef U64
+
+// The callback from fl_draw_image to get a row of data passes this:
+struct pixmap_data {
+  int w, h;
+  char*const* data;
+  U64 colors[256];
+};
+
+// callback for 1 byte per pixel:
+static void cb1(void*v, int x, int y, int w, uchar* buf) {
+  pixmap_data& d = *(pixmap_data*)v;
+  const char* p = d.data[y]+x;
+  U64* q = (U64*)buf;
+  for (int X=(w+1)/2; X--; p += 2) {
+#if WORDS_BIGENDIAN
+    *q++ = (d.colors[p[0]&255]<<32) | d.colors[p[1]&255];
+#else
+    *q++ = (d.colors[p[1]&255]<<32) | d.colors[p[0]&255];
+#endif
+  }
+}
+
+// callback for 2 bytes per pixel:
+static void cb2(void*v, int x, int y, int w, uchar* buf) {
+  pixmap_data& d = *(pixmap_data*)v;
+  const char* p = d.data[y]+2*x;
+  U64* q = (U64*)buf;
+  for (int X=(w+1)/2; X--;) {
+    int index = *p++; int t = *p++; index += (t<<4)+(t>>4);
+    int index1= *p++; t = *p++; index1 += (t<<4)+(t>>4);
+#if WORDS_BIGENDIAN
+    *q++ = (d.colors[index&255]<<32) | d.colors[index1&255];
+#else
+    *q++ = (d.colors[index1&255]<<32) | d.colors[index&255];
+#endif
+  }
+}
+
+#else
+
+// The callback from fl_draw_image to get a row of data passes this:
+struct pixmap_data {
+  int w, h;
+  char*const* data;
+  U32 colors[256];
+};
+
+// callback for 1 byte per pixel:
+static void cb1(void*v, int x, int y, int w, uchar* buf) {
+  pixmap_data& d = *(pixmap_data*)v;
+  const char* p = d.data[y]+x;
+  U32* q = (U32*)buf;
+  for (int X=w; X--;) *q++ = d.colors[(*p++)&255];
+}
+
+// callback for 2 bytes per pixel:
+static void cb2(void*v, int x, int y, int w, uchar* buf) {
+  pixmap_data& d = *(pixmap_data*)v;
+  const char* p = d.data[y]+2*x;
+  U32* q = (U32*)buf;
+  for (int X=w; X--;) {
+    int index = *p++; int t = *p++; index += (t<<4)+(t>>4);
+    *q++ = d.colors[index&255];
+  }
+}
+
+#endif
+
+#ifdef WIN32
+// this is in Fl_arg.C:
+extern int fl_parse_color(const char*, uchar&, uchar&, uchar&);
+#endif
+
+uchar **fl_mask_bitmap; // if non-zero, create bitmap and store pointer here
+
+int fl_draw_pixmap(/*const*/char*const* data, int x, int y, Fl_Color bg) {
+  pixmap_data d;
+  if (!fl_measure_pixmap(data, d.w, d.h)) return 0;
+  data++;
+  int transparent_index = -1;
+
+  if (ncolors < 0) {	// fltk (non standard) compressed colormap
+    ncolors = -ncolors;
+    const char *p = *data++;
+    // if first color is ' ' it is transparent (put it later to make
+    // it not be transparent):
+    if (*p == ' ') {
+      uchar* c = (uchar*)&d.colors[' '];
+#ifdef U64
+      *(U64*)c = 0;
+#if WORDS_BIGENDIAN
+      c += 4;
+#endif
+#endif
+      transparent_index = ' ';
+      Fl::get_color(bg, c[0], c[1], c[2]); c[3] = 0;
+      p += 4;
+      ncolors--;
+    }
+    // read all the rest of the colors:
+    for (int i=0; i < ncolors; i++) {
+      uchar* c = (uchar*)&d.colors[(*p++)&255];
+#ifdef U64
+      *(U64*)c = 0;
+#if WORDS_BIGENDIAN
+      c += 4;
+#endif
+#endif
+      *c++ = *p++;
+      *c++ = *p++;
+      *c++ = *p++;
+      *c = 0;
+    }
+  } else {	// normal XPM colormap with names
+    for (int i=0; i1) {int t = *p++; index += (t<<4)+(t>>4);}
+      // look for "c word", or last word if none:
+      const char *previous_word = p;
+      for (;;) {
+	while (*p && isspace(*p)) p++; char what = *p++;
+	while (*p && !isspace(*p)) p++;
+	while (*p && isspace(*p)) p++;
+	if (!*p) {p = previous_word; break;}
+	if (what == 'c') break;
+	previous_word = p;
+	while (*p && !isspace(*p)) p++;
+      }
+      // copy the color name and look it up:
+      char name[256];
+      char *q; for (q = name; *p && !isspace(*p); *q++ = *p++); *q++ = 0;
+      uchar *c = (uchar *)&d.colors[index&255];
+#ifdef U64
+      *(U64*)c = 0;
+#if WORDS_BIGENDIAN
+      c += 4;
+#endif
+#endif
+#ifdef WIN32
+      if (fl_parse_color(name, c[0], c[1], c[2])) {;
+#else
+      XColor x;
+      if (XParseColor(fl_display, fl_colormap, name, &x)) {
+	c[0] = x.red>>8; c[1] = x.green>>8; c[2] = x.blue>>8;
+#endif
+      } else { // assumme "None" or "#transparent" for any errors
+	// this should be transparent...
+	Fl::get_color(bg, c[0], c[1], c[2]);
+	transparent_index = index&255;
+      }
+    }
+  }
+  d.data = data;
+
+  // build the mask bitmap used by Fl_Pixmap:
+  if (fl_mask_bitmap && transparent_index >= 0) {
+    int W = (d.w+7)/8;
+    uchar *bitmap = new uchar[W * d.h];
+    *fl_mask_bitmap = bitmap;
+    for (int y = 0; y < d.h; y++) {
+      uchar* p = (uchar*)data[y];
+      if (chars_per_pixel <= 1) {
+	for (int x = 0; x < W; x++) {
+	  int b = (*p++ != transparent_index);
+	  if (*p++ != transparent_index) b |= 2;
+	  if (*p++ != transparent_index) b |= 4;
+	  if (*p++ != transparent_index) b |= 8;
+	  if (*p++ != transparent_index) b |= 16;
+	  if (*p++ != transparent_index) b |= 32;
+	  if (*p++ != transparent_index) b |= 64;
+	  if (*p++ != transparent_index) b |= 128;
+	  *bitmap++ = b;
+	}
+      } else {
+	for (int x = 0; x < W; x++) {
+	  int b = 0;
+	  for (int i = 0; i < 8; i++) {
+	    int index = *p++; int t = *p++; index += (t<<4)+(t>>4);
+	    if ((index&255) != transparent_index) b |= (1<
+#include 
+#include 
+
+// data[] is dx, dy, color triples
+
+static void innards(
+    const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align,
+    int data[][3], int n)
+{
+  Fl_Align a1 = align;
+  if (a1 & FL_ALIGN_CLIP) {
+    fl_clip(X, Y, W, H); a1 = (Fl_Align)(a1&~FL_ALIGN_CLIP);}
+  fl_font((Fl_Font)o->font, o->size);
+  for (int i = 0; i < n; i++) {
+    fl_color((Fl_Color)(i < n-1 ? data[i][2] : o->color));
+    fl_draw(o->value, X+data[i][0], Y+data[i][1], W, H, a1);
+  }
+  if (align & FL_ALIGN_CLIP) fl_pop_clip();
+}
+
+static void fl_shadow_label(
+    const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align)
+{
+  static int data[2][3] = {{2,2,FL_DARK3},{0,0,0}};
+  innards(o, X, Y, W, H, align, data, 2);
+}
+
+static void fl_engraved_label(
+    const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align)
+{
+  static int data[7][3] = {
+    {1,0,FL_LIGHT3},{1,1,FL_LIGHT3},{0,1,FL_LIGHT3},
+    {-1,0,FL_DARK3},{-1,-1,FL_DARK3},{0,-1,FL_DARK3},
+    {0,0,0}};
+  innards(o, X, Y, W, H, align, data, 7);
+}
+
+static void fl_embossed_label(
+    const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align)
+{
+  static int data[7][3] = {
+    {-1,0,FL_LIGHT3},{-1,-1,FL_LIGHT3},{0,-1,FL_LIGHT3},
+    {1,0,FL_DARK3},{1,1,FL_DARK3},{0,1,FL_DARK3},
+    {0,0,0}};
+  innards(o, X, Y, W, H, align, data, 7);
+}
+
+Fl_Labeltype define_FL_SHADOW_LABEL() {
+  Fl::set_labeltype(_FL_SHADOW_LABEL, fl_shadow_label, 0);
+  return _FL_SHADOW_LABEL;
+}
+Fl_Labeltype define_FL_ENGRAVED_LABEL() {
+  Fl::set_labeltype(_FL_ENGRAVED_LABEL, fl_engraved_label, 0);
+  return _FL_ENGRAVED_LABEL;
+}
+Fl_Labeltype define_FL_EMBOSSED_LABEL() {
+  Fl::set_labeltype(_FL_EMBOSSED_LABEL, fl_embossed_label, 0);
+  return _FL_EMBOSSED_LABEL;
+}
diff --git a/src/fl_file_chooser.cxx b/src/fl_file_chooser.cxx
new file mode 100644
index 000000000..35cbeb747
--- /dev/null
+++ b/src/fl_file_chooser.cxx
@@ -0,0 +1,600 @@
+// fl_file_chooser.c
+
+// fltk (Fast Light Tool Kit) version 0.99
+// Copyright (C) 1998 Bill Spitzak
+
+// The "completion" file chooser for fltk
+// Designed and implemented by Bill Spitzak 12/17/93
+// Rewritten for fltk 4/29/96
+// Rewritten to use scandir() 1/7/97
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+static void default_callback(const char*) {}
+static void (*current_callback)(const char*) = default_callback;
+void fl_file_chooser_callback(void (*cb)(const char*)) {
+  current_callback = cb ? cb : default_callback;
+}
+
+// "File Chooser Browser" widget:
+class FCB : public Fl_Browser_ {
+  void* item_first() const ;
+  void* item_next(void*) const ;
+  void* item_prev(void*) const ;
+  int item_height(const dirent*, int) const ;
+  int item_height(void*) const ;
+  int item_width(const dirent*) const ;
+  int item_width(void*) const ;
+  int item_quick_height(void*) const ;
+  int incr_height() const ;
+  void item_draw(void*, int, int, int, int) const ;
+  int checkdir(const dirent*, char*) const ;
+  void draw();
+  void clear_prev();
+public:
+  char listed[FL_PATH_MAX];// current dir & starname
+  int dirend;		// points after last / before starname
+  int nameend;		// length to trailing '*' or '\0'
+  const char* pattern;	// default pattern
+  dirent** list;	// the file names
+  dirent** last;	// pointer after end of list
+  const char* message;	// message if no file names
+  char preved[FL_PATH_MAX];// directory listed in prev
+  dirent** prev;	// cached list of another directory
+  dirent** prev_last;	// end of that list
+  int prev_count;
+  FCB(int x, int y, int w, int h) : Fl_Browser_(x, y, w, h, 0) {
+    type(FL_HOLD_BROWSER);
+    listed[0] = 0;
+    dirend = nameend = 1;
+    pattern = 0;
+    list = prev = 0;
+    message = 0;
+  }
+  // ~FCB nyi
+  void clear();
+  void set(const char*);
+  int get(char*);
+};
+
+// "File Chooser Window" widget:
+class FCW : public Fl_Window {
+public:
+  int handle(int);
+  Fl_Input input;
+  Fl_Button* ok_button;
+  Fl_Button* cancel_button;
+  Fl_Button* normal_button;
+  FCB browser;
+  FCW();
+};
+
+/* Files are marked as being directories by replacing the trailing null
+   with a '/' if it is a directory, a '\001' if it is *not* a directory.
+   An item has height (and is thus selectable) if it is either a directory
+   or if it matches the pattern.  Quick-height assummes all unknown files
+   are directories, and thus saves the time needed to do a stat().
+*/
+
+// return pointer to last character:
+static const char* end_of_name(const dirent* d) {
+#if HAVE_DIRENT_H
+  const char* e;
+  for (e = d->d_name; ;e++) switch (*e) {
+  case 0: case 1: case '/': return e;
+  }
+#else
+  // warning: clobbers byte after end of name
+  return d->d_name + d->d_namelen;
+#endif
+}
+
+// return true if item is directory, when given pointer to last character:
+int FCB::checkdir(const dirent* d, char* e) const {
+  if (*e == 1) return 0;
+  if (*e == '/') return 1;
+  char buf[FL_PATH_MAX];
+  memcpy(buf, listed, dirend);
+  memcpy(buf+dirend, d->d_name, e-d->d_name);
+  *(buf+dirend+(e-d->d_name)) = 0;
+  if (filename_isdir(buf)) {
+    *e = '/'; return 1;
+  } else {
+    *e = 1; return 0;
+  }
+}
+
+void* FCB::item_first() const {return list;}
+
+void* FCB::item_next(void* p) const {
+  if ((dirent**)p+1 >= last) return 0;
+  return (dirent**)p+1;
+}
+
+void* FCB::item_prev(void* p) const {
+  if ((dirent**)p <= list) return 0;
+  return ((dirent**)p)-1;
+}
+
+static int ido_matching(const dirent* p, const char* e, const char* n) {
+  // replace / or 1 at end with 0 and do match, then put back.  yukko
+  int save = *e; *(char*)e = 0;
+  int r = filename_match(p->d_name, n);
+  *(char*)e = save;
+  return(r);
+}
+
+int FCB::incr_height() const {return textsize()+2;}
+
+int FCB::item_height(const dirent* p, int slow) const {
+  const char* e = end_of_name(p);
+  if (listed[dirend]) {
+//  if (p->d_name[0]=='.' && listed[dirend]!='.') return 0;
+    if (listed[nameend-1]=='/') {
+      if (slow ? !checkdir(p, (char*)e) : *e==1) return 0;
+      ((char*)listed)[nameend-1] = 0;
+      int r = ido_matching(p, e, listed+dirend);
+      ((char*)listed)[nameend-1] = '/';
+      if (!r) return 0;
+    } else {
+      if (!ido_matching(p, e, listed+dirend)) return 0;
+    }
+  } else {
+    if (p->d_name[0]=='.') return 0;
+    if (pattern && (slow ? !checkdir(p, (char*)e) : *e==1) &&
+	!ido_matching(p, e, pattern)) return 0;
+  }
+  return textsize()+2;
+}
+
+int FCB::item_height(void* x) const {
+  return item_height(*(const dirent**)x, 1);
+}
+
+int FCB::item_quick_height(void* x) const {
+  return item_height(*(const dirent**)x, 0);
+}
+
+void FCB::item_draw(void* v, int x, int y, int, int h) const {
+  const dirent* p = *(const dirent**)v;
+  const char* e = end_of_name(p);
+  if (checkdir(p, (char*)e)) e++;
+  if (v == selection()) fl_color(contrast(textcolor(), selection_color()));
+  else fl_color(textcolor());
+  fl_font(textfont(), textsize(), default_font(), default_size());
+  fl_draw(p->d_name, e-p->d_name, x+4, y+h-3);
+}
+
+int FCB::item_width(const dirent* p) const {
+  const char* e = end_of_name(p); if (*e == '/') e++;
+  fl_font(textfont(), textsize(), default_font(), default_size());
+  return (int)fl_width(p->d_name, e-p->d_name)+4;
+}
+
+int FCB::item_width(void* x) const {
+  return item_width(*(const dirent**)x);
+}
+
+// "get" the current value by copying the name of the selected file
+// or if none are selected, by copying as many common letters as
+// possible of the matched file list:
+int FCB::get(char* buf) {
+  dirent** q = (dirent**)selection(); // the file to copy from
+  int n = 0;	// number of letters
+  if (q) {	// a file is selected
+    const char* e = end_of_name(*q);
+    n = e - (*q)->d_name;
+    if (*e == '/') n++;
+  } else {	// do filename completion
+    for (q = list; q < last && !item_height(*q, 0); q++);
+    if (q < last) {
+      const char* e = end_of_name(*q);
+      n = e - (*q)->d_name;
+      if (*e == '/') n++;
+      for (dirent** r = q+1; n && r < last; r++) {
+	if (!item_height(*r, 0)) continue;
+	int i;
+	for (i=0; id_name[i]==(*r)->d_name[i]; i++);
+	n = i;
+      }
+    }
+  }
+  if (n) {
+    memcpy(buf, listed, dirend);
+    memcpy(buf+dirend, (*q)->d_name, n);
+    buf[dirend+n]=0;
+  }
+  return n;
+}
+
+// "set" the current value by changing the directory being listed and
+// changing the highlighted item, if possible:
+void FCB::set(const char* buf) {
+
+  int bufdirend;
+  int ispattern = 0;
+  const char* c = buf;
+  for (bufdirend=0; *c;) switch(*c++) {
+  case '?': case '[': case '*': case '{': ispattern = 1; goto BREAK;
+#if defined(WIN32) || defined(__EMX__)
+  case '\\':
+#endif
+  case '/': bufdirend=c-buf; break;
+  }
+#if defined(WIN32) || defined(__EMX__)
+  if ((!bufdirend) && isalpha(buf[0]) && (buf[1]==':')) bufdirend = 2;
+#endif
+ BREAK:
+  int bufend = strlen(buf);
+  if (bufend<=bufdirend) ispattern = 1;
+
+  // if directory is different, change list to xxx/ :
+  if (bufdirend != dirend || strncmp(buf, listed, bufdirend)) {
+    if (prev &&
+	preved[bufdirend]==0 && !strncmp(buf, preved, bufdirend)) {
+      strcpy(preved, listed); preved[dirend] = 0;
+      dirent** t;
+      t = prev; prev = list; list = t;
+      t = prev_last; prev_last = last; last = t;
+      strcpy(listed, buf);
+      dirend = nameend = bufdirend;
+      message = 0;
+    } else {
+      if (list) {
+	clear_prev();
+	strcpy(preved, listed); preved[dirend]=0;
+	prev = list;
+	prev_last = last;
+      }
+      list = last = 0;
+      message = "reading..."; redraw(); Fl::flush();
+      strcpy(listed, buf);
+      dirend = nameend = bufdirend;
+      listed[dirend] = listed[dirend+1] = 0;
+      int n = filename_list(dirend ? listed : ".", &list);
+      if (n < 0) {
+	if (errno==ENOENT) message = "No such directory";
+	else message = strerror(errno);
+	n = 0; list = 0;
+      } else message = 0;
+      last = list+n;
+    }
+    if (list && last <= list+2) message = "Empty directory";
+    new_list();
+  }
+
+  dirent** q = 0; // will point to future selection
+  int any = 0; // true if any names shown
+
+  // do we match one item in the previous list?
+  if (!ispattern && bufend >= nameend) {
+    for (q = list; ; q++) {
+      if (q >= last) {q = 0; break;}
+      if (item_height(*q, 0)==0) continue;
+      any = 1;
+      const char* a = (*q)->d_name;
+      const char* b = buf+bufdirend;
+      while (*b && *a==*b) {a++; b++;}
+      if (!*b && (*a==0 || /* *a=='/' ||*/ *a==1)) break;
+    }
+  }
+
+  // no, change the list pattern to the new text + a star:
+  if (!q) {
+    strcpy(listed+dirend, buf+bufdirend);
+    nameend = bufend;
+    if (!ispattern) {listed[nameend]='*'; listed[nameend+1]=0;}
+    any = 0;
+    // search again for an exact match:
+    for (q = list; ; q++) {
+      if (q >= last) {q = 0; break;}
+      if (item_height(*q, 0)==0) continue;
+      any = 1;
+      const char* a = (*q)->d_name;
+      const char* b = buf+bufdirend;
+      while (*b && *a==*b) {a++; b++;}
+      if (!*b && (*a==0 || /* *a=='/' ||*/ *a==1)) break;
+    }
+    new_list();
+  }
+
+  if (any) message = 0;
+  else if (!message) message = "No matching files";
+  select_only(q);
+  if (q) current_callback(buf);
+}
+
+void FCB::draw() {
+  if (message) {
+    Fl_Boxtype b = box(); if (!b) b = Fl_Input_::default_box();
+    draw_box(b,color());
+    fl_color(FL_INACTIVE_COLOR);
+    fl_draw(message, x()+7, y()+3, w(), h()-3, FL_ALIGN_TOP_LEFT);
+  } else {
+    Fl_Browser_::draw();
+    if (full_height()<=0) {
+      message = "No matching files";
+      draw();
+    }
+  }
+}
+
+void FCB::clear_prev() {
+  if (prev) {
+    for (dirent**p=prev_last-1; p>=prev; p--) free((void*)*p);
+    free((void*)prev);
+    prev = prev_last = 0;
+  }
+}
+
+void FCB::clear() {
+  if (list) {
+    for (dirent**p=last-1; p>=list; p--) free((void*)*p);
+    free((void*)list);
+    list = last = 0;
+  }
+  clear_prev();
+  listed[0] = 0; dirend = 1;
+}
+
+////////////////////////////////////////////////////////////////
+
+static void fcb_cb(Fl_Widget*, void* v) {
+  FCW* w = (FCW*)v;
+  char buf[FL_PATH_MAX];
+  if (w->browser.get(buf)) {
+    w->input.value(buf);
+    w->input.position(10000);
+//  w->input.position(10000, w->browser.dirend);
+    if (Fl::event_button()==1) {
+      if (Fl::event_clicks()) w->ok_button->do_callback();
+      else w->browser.set(buf);
+    } else {
+      current_callback(buf);
+    }
+  }
+}
+
+static void tab_cb(Fl_Widget*, void* v) {
+  FCW* w = (FCW*)v;
+  char buf[FL_PATH_MAX];
+  if (w->browser.get(buf)) {
+    w->input.value(buf);
+    w->input.position(10000);
+    w->browser.set(buf);
+  }
+}
+
+#if defined(WIN32) || defined(__EMX__)
+// ':' needs very special handling!
+static inline int isdirsep(char c) {return c=='/' || c=='\\';}
+#else
+#define isdirsep(c) ((c)=='/')
+#endif
+
+static void input_cb(Fl_Widget*, void* v) {
+  FCW* w = (FCW*)v;
+  const char* buf = w->input.value();
+  char localbuf[FL_PATH_MAX];
+  if (buf[0] && isdirsep(buf[w->input.size()-1])
+      && filename_expand(localbuf, buf)) {
+    buf = localbuf;
+    w->input.value(localbuf);
+    w->input.position(10000);
+  }
+  w->browser.set(buf);
+}
+
+static void up_cb(Fl_Widget*, void* v) { // the .. button
+  FCW* w = (FCW*)v;
+  char* p;
+  char* newname;
+  char buf[FL_PATH_MAX];
+  p = w->browser.listed+w->browser.dirend-1; // point right before last '/'
+  if (p < w->browser.listed)
+    newname = "../"; // go up from current directory
+  else {
+    for (; p>w->browser.listed; p--) if (isdirsep(*(p-1))) break;
+    if (isdirsep(*p) || *p=='.' &&
+	(isdirsep(p[1]) || p[1]=='.' && isdirsep(p[2]))) {
+      p = w->browser.listed+w->browser.dirend;
+      memcpy(buf, w->browser.listed, p-w->browser.listed);
+      strcpy(buf+(p-w->browser.listed), "../");
+    } else {
+      memcpy(buf, w->browser.listed, p-w->browser.listed);
+      buf[p-w->browser.listed] = 0;
+    }
+    newname = buf;
+  }
+  w->input.value(newname);
+  w->input.position(10000);
+  w->browser.set(newname);
+}
+
+static void dir_cb(Fl_Widget* obj, void* v) { // directory buttons
+  FCW* w = (FCW*)v;
+  const char* p = obj->label(); if (*p=='&') p++;
+  char buf[FL_PATH_MAX];
+  char* q; for (q=buf; *p && *p!=' '; *q++ = *p++); *q = 0;
+  filename_expand(buf, buf);
+  w->input.value(buf);
+  w->input.position(10000);
+  w->browser.set(buf);
+}
+
+static void working_cb(Fl_Widget*, void* v) { // directory buttons
+  FCW*w = (FCW*)v;
+  char buf[FL_PATH_MAX];
+  filename_absolute(buf, "");
+  w->input.value(buf);
+  w->input.position(10000);
+  w->browser.set(buf);
+}
+
+static void files_cb(Fl_Widget* obj, void* v) { // file pattern buttons
+  FCW* w = (FCW*)v;
+  char buf[FL_PATH_MAX];
+  strcpy(buf, w->input.value());
+  char* q = buf+w->browser.dirend;
+  if (obj != w->normal_button) {	// tack on first word of label
+    const char* p = obj->label(); if (*p=='&') p++;
+    for (; *p && *p!=' '; *q++ = *p++);
+  }
+  *q = 0;
+  w->input.value(buf);
+  w->input.position(10000, w->browser.dirend);
+  w->browser.set(buf);
+}
+
+/*----------------------- The Main Routine ----------------------*/
+#define HEIGHT_BOX	(4*WIDTH_SPC+HEIGHT_BUT+HEIGHT_INPUT+HEIGHT_BROWSER)
+#define HEIGHT_BUT	25
+#define HEIGHT_INPUT	30
+#define HEIGHT_BROWSER	(9*HEIGHT_BUT+2) // must be > buttons*HEIGHT_BUT
+#define WIDTH_BOX	(3*WIDTH_SPC+WIDTH_BUT+WIDTH_BROWSER)
+#define WIDTH_BROWSER	350
+#define WIDTH_BUT	125
+#define WIDTH_OK	70
+#define WIDTH_SPC	5
+
+int FCW::handle(int event) {
+  if (Fl_Window::handle(event)) return 1;
+  if (event==FL_KEYBOARD && Fl::event_key()==FL_Tab) {
+    tab_cb(this, this);
+    return 1;
+  }
+  return 0;
+}
+
+// set this to make extra directory-jumping button:
+const char* fl_file_chooser_button;
+extern const char* fl_ok;
+extern const char* fl_cancel;
+
+FCW::FCW() : Fl_Window(WIDTH_BOX, HEIGHT_BOX),
+	input(WIDTH_SPC, HEIGHT_BOX-HEIGHT_BUT-2*WIDTH_SPC-HEIGHT_INPUT,
+	      WIDTH_BOX-2*WIDTH_SPC, HEIGHT_INPUT, 0),
+	browser(2*WIDTH_SPC+WIDTH_BUT, WIDTH_SPC,
+		WIDTH_BROWSER, HEIGHT_BROWSER)
+{
+  int but_y = WIDTH_SPC;
+  input.callback(input_cb, this);
+  input.when(FL_WHEN_CHANGED);
+  //  add(browser);
+  browser.callback(fcb_cb, this);
+
+  begin();
+  Fl_Widget* obj;
+  obj = ok_button = new Fl_Return_Button(
+    WIDTH_BOX-2*(WIDTH_SPC+WIDTH_OK), HEIGHT_BOX-WIDTH_SPC-HEIGHT_BUT,
+    WIDTH_OK, HEIGHT_BUT, fl_ok);
+  obj = cancel_button = new Fl_Button(
+    WIDTH_BOX-WIDTH_SPC-WIDTH_OK, HEIGHT_BOX-WIDTH_SPC-HEIGHT_BUT,
+    WIDTH_OK, HEIGHT_BUT, fl_cancel);
+  cancel_button->shortcut("^[");
+
+  obj=new Fl_Button(WIDTH_SPC,but_y,WIDTH_BUT,HEIGHT_BUT, "&Up one directory");
+  obj->callback(up_cb, this);
+  but_y += HEIGHT_BUT;
+
+  obj = new Fl_Button(WIDTH_SPC, but_y, WIDTH_BUT, HEIGHT_BUT, "&~/ Home");
+  obj->callback(dir_cb, this);
+  but_y += HEIGHT_BUT;
+
+  obj = new Fl_Button(WIDTH_SPC, but_y, WIDTH_BUT, HEIGHT_BUT, "&/ Root");
+  obj->callback(dir_cb, this);
+  but_y += HEIGHT_BUT;
+
+  obj=new Fl_Button(WIDTH_SPC, but_y, WIDTH_BUT, HEIGHT_BUT, "&Current dir");
+  obj->callback(working_cb, this);
+  but_y += HEIGHT_BUT;
+
+  if (fl_file_chooser_button) {
+    obj=new Fl_Button(WIDTH_SPC,but_y,WIDTH_BUT,HEIGHT_BUT,fl_file_chooser_button);
+    obj->callback(dir_cb, this);
+    but_y += HEIGHT_BUT;
+  }
+
+  normal_button = new Fl_Button(WIDTH_SPC, but_y, WIDTH_BUT, HEIGHT_BUT, "");
+  normal_button->callback(files_cb, this);
+  but_y += HEIGHT_BUT;
+
+  obj = new Fl_Button(WIDTH_SPC,but_y, WIDTH_BUT, HEIGHT_BUT, "* &All files");
+  obj->callback(files_cb, this);
+  but_y += HEIGHT_BUT;
+
+  obj = new Fl_Button(WIDTH_SPC,but_y,WIDTH_BUT,HEIGHT_BUT, ". &Hidden files");
+  obj->callback(files_cb, this);
+  but_y += HEIGHT_BUT;
+
+  obj = new Fl_Button(WIDTH_SPC,but_y,WIDTH_BUT,HEIGHT_BUT, "*/ &Directories");
+  obj->callback(files_cb, this);
+  but_y += HEIGHT_BUT;
+
+  resizable(new Fl_Box(browser.x(), but_y,
+		       cancel_button->x()-browser.x(),
+		       browser.y()+browser.h()-but_y));
+  // add(input); // put last for better draw() speed
+  end();
+  set_modal();
+}
+
+char* fl_file_chooser(const char* message, const char* pat, const char* fname)
+{
+  static FCW* f; if (!f) f = new FCW();
+  f->ok_button->label(fl_ok);
+  f->cancel_button->label(fl_cancel);
+
+  if (pat && !*pat) pat = 0;
+  if (fname && *fname) {
+    f->input.value(fname);
+  } else if (f->browser.pattern != pat && (!pat || !f->browser.pattern ||
+					   strcmp(pat,f->browser.pattern))) {
+    // if pattern is different, remove name but leave old directory:
+    const char* p = f->input.value();
+    const char* q = filename_name(p);
+    f->input.value(p, q-p);
+  }
+  f->browser.pattern = pat;
+  f->normal_button->label(pat ? pat : "visible files");
+  f->browser.set(f->input.value());
+  f->input.position(10000, f->browser.dirend);
+
+  f->label(message);
+  f->hotspot(f);
+  f->show();
+  int ok = 0;
+  for (;;) {
+    Fl::wait();
+    Fl_Widget* o = Fl::readqueue();
+    if (o == f->ok_button) {ok = 1; break;}
+    else if (o == f->cancel_button || o == f) break;
+  }
+  f->hide();
+  f->browser.clear();
+
+  if (!ok) return 0;
+  const char* r = f->input.value();
+  const char* p;
+  for (p=r+f->browser.dirend; *p; p++)
+    if (*p=='*' || *p=='?' || *p=='[' || *p=='{') return 0;
+  return (char*)r;
+}
+
+// end of fl_file_chooser.C
diff --git a/src/fl_font.cxx b/src/fl_font.cxx
new file mode 100644
index 000000000..746f65547
--- /dev/null
+++ b/src/fl_font.cxx
@@ -0,0 +1,283 @@
+// fl_font.C
+
+// Select fonts from the fltk font table.
+
+#ifdef WIN32
+#include "fl_font_win32.C"
+#else
+
+#include 
+#include 
+#include 
+#include 
+#include "Fl_Font.H"
+
+#include 
+#include 
+#include 
+
+Fl_XFont::Fl_XFont(const char *name, int num) 
+  : number(num)
+{
+  font = XLoadQueryFont(fl_display, name);
+  if (!font) {
+    Fl::warning("bad font: %s", name);
+    font = XLoadQueryFont(fl_display, "fixed"); // if fixed fails we crash
+  }
+  XCharStruct *p = font->per_char;
+  if (!p) {
+    free_this = per_char = 0;
+  } else if (font->min_char_or_byte2>0x20 || font->max_char_or_byte2<0xff) {
+    // fill in short fonts so fl_width does not crash:
+    XCharStruct *q = free_this = new XCharStruct[0xff-0x20+1];
+    per_char = q - 0x20;
+    unsigned int i = 0x20;
+    for (; imin_char_or_byte2; i++, q++)
+      q->width = font->min_bounds.width;
+    for (; i<=font->max_char_or_byte2; i++)
+      *q++ = *p++;
+    for (; i<=0xff; i++)
+      q->width = font->min_bounds.width;
+  } else {
+    free_this = 0;
+    per_char = p - font->min_char_or_byte2;
+  }
+#if HAVE_GL
+  listbase = 0;
+#endif
+}
+
+Fl_XFont *fl_current_xfont;
+Fl_XFont *fl_fixed_xfont;
+
+Fl_XFont::~Fl_XFont() {
+#if HAVE_GL
+// Delete list created by gl_draw().  This is not done by this code
+// as it will link in GL unnecessarily.  There should be some kind
+// of "free" routine pointer, or a subclass?
+// if (listbase) {
+//  int base = font->min_char_or_byte2;
+//  int size = font->max_char_or_byte2-base+1;
+//  int base = 0; int size = 256;
+//  glDeleteLists(listbase+base,size);
+// }
+#endif
+  if (this == fl_current_xfont) fl_current_xfont = 0;
+  delete[] free_this;
+  XFreeFont(fl_display, font);
+}
+
+////////////////////////////////////////////////////////////////
+
+// WARNING: if you add to this table, you must redefine FL_FREE_FONT
+// in Enumerations.H & recompile!!
+static Fl_Fontdesc built_in_table[] = {
+{"-*-helvetica-medium-r-normal--*"},
+{"-*-helvetica-bold-r-normal--*"},
+{"-*-helvetica-medium-o-normal--*"},
+{"-*-helvetica-bold-o-normal--*"},
+{"-*-courier-medium-r-normal--*"},
+{"-*-courier-bold-r-normal--*"},
+{"-*-courier-medium-o-normal--*"},
+{"-*-courier-bold-o-normal--*"},
+{"-*-times-medium-r-normal--*"},
+{"-*-times-bold-r-normal--*"},
+{"-*-times-medium-i-normal--*"},
+{"-*-times-bold-i-normal--*"},
+{"-*-symbol-*"},
+{"-*-lucidatypewriter-medium-r-normal-sans-*"},
+{"-*-lucidatypewriter-bold-r-normal-sans-*"},
+{"-*-*zapf dingbats-*"}
+};
+
+Fl_Fontdesc *fl_fonts = built_in_table;
+
+#define MAXSIZE 32767
+
+// return dash number N, or pointer to ending null if none:
+const char* fl_font_word(const char *p, int n) {
+  while (*p) {if (*p=='-') {if (!--n) break;} p++;}
+  return p;
+}
+
+// return a pointer to a number we think is "point size":
+char *fl_find_fontsize(char* name) {
+  char *c = name;
+  // for standard x font names, try after 7th dash:
+  if (*c == '-') {
+    c = (char*)fl_font_word(c,7);
+    if (*c++ && isdigit(*c)) return c;
+    return 0; // malformed x font name?
+  }
+  char *r = 0;
+  // find last set of digits:
+  for (c++; *c; c++)
+    if (isdigit(*c) && !isdigit(*(c-1))) r = c;
+  return r;
+}
+
+const char* fl_encoding = "iso8859-1";
+
+// return true if this matches fl_encoding:
+int fl_correct_encoding(const char* name) {
+  if (*name != '-') return 0;
+  const char* c = fl_font_word(name,13);
+  return (*c++ && !strcmp(c,fl_encoding));
+}
+
+// locate or create an Fl_XFont for a given Fl_Fontdesc and size:
+static Fl_XFont *find(int fnum, int size) {
+  Fl_Fontdesc *s = fl_fonts+fnum;
+  if (!s->name) s = fl_fonts; // use font 0 if still undefined
+  Fl_XFont *f;
+  for (f = s->first; f; f = f->next)
+    if (f->minsize <= size && f->maxsize >= size) return f;
+  fl_open_display();
+  if (!s->xlist) {
+    s->xlist = XListFonts(fl_display, s->name, 100, &(s->n));
+    if (!s->xlist) {	// use fixed if no matching font...
+      if (!fl_fixed_xfont) {
+	fl_fixed_xfont = new Fl_XFont("fixed",fnum);
+	fl_fixed_xfont->minsize = 0;
+	fl_fixed_xfont->maxsize = 32767;
+      }
+      s->first = fl_fixed_xfont;
+      return fl_fixed_xfont;
+    }
+  }
+  // search for largest <= font size:
+  char *name = s->xlist[0]; int ptsize = 0;	// best one found so far
+  int matchedlength = 32767;
+  char namebuffer[1024];	// holds scalable font name
+  int found_encoding = 0;
+  int m = s->n; if (m<0) m = -m;
+  for (int n=0; n < m; n++) {
+
+    char *thisname = s->xlist[n];
+    if (fl_correct_encoding(thisname)) {
+      if (!found_encoding) ptsize = 0; // force it to choose this
+      found_encoding = 1;
+    } else {
+      if (found_encoding) continue;
+    }
+    char *c = fl_find_fontsize(thisname);
+    int thissize = c ? atoi(c) : MAXSIZE;
+    int thislength = strlen(thisname);
+    if (thissize == size && thislength < matchedlength) {
+      // exact match, use it:
+      name = thisname;
+      ptsize = size;
+      matchedlength = thislength;
+    } else if (!thissize && ptsize!=size) {
+      // whoa!  A scalable font!  Use unless exact match found:
+      int l = c-thisname;
+      memcpy(namebuffer,thisname,l);
+#if 1 // this works if you don't want stdio
+      if (size>=100) namebuffer[l++] = size/100+'0';
+      if (size>=10) namebuffer[l++] = (size/10)%10+'0';
+      namebuffer[l++] = (size%10)+'0';
+#else
+      //for some reason, sprintf fails to return the right value under Solaris.
+      l += sprintf(namebuffer+l,"%d",size);
+#endif
+      while (*c == '0') c++;
+      strcpy(namebuffer+l,c);
+      name = namebuffer;
+      ptsize = size;
+    } else if (!ptsize ||	// no fonts yet
+	       thissize < ptsize && ptsize > size || // current font too big
+	       thissize > ptsize && thissize <= size // current too small
+      ) {
+      name = thisname; ptsize = thissize;
+      matchedlength = thislength;
+    }
+  }
+
+  if (ptsize != size) { // see if we already found this unscalable font:
+    for (f = s->first; f; f = f->next) {
+      if (f->minsize <= ptsize && f->maxsize >= ptsize) {
+	if (f->minsize > size) f->minsize = size;
+	if (f->maxsize < size) f->maxsize = size;
+	return f;
+      }
+    }
+  }
+
+  // okay, we definately have some name, make the font:
+  f = new Fl_XFont(name,fnum);
+  if (ptsize < size) {f->minsize = ptsize; f->maxsize = size;}
+  else {f->minsize = size; f->maxsize = ptsize;}
+  f->next = s->first;
+  s->first = f;
+  return f;
+
+}
+
+////////////////////////////////////////////////////////////////
+// Public interface:
+
+int fl_font_;
+int fl_size_;
+static GC font_gc;
+
+void fl_font(int fnum, int size) {
+  if (fnum == fl_font_ && size == fl_size_) return;
+  fl_font_ = fnum; fl_size_ = size;
+  Fl_XFont *f = find(fnum, size);
+  if (f != fl_current_xfont) {fl_current_xfont = f; font_gc = 0;}
+}
+
+void fl_font(int fnum, int size, Fl_Font default_font, int default_size) {
+  if (fnum<4) fnum |= default_font;
+  fl_font(fnum, size + default_size);
+}
+
+int fl_height() {
+  return (fl_current_xfont->font->ascent + fl_current_xfont->font->descent);
+}
+
+int fl_descent() {
+  return fl_current_xfont->font->descent;
+}
+
+double fl_width(const char *c) {
+  XCharStruct *p = fl_current_xfont->per_char;
+  if (!p) return strlen(c)*fl_current_xfont->font->min_bounds.width;
+  int w = 0;
+  while (*c)
+    if (*c >= ' ')
+      w += p[(uchar)(*c++)].width;
+    else
+      c ++;
+
+  return w;
+}
+
+double fl_width(const char *c, int n) {
+  XCharStruct *p = fl_current_xfont->per_char;
+  if (!p) return n*fl_current_xfont->font->min_bounds.width;
+  int w = 0;
+  while (n--) w += p[(uchar)(*c++)].width;
+  return w;
+}
+
+double fl_width(uchar c) {
+  XCharStruct *p = fl_current_xfont->per_char;
+  if (!p) return fl_current_xfont->font->min_bounds.width;
+  return p[c].width;
+}
+
+void fl_draw(const char *str, int n, int x, int y) {
+  if (font_gc != fl_gc) {
+    font_gc = fl_gc;
+    XSetFont(fl_display, fl_gc, fl_current_xfont->font->fid);
+  }
+  XDrawString(fl_display, fl_window, fl_gc, x, y, str, n);
+}
+
+void fl_draw(const char *str, int x, int y) {
+  fl_draw(str, strlen(str), x, y);
+}
+
+#endif
+// end of fl_font.C
diff --git a/src/fl_font_win32.cxx b/src/fl_font_win32.cxx
new file mode 100644
index 000000000..0f4e20e77
--- /dev/null
+++ b/src/fl_font_win32.cxx
@@ -0,0 +1,159 @@
+// fl_font_win32.C
+
+#include 
+#include 
+#include 
+#include 
+#include "Fl_Font.H"
+
+#include 
+#include 
+#include 
+
+Fl_XFont::Fl_XFont(const char *name, int size, int num) {
+  int weight = FW_NORMAL;
+  int italic = 0;
+  switch (*name++) {
+  case 'I': italic = 1; break;
+  case 'P': italic = 1;
+  case 'B': weight = FW_BOLD; break;
+  case ' ': break;
+  default: name--;
+  }
+  fid = CreateFont(
+    -size, // negative makes it use "char size"
+    0,	            // logical average character width 
+    0,	            // angle of escapement 
+    0,	            // base-line orientation angle 
+    weight,
+    italic,
+    FALSE,	        // underline attribute flag 
+    FALSE,	        // strikeout attribute flag 
+    DEFAULT_CHARSET,    // character set identifier 
+    OUT_DEFAULT_PRECIS,	// output precision 
+    CLIP_DEFAULT_PRECIS,// clipping precision 
+    DEFAULT_QUALITY,	// output quality 
+    DEFAULT_PITCH,	// pitch and family 
+    name	        // pointer to typeface name string 
+    );
+  if (!fl_gc) fl_gc = fl_GetDC(0);
+  SelectObject(fl_gc, fid);
+  GetTextMetrics(fl_gc, &metr);
+//  BOOL ret = GetCharWidthFloat(fl_gc, metr.tmFirstChar, metr.tmLastChar, font->width+metr.tmFirstChar);
+// ...would be the right call, but is not implemented into Window95! (WinNT?)
+  GetCharWidth(fl_gc, 0, 255, width);
+#if HAVE_GL
+  listbase = 0;
+#endif
+  number = num;
+  minsize = maxsize = size;
+}
+
+Fl_XFont *fl_current_xfont;
+
+Fl_XFont::~Fl_XFont() {
+#if HAVE_GL
+// Delete list created by gl_draw().  This is not done by this code
+// as it will link in GL unnecessarily.  There should be some kind
+// of "free" routine pointer, or a subclass?
+// if (listbase) {
+//  int base = font->min_char_or_byte2;
+//  int size = font->max_char_or_byte2-base+1;
+//  int base = 0; int size = 256;
+//  glDeleteLists(listbase+base,size);
+// }
+#endif
+  if (this == fl_current_xfont) fl_current_xfont = 0;
+  DeleteObject(fid);
+}
+
+////////////////////////////////////////////////////////////////
+
+// WARNING: if you add to this table, you must redefine FL_FREE_FONT
+// in Enumerations.H & recompile!!
+static Fl_Fontdesc built_in_table[] = {
+{" Arial"},
+{"BArial"},
+{"IArial"},
+{"PArial"},
+{" Courier New"},
+{"BCourier New"},
+{"ICourier New"},
+{"PCourier New"},
+{" Times New Roman"},
+{"BTimes New Roman"},
+{"ITimes New Roman"},
+{"PTimes New Roman"},
+{" Symbol"},
+{" Terminal"},
+{"BTerminal"},
+{" Wingdings"},
+};
+
+Fl_Fontdesc *fl_fonts = built_in_table;
+
+static Fl_XFont *find(int fnum, int size) {
+  Fl_Fontdesc *s = fl_fonts+fnum;
+  if (!s->name) s = fl_fonts; // use 0 if fnum undefined
+  Fl_XFont *f;
+  for (f = s->first; f; f = f->next)
+    if (f->minsize <= size && f->maxsize >= size) return f;
+  f = new Fl_XFont(s->name, size, fnum);
+  f->next = s->first;
+  s->first = f;
+  return f;
+}
+
+////////////////////////////////////////////////////////////////
+// Public interface:
+
+int fl_font_;
+int fl_size_;
+static HDC font_gc;
+
+void fl_font(int fnum, int size) {
+  if (fnum == fl_font_ && size == fl_size_) return;
+  fl_font_ = fnum; fl_size_ = size;
+  fl_current_xfont = find(fnum, size);
+}
+
+void fl_font(int fnum, int size, Fl_Font default_font, int default_size) {
+  if (fnum<4) fnum |= default_font;
+  fl_font(fnum, size + default_size);
+}
+
+int fl_height() {
+  return (fl_current_xfont->metr.tmAscent + fl_current_xfont->metr.tmDescent);
+}
+
+int fl_descent() {
+  return fl_current_xfont->metr.tmDescent;
+}
+
+double fl_width(const char *c) {
+  double w = 0.0;
+  while (*c) w += fl_current_xfont->width[uchar(*c++)];
+  return w;
+}
+
+double fl_width(const char *c, int n) {
+  double w = 0.0;
+  while (n--) w += fl_current_xfont->width[uchar(*c++)];
+  return w;
+}
+
+double fl_width(uchar c) {
+  return fl_current_xfont->width[c];
+}
+
+void fl_draw(const char *str, int n, int x, int y) {
+  SetTextColor(fl_gc, fl_RGB());
+  SelectObject(fl_gc, fl_current_xfont->fid);
+  TextOut(fl_gc, x, y, str, n);
+}
+
+void fl_draw(const char *str, int x, int y) {
+  fl_draw(str, strlen(str), x, y);
+}
+
+// end of fl_font_win32.C
diff --git a/src/fl_labeltype.cxx b/src/fl_labeltype.cxx
new file mode 100644
index 000000000..8b7755eaf
--- /dev/null
+++ b/src/fl_labeltype.cxx
@@ -0,0 +1,104 @@
+// fl_labeltype.C
+
+// Drawing code for the (one) common label types.
+// Other label types (symbols) are in their own source files
+// to avoid linking if not used.
+
+#include 
+#include 
+#include 
+#include 
+
+void
+fl_no_label(const Fl_Label*,int,int,int,int,Fl_Align) {}
+
+void
+fl_normal_label(const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align)
+{
+  fl_font(o->font, o->size);
+  fl_color((Fl_Color)o->color);
+  fl_draw(o->value, X, Y, W, H, align);
+}
+
+void
+fl_normal_measure(const Fl_Label* o, int& W, int& H) {
+  fl_font(o->font, o->size);
+  fl_measure(o->value, W, H);
+}
+
+#define MAX_LABELTYPE 16
+
+static Fl_Label_Draw_F* table[MAX_LABELTYPE] = {
+  fl_normal_label,
+  fl_no_label,
+  fl_normal_label,	// _FL_SYMBOL_LABEL,
+  fl_normal_label,	// _FL_SHADOW_LABEL,
+  fl_normal_label,	// _FL_ENGRAVED_LABEL,
+  fl_normal_label,	// _FL_EMBOSSED_LABEL,
+  fl_no_label,		// _FL_BITMAP_LABEL,
+  fl_no_label,		// _FL_PIXMAP_LABEL,
+  fl_no_label,		// _FL_IMAGE_LABEL,
+  // FL_FREE_LABELTYPE+n:
+  fl_no_label, fl_no_label, fl_no_label,
+  fl_no_label, fl_no_label, fl_no_label, fl_no_label,
+};
+
+static Fl_Label_Measure_F* measure[MAX_LABELTYPE];
+
+void Fl::set_labeltype(Fl_Labeltype t,Fl_Label_Draw_F* f,Fl_Label_Measure_F*m) 
+{
+  table[t] = f; measure[t] = m;
+}
+
+////////////////////////////////////////////////////////////////
+
+// draw label with arbitrary alignment in arbitrary box:
+void Fl_Label::draw(int X, int Y, int W, int H, Fl_Align align) const {
+  if (!value) return;
+  table[type](this, X, Y, W, H, align);
+}
+
+void Fl_Label::measure(int& W, int& H) const {
+  if (!value) return;
+  Fl_Label_Measure_F* f = ::measure[type]; if (!f) f = fl_normal_measure;
+  f(this, W, H);
+}
+
+// The normal call for a draw() method:
+void Fl_Widget::draw_label() const {
+  int X = x_+Fl::box_dx(box());
+  int W = w_-Fl::box_dw(box());
+  if (W > 11 && align()&(FL_ALIGN_LEFT|FL_ALIGN_RIGHT)) {X += 3; W -= 6;}
+  draw_label(X, y_+Fl::box_dy(box()), W, h_-Fl::box_dh(box()));
+}
+
+// draw() can use this instead to change the bounding box:
+void Fl_Widget::draw_label(int X, int Y, int W, int H) const {
+  // quit if we are not drawing a label inside the widget:
+  if ((align()&15) && !(align() & FL_ALIGN_INSIDE)) return;
+  draw_label(X,Y,W,H,align());
+}
+
+Fl_Font Fl_Widget::default_font_;
+int Fl_Widget::default_size_;
+
+// Anybody can call this to force the label to draw anywhere:
+extern char fl_draw_shortcut;
+void Fl_Widget::draw_label(int X, int Y, int W, int H, Fl_Align a) const {
+  if (flags()&SHORTCUT_LABEL) fl_draw_shortcut = 1;
+  Fl_Label l1 = label_;
+  if (!active_r()) l1.color |= 8;
+  if (l1.font<4) l1.font |= default_font_;
+  l1.size += default_size_;
+  l1.draw(X,Y,W,H,a);
+  fl_draw_shortcut = 0;
+}
+
+// include these vars here so they can be referenced without including
+// Fl_Input_ code:
+#include 
+
+Fl_Boxtype Fl_Input_::default_box_ = FL_DOWN_BOX;
+Fl_Font Fl_Input_::default_font_;
+int Fl_Input_::default_size_;
+
diff --git a/src/fl_oval_box.cxx b/src/fl_oval_box.cxx
new file mode 100644
index 000000000..8e5c1c564
--- /dev/null
+++ b/src/fl_oval_box.cxx
@@ -0,0 +1,38 @@
+/*	fl_oval_box.C
+
+	Less-used box types are in seperate files so they are not linked
+	in if not used.
+
+*/
+
+#include 
+#include 
+
+static void fl_oval_flat_box(int x, int y, int w, int h, Fl_Color c) {
+  fl_color(c);
+  fl_pie(x, y, w, h, 0, 360);
+}
+
+static void fl_oval_frame(int x, int y, int w, int h, Fl_Color c) {
+  fl_color(c);
+  fl_arc(x, y, w, h, 0, 360);
+}
+
+static void fl_oval_box(int x, int y, int w, int h, Fl_Color c) {
+  fl_oval_flat_box(x,y,w-1,h-1,c);
+  fl_oval_frame(x,y,w,h,FL_BLACK);
+}
+
+static void fl_oval_shadow_box(int x, int y, int w, int h, Fl_Color c) {
+  fl_oval_flat_box(x+3,y+3,w,h,FL_DARK3);
+  fl_oval_box(x,y,w,h,c);
+}
+
+extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*);
+Fl_Boxtype define_FL_OVAL_BOX() {
+  fl_internal_boxtype(_FL_OSHADOW_BOX,fl_oval_shadow_box);
+  fl_internal_boxtype(_FL_OVAL_FRAME,fl_oval_frame);
+  fl_internal_boxtype(_FL_OFLAT_BOX,fl_oval_flat_box);
+  fl_internal_boxtype(_FL_OVAL_BOX,fl_oval_box);
+  return _FL_OVAL_BOX;
+}
diff --git a/src/fl_overlay.cxx b/src/fl_overlay.cxx
new file mode 100644
index 000000000..ed44ec9c6
--- /dev/null
+++ b/src/fl_overlay.cxx
@@ -0,0 +1,39 @@
+// fl_overlay.C
+
+// Extremely limited "overlay" support.  You can use this to drag out
+// a rectangle in response to mouse events.  It is your responsibility
+// to erase the overlay before drawing anything that might intersect
+// it.
+
+#include 
+#include 
+
+static int px,py,pw,ph;
+
+static void draw_current_rect() {
+#ifdef WIN32
+  int old = SetROP2(fl_gc, R2_NOT);
+  fl_rect(px, py, pw, ph);
+  SetROP2(fl_gc, old);
+#else
+  XSetFunction(fl_display, fl_gc, GXxor);
+  XSetForeground(fl_display, fl_gc, 0xffffffff);
+  XDrawRectangle(fl_display, fl_window, fl_gc, px, py, pw, ph);
+  XSetFunction(fl_display, fl_gc, GXcopy);
+#endif
+}
+
+void fl_overlay_clear() {
+  if (pw > 0) {draw_current_rect(); pw = 0;}
+}
+
+void fl_overlay_rect(int x, int y, int w, int h) {
+  if (w < 0) {x += w; w = -w;} else if (!w) w = 1;
+  if (h < 0) {y += h; h = -h;} else if (!h) h = 1;
+  if (pw > 0) {
+    if (x==px && y==py && w==pw && h==ph) return;
+    draw_current_rect();
+  }
+  px = x; py = y; pw = w; ph = h;
+  draw_current_rect();
+}
diff --git a/src/fl_overlay_visual.cxx b/src/fl_overlay_visual.cxx
new file mode 100644
index 000000000..a176bf69c
--- /dev/null
+++ b/src/fl_overlay_visual.cxx
@@ -0,0 +1,76 @@
+// Stupid X tricks
+
+// Return an overlay visual, if any.  Also allocate a colormap and
+// record the depth for fl_color() to use.
+// Another disgusting X interface, based on code extracted and
+// purified with great difficulty from XLayerUtil.C:
+
+#include 
+#if HAVE_OVERLAY
+#include 
+#include 
+
+// SERVER_OVERLAY_VISUALS property element:
+struct OverlayInfo {
+  long overlay_visual;
+  long transparent_type;
+  long value;
+  long layer;
+};
+
+extern Colormap fl_overlay_colormap;
+extern XVisualInfo* fl_overlay_visual;
+extern ulong fl_transparent_pixel;
+
+XVisualInfo *fl_find_overlay_visual() {
+  static char beenhere;
+  if (beenhere) return fl_overlay_visual;
+  beenhere = 1;
+
+  fl_open_display();
+  Atom overlayVisualsAtom =
+    XInternAtom(fl_display,"SERVER_OVERLAY_VISUALS",1);
+  if (!overlayVisualsAtom) return 0;
+  OverlayInfo *overlayInfo;
+  ulong sizeData, bytesLeft;
+  Atom actualType;
+  int actualFormat;
+  if (XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
+			 overlayVisualsAtom, 0L, 10000L, False,
+			 overlayVisualsAtom, &actualType, &actualFormat,
+			 &sizeData, &bytesLeft,
+			 (unsigned char **) &overlayInfo)) return 0;
+
+  if (actualType == overlayVisualsAtom && actualFormat == 32) {
+    int n = int(sizeData/4);
+    XVisualInfo* v = 0;
+    // find the greatest depth that has a transparent pixel:
+    for (int i = 0; i < n; i++) {
+      if (overlayInfo[i].transparent_type != 1) continue;
+      if (overlayInfo[i].layer <= 0) continue;
+      XVisualInfo templt;
+      templt.visualid = overlayInfo[i].overlay_visual;
+      int num;
+      XVisualInfo *v1=XGetVisualInfo(fl_display, VisualIDMask, &templt, &num);
+      if (v1->screen == fl_screen && 
+	  !v1->red_mask && (!v || v1->depth >= v->depth && v1->depth <= 8)) {
+	if (v) XFree((char*)v);
+	v = v1;
+	fl_transparent_pixel = overlayInfo[i].value;
+      } else {
+	XFree((char*)v1);
+      }
+    }
+    if (v) {
+      fl_overlay_visual = v;
+      fl_overlay_colormap = 
+	XCreateColormap(fl_display, RootWindow(fl_display, fl_screen),
+			v->visual, AllocNone);
+    }
+  }
+  XFree((char*)overlayInfo);
+  //  printf("overlay visual %d selected\n", fl_overlay_visual->visualid);
+  return fl_overlay_visual;
+}
+
+#endif
diff --git a/src/fl_rect.cxx b/src/fl_rect.cxx
new file mode 100644
index 000000000..2e294bd96
--- /dev/null
+++ b/src/fl_rect.cxx
@@ -0,0 +1,380 @@
+// fl_rect.C
+
+// These routines from fl_draw.H are used by the standard boxtypes
+// and thus are always linked into an fltk program.
+
+// Also all fl_clip routines, since they are always linked in so
+// that minimal update works.
+
+#include 
+#include 
+#include 
+
+void fl_rect(int x, int y, int w, int h) {
+  if (w<=0 || h<=0) return;
+#ifdef WIN32
+  MoveToEx(fl_gc, x, y, 0L); 
+  LineTo(fl_gc, x+w-1, y);
+  LineTo(fl_gc, x+w-1, y+h-1);
+  LineTo(fl_gc, x, y+h-1);
+  LineTo(fl_gc, x, y);
+#else
+  XDrawRectangle(fl_display, fl_window, fl_gc, x, y, w-1, h-1);
+#endif
+}
+
+void fl_rectf(int x, int y, int w, int h) {
+  if (w<=0 || h<=0) return;
+#ifdef WIN32
+  RECT rect;
+  rect.left = x; rect.top = y;  
+  rect.right = x + w; rect.bottom = y + h;
+  FillRect(fl_gc, &rect, fl_brush());
+#else
+  if (w && h) XFillRectangle(fl_display, fl_window, fl_gc, x, y, w, h);
+#endif
+}
+
+void fl_xyline(int x, int y, int x1) {
+#ifdef WIN32
+  MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x1+1, y);
+#else
+  XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y);
+#endif
+}
+
+void fl_xyline(int x, int y, int x1, int y2) {
+#ifdef WIN32
+  if (y2 < y) y2--;
+  MoveToEx(fl_gc, x, y, 0L); 
+  LineTo(fl_gc, x1, y);
+  LineTo(fl_gc, x1, y2);
+#else
+  XPoint p[3];
+  p[0].x = x;  p[0].y = p[1].y = y;
+  p[1].x = p[2].x = x1; p[2].y = y2;
+  XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0);
+#endif
+}
+
+void fl_xyline(int x, int y, int x1, int y2, int x3) {
+#ifdef WIN32
+  MoveToEx(fl_gc, x, y, 0L); 
+  LineTo(fl_gc, x1, y);
+  LineTo(fl_gc, x1, y2);
+  LineTo(fl_gc, x3, y2);
+#else
+  XPoint p[4];
+  p[0].x = x;  p[0].y = p[1].y = y;
+  p[1].x = p[2].x = x1; p[2].y = p[3].y = y2;
+  p[3].x = x3;
+  XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
+#endif
+}
+
+void fl_yxline(int x, int y, int y1) {
+#ifdef WIN32
+  if (y1 < y) y1--;
+  MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x, y1);
+#else
+  XDrawLine(fl_display, fl_window, fl_gc, x, y, x, y1);
+#endif
+}
+
+void fl_yxline(int x, int y, int y1, int x2) {
+#ifdef WIN32
+  if (x2 > x) x2++;
+  MoveToEx(fl_gc, x, y, 0L); 
+  LineTo(fl_gc, x, y1);
+  LineTo(fl_gc, x2, y1);
+#else
+  XPoint p[3];
+  p[0].x = p[1].x = x;  p[0].y = y;
+  p[1].y = p[2].y = y1; p[2].x = x2;
+  XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0);
+#endif
+}
+
+void fl_yxline(int x, int y, int y1, int x2, int y3) {
+#ifdef WIN32
+  MoveToEx(fl_gc, x, y, 0L); 
+  LineTo(fl_gc, x, y1);
+  LineTo(fl_gc, x2, y1);
+  LineTo(fl_gc, x2, y3);
+#else
+  XPoint p[4];
+  p[0].x = p[1].x = x;  p[0].y = y;
+  p[1].y = p[2].y = y1; p[2].x = p[3].x = x2;
+  p[3].y = y3;
+  XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
+#endif
+}
+
+void fl_line(int x, int y, int x1, int y1) {
+#ifdef WIN32
+  MoveToEx(fl_gc, x, y, 0L); 
+  LineTo(fl_gc, x1, y1);
+#else
+  XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y1);
+#endif
+}
+
+void fl_line(int x, int y, int x1, int y1, int x2, int y2) {
+#ifdef WIN32
+  MoveToEx(fl_gc, x, y, 0L); 
+  LineTo(fl_gc, x1, y1);
+  LineTo(fl_gc, x2, y2);
+#else
+  XPoint p[3];
+  p[0].x = x;  p[0].y = y;
+  p[1].x = x1; p[1].y = y1;
+  p[2].x = x2; p[2].y = y2;
+  XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0);
+#endif
+}
+
+void fl_loop(int x, int y, int x1, int y1, int x2, int y2) {
+#ifdef WIN32
+  MoveToEx(fl_gc, x, y, 0L); 
+  LineTo(fl_gc, x1, y1);
+  LineTo(fl_gc, x2, y2);
+  LineTo(fl_gc, x, y);
+#else
+  XPoint p[4];
+  p[0].x = x;  p[0].y = y;
+  p[1].x = x1; p[1].y = y1;
+  p[2].x = x2; p[2].y = y2;
+  p[3].x = x;  p[3].y = y;
+  XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
+#endif
+}
+
+void fl_loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
+#ifdef WIN32
+  MoveToEx(fl_gc, x, y, 0L); 
+  LineTo(fl_gc, x1, y1);
+  LineTo(fl_gc, x2, y2);
+  LineTo(fl_gc, x3, y3);
+  LineTo(fl_gc, x, y);
+#else
+  XPoint p[5];
+  p[0].x = x;  p[0].y = y;
+  p[1].x = x1; p[1].y = y1;
+  p[2].x = x2; p[2].y = y2;
+  p[3].x = x3; p[3].y = y3;
+  p[4].x = x;  p[4].y = y;
+  XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0);
+#endif
+}
+
+void fl_polygon(int x, int y, int x1, int y1, int x2, int y2) {
+  XPoint p[4];
+  p[0].x = x;  p[0].y = y;
+  p[1].x = x1; p[1].y = y1;
+  p[2].x = x2; p[2].y = y2;
+#ifdef WIN32
+  SelectObject(fl_gc, fl_brush());
+  Polygon(fl_gc, p, 3);
+#else
+  p[3].x = x;  p[3].y = y;
+  XFillPolygon(fl_display, fl_window, fl_gc, p, 3, Convex, 0);
+  XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
+#endif
+}
+
+void fl_polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
+  XPoint p[5];
+  p[0].x = x;  p[0].y = y;
+  p[1].x = x1; p[1].y = y1;
+  p[2].x = x2; p[2].y = y2;
+  p[3].x = x3; p[3].y = y3;
+#ifdef WIN32
+  SelectObject(fl_gc, fl_brush());
+  Polygon(fl_gc, p, 4);
+#else
+  p[4].x = x;  p[4].y = y;
+  XFillPolygon(fl_display, fl_window, fl_gc, p, 4, Convex, 0);
+  XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0);
+#endif
+}
+
+void fl_point(int x, int y) {
+#ifdef WIN32
+  SetPixel(fl_gc, x, y, fl_RGB());
+#else
+  XDrawPoint(fl_display, fl_window, fl_gc, x, y);
+#endif
+}
+
+////////////////////////////////////////////////////////////////
+
+#ifdef WIN32
+
+static struct rect {int notnull, x, y, r, b;} rstack[10];
+static int rstackptr;
+int fl_clip_state_number; // used by gl_begin.C to update GL clip
+extern char fl_direct_paint; // in Fl_win32.C
+
+void fl_clip(int x, int y, int w, int h) {
+  fl_clip_state_number++;
+  int r = x+w;
+  int b = y+h;
+  rect& current = rstack[rstackptr];
+  if (current.notnull) {
+    if (current.x > x) x = current.x;
+    if (current.y > y) y = current.y;
+    if (current.r < r) r = current.r;
+    if (current.b < b) b = current.b;
+  }
+  rect& newrect = rstack[++rstackptr];
+  newrect.notnull = 1;
+  newrect.x = x;
+  newrect.y = y;
+  newrect.r = r;
+  newrect.b = b;
+  if (rstackptr == 1 && fl_direct_paint) return;
+  HRGN R = CreateRectRgn(x,y,r,b);
+  SelectClipRgn(fl_gc, R);
+  DeleteObject(R);
+}
+
+void fl_push_no_clip() {
+  fl_clip_state_number++;
+  if (rstack[rstackptr].notnull) SelectClipRgn(fl_gc, 0);
+  rstack[++rstackptr].notnull = 0;
+}
+
+void fl_pop_clip() {
+  fl_clip_state_number++;
+  rect& r = rstack[--rstackptr];
+  if (r.notnull) {
+    HRGN R = CreateRectRgn(r.x, r.y, r.r, r.b);
+    SelectClipRgn(fl_gc, R);
+    DeleteObject(R);
+  } else {
+    SelectClipRgn(fl_gc, 0);
+  }
+}
+
+// does this rectangle intersect current clip?
+int fl_not_clipped(int x, int y, int w, int h) {
+  rect& r = rstack[rstackptr];
+  if (!r.notnull) return 2;
+  return (x < r.r && x+w > r.x && y < r.b && y+h > r.y);
+}
+
+// return rectangle surrounding intersection of this rectangle and clip:
+int fl_clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){
+  X = x; Y = y; W = w; H = h;
+  rect& r = rstack[rstackptr];
+  if (!r.notnull) return 0;
+  int R = x+w;
+  int B = y+h;
+  int ret = 0;
+  if (r.x > x) {X = r.x; ret = 1;}
+  if (r.y > y) {Y = r.y; ret = 1;}
+  if (r.r < R) {R = r.r; ret = 1;}
+  if (r.b < B) {B = r.b; ret = 1;}
+  if (B <= Y || R <= X) {W = H = 0; return 2;}
+  W = R-X;
+  H = B-Y;
+  return ret;
+}
+
+#else
+
+// Missing X call: (is this the fastest way to init a 1-rectangle region?)
+Region XRectangleRegion(int x, int y, int w, int h) {
+  XRectangle R;
+  R.x = x; R.y = y; R.width = w; R.height = h;
+  Region r = XCreateRegion();
+  XUnionRectWithRegion(&R, r, r);
+  return r;
+}
+
+static Region rstack[10];
+static int rstackptr;
+int fl_clip_state_number; // used by gl_begin.C to update GL clip
+
+// undo any clobbering of clip done by your program:
+void fl_restore_clip() {
+  fl_clip_state_number++;
+  Region r = rstack[rstackptr];
+  if (r) XSetRegion(fl_display, fl_gc, r);
+  else XSetClipMask(fl_display, fl_gc, 0);
+}
+
+// Replace the top of the clip stack:
+void fl_clip_region(Region r) {
+  Region oldr = rstack[rstackptr];
+  if (oldr) XDestroyRegion(oldr);
+  rstack[rstackptr] = r;
+  fl_restore_clip();
+}
+
+// Intersect & push a new clip rectangle:
+void fl_clip(int x, int y, int w, int h) {
+  Region r;
+  if (w > 0 && h > 0) {
+    r = XRectangleRegion(x,y,w,h);
+    Region current = rstack[rstackptr];
+    if (current) {
+      Region temp = XCreateRegion();
+      XIntersectRegion(current, r, temp);
+      XDestroyRegion(r);
+      r = temp;
+    }
+  } else { // make empty clip region:
+    r = XCreateRegion();
+  }
+  rstack[++rstackptr] = r;
+  fl_restore_clip();
+}
+
+// make there be no clip (used by fl_begin_offscreen() only!)
+void fl_push_no_clip() {
+  rstack[++rstackptr] = 0;
+  fl_restore_clip();
+}
+
+// pop back to previous clip:
+void fl_pop_clip() {
+  Region oldr = rstack[rstackptr--];
+  if (oldr) XDestroyRegion(oldr);
+  fl_restore_clip();
+}
+
+// does this rectangle intersect current clip?
+int fl_not_clipped(int x, int y, int w, int h) {
+  Region r = rstack[rstackptr];
+  return r ? XRectInRegion(r, x, y, w, h) : 1;
+}
+
+// return rectangle surrounding intersection of this rectangle and clip:
+int fl_clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){
+  X = x; Y = y; W = w; H = h;
+  Region r = rstack[rstackptr];
+  if (!r) return 0;
+  switch (XRectInRegion(r, x, y, w, h)) {
+  case 0: // completely outside
+    W = H = 0;
+    return 2;
+  case 1: // completely inside:
+    return 0;
+  default: // partial:
+    break;
+  }
+  Region rr = XRectangleRegion(x,y,w,h);
+  Region temp = XCreateRegion();
+  XIntersectRegion(r, rr, temp);
+  XRectangle rect;
+  XClipBox(temp, &rect);
+  X = rect.x; Y = rect.y; W = rect.width; H = rect.height;
+  XDestroyRegion(temp);
+  XDestroyRegion(rr);
+  return 1;
+}
+
+#endif
+
+// end of fl_rect.C
diff --git a/src/fl_round_box.cxx b/src/fl_round_box.cxx
new file mode 100644
index 000000000..c165e22ec
--- /dev/null
+++ b/src/fl_round_box.cxx
@@ -0,0 +1,94 @@
+/*	fl_round_box.C
+
+	Box drawing code for an obscure box type.
+	These box types are in seperate files so they are not linked
+	in if not used.
+
+	3/8/99: Complete rewrite to use XDrawArc
+*/
+
+#include 
+#include 
+
+// A compiler from a certain very large software company will not compile
+// the function pointer assignment due to the name conflict with fl_arc.
+// This function is to fix that:
+void fl_arc_i(int x,int y,int w,int h,double a1,double a2) {
+  fl_arc(x,y,w,h,a1,a2);
+}
+
+enum {UPPER_LEFT, LOWER_RIGHT, CLOSED, FILL};
+
+static void draw(int which, int x,int y,int w,int h, int inset, uchar color)
+{
+  if (inset*2 >= w) inset = (w-1)/2;
+  if (inset*2 >= h) inset = (h-1)/2;
+  x += inset;
+  y += inset;
+  w -= 2*inset;
+  h -= 2*inset;
+  int d = w <= h ? w : h;
+  if (d <= 1) return;
+  fl_color((Fl_Color)color);
+  void (*f)(int,int,int,int,double,double) =
+    (which==FILL) ? fl_pie : fl_arc_i;
+  if (which >= CLOSED) {
+    f(x+w-d, y, d, d, w<=h ? 0 : -90, w<=h ? 180 : 90);
+    f(x, y+h-d, d, d, w<=h ? 180 : 90, w<=h ? 360 : 270);
+  } else if (which == UPPER_LEFT) {
+    f(x+w-d, y, d, d, 45, w<=h ? 180 : 90);
+    f(x, y+h-d, d, d, w<=h ? 180 : 90, 225);
+  } else { // LOWER_RIGHT
+    f(x, y+h-d, d, d, 225, w<=h ? 360 : 270);
+    f(x+w-d, y, d, d, w<=h ? 360 : 270, 360+45);
+  }
+  if (which == FILL) {
+    if (w < h)
+      fl_rectf(x, y+d/2, w, h-(d&-2));
+    else if (w > h)
+      fl_rectf(x+d/2, y, w-(d&-2), h);
+  } else {
+    if (w < h) {
+      if (which != UPPER_LEFT) fl_yxline(x+w-1, y+d/2, y+h-d/2);
+      if (which != LOWER_RIGHT) fl_yxline(x, y+d/2, y+h-d/2);
+    } else if (w > h) {
+      if (which != UPPER_LEFT) fl_xyline(x+d/2, y+h-1, x+w-d/2);
+      if (which != LOWER_RIGHT) fl_xyline(x+d/2, y, x+w-d/2);
+    }
+  }
+}
+
+extern uchar* Fl_Gray_Ramp;
+
+static void fl_round_down_box(int x, int y, int w, int h, Fl_Color bgcolor) {
+  draw(FILL,	    x,   y, w,   h, 2, bgcolor);
+  draw(UPPER_LEFT,  x+1, y, w-2, h, 0, Fl_Gray_Ramp['N']);
+  draw(UPPER_LEFT,  x+1, y, w-2, h, 1, Fl_Gray_Ramp['H']);
+  draw(UPPER_LEFT,  x,   y, w,   h, 0, Fl_Gray_Ramp['N']);
+  draw(UPPER_LEFT,  x,   y, w,   h, 1, Fl_Gray_Ramp['H']);
+  draw(LOWER_RIGHT, x,   y, w,   h, 0, Fl_Gray_Ramp['S']);
+  draw(LOWER_RIGHT, x+1, y, w-2, h, 0, Fl_Gray_Ramp['U']);
+  draw(LOWER_RIGHT, x,   y, w,   h, 1, Fl_Gray_Ramp['U']);
+  draw(LOWER_RIGHT, x+1, y, w-2, h, 1, Fl_Gray_Ramp['W']);
+  draw(CLOSED,	    x,   y, w,   h, 2, Fl_Gray_Ramp['A']);
+}
+
+static void fl_round_up_box(int x, int y, int w, int h, Fl_Color bgcolor) {
+  draw(FILL,	    x,   y, w,   h, 2, bgcolor);
+  draw(LOWER_RIGHT, x+1, y, w-2, h, 0, Fl_Gray_Ramp['H']);
+  draw(LOWER_RIGHT, x+1, y, w-2, h, 1, Fl_Gray_Ramp['N']);
+  draw(LOWER_RIGHT, x,   y, w,   h, 1, Fl_Gray_Ramp['H']);
+  draw(LOWER_RIGHT, x,   y, w,   h, 2, Fl_Gray_Ramp['N']);
+  draw(UPPER_LEFT,  x,   y, w,   h, 2, Fl_Gray_Ramp['U']);
+  draw(UPPER_LEFT,  x+1, y, w-2, h, 1, Fl_Gray_Ramp['S']);
+  draw(UPPER_LEFT,  x,   y, w,   h, 1, Fl_Gray_Ramp['W']);
+  draw(UPPER_LEFT,  x+1, y, w-2, h, 0, Fl_Gray_Ramp['U']);
+  draw(CLOSED,	    x,   y, w,   h, 0, Fl_Gray_Ramp['A']);
+}
+
+extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*);
+Fl_Boxtype define_FL_ROUND_UP_BOX() {
+  fl_internal_boxtype(_FL_ROUND_DOWN_BOX, fl_round_down_box);
+  fl_internal_boxtype(_FL_ROUND_UP_BOX, fl_round_up_box);
+  return _FL_ROUND_UP_BOX;
+}
diff --git a/src/fl_rounded_box.cxx b/src/fl_rounded_box.cxx
new file mode 100644
index 000000000..f670726c1
--- /dev/null
+++ b/src/fl_rounded_box.cxx
@@ -0,0 +1,75 @@
+/*	fl_rounded_box.C
+
+	Less-used box types are in seperate files so they are not linked
+	in if not used.
+
+*/
+
+#include 
+#include 
+
+#define RN	5
+#define RS	15
+#define BW	3
+
+static double offset[RN] = { 0.0, 0.07612, 0.29289, 0.61732, 1.0};
+
+static void rbox(int fill, int x, int y, int w, int h) {
+  int i;
+  int rsx ,rsy, rs;
+  rsx = w*2/5; rsy = h*2/5;
+  if (rsx > rsy) rs = rsy; else  rs = rsx;
+  if (rs > RS) rs = RS;
+  rsx = rs; rsy = rs;
+
+  if (fill) fl_begin_polygon(); else fl_begin_loop();
+  for (i=0; i
+
+// scroll a rectangle and redraw the newly exposed portions:
+void fl_scroll(int X, int Y, int W, int H, int dx, int dy,
+	       void (*draw_area)(void*, int,int,int,int), void* data)
+{
+  if (!dx && !dy) return;
+  if (dx <= -W || dx >= W || dy <= -H || dy >= H) {
+    // no intersection of old an new scroll
+    draw_area(data,X,Y,W,H);
+    return;
+  }
+  int src_x, src_w, dest_x, clip_x, clip_w;
+  if (dx > 0) {
+    src_x = X;
+    dest_x = X+dx;
+    src_w = W-dx;
+    clip_x = X;
+    clip_w = dx;
+  } else {
+    src_x = X-dx;
+    dest_x = X;
+    src_w = W+dx;
+    clip_x = X+src_w;
+    clip_w = W-src_w;
+  }
+  int src_y, src_h, dest_y, clip_y, clip_h;
+  if (dy > 0) {
+    src_y = Y;
+    dest_y = Y+dy;
+    src_h = H-dy;
+    clip_y = Y;
+    clip_h = dy;
+  } else {
+    src_y = Y-dy;
+    dest_y = Y;
+    src_h = H+dy;
+    clip_y = Y+src_h;
+    clip_h = H-src_h;
+  }
+#ifdef WIN32
+  BitBlt(fl_gc, dest_x, dest_y, src_w, src_h, fl_gc, src_x, src_y,SRCCOPY);
+  // NYI: need to redraw areas that the source of BitBlt was bad due to
+  // overlapped windows, probably similar to X version:
+#else
+  XCopyArea(fl_display, fl_window, fl_window, fl_gc,
+	    src_x, src_y, src_w, src_h, dest_x, dest_y);
+  // we have to sync the display and get the GraphicsExpose events! (sigh)
+  for (;;) {
+    XEvent e; XWindowEvent(fl_display, fl_window, ExposureMask, &e);
+    if (e.type == NoExpose) break;
+    // otherwise assumme it is a GraphicsExpose event:
+    draw_area(data, e.xexpose.x, e.xexpose.y,
+	      e.xexpose.width, e.xexpose.height);
+    if (!e.xgraphicsexpose.count) break;
+  }
+#endif
+  if (dx) draw_area(data, clip_x, dest_y, clip_w, src_h);
+  if (dy) draw_area(data, X, clip_y, W, clip_h);
+}
diff --git a/src/fl_set_font.cxx b/src/fl_set_font.cxx
new file mode 100644
index 000000000..2d166bf9f
--- /dev/null
+++ b/src/fl_set_font.cxx
@@ -0,0 +1,51 @@
+// fl_set_font.C
+
+// Add a font to the internal table.
+// Also see fl_set_fonts.C which adds all possible fonts.
+
+#include 
+#include 
+#include 
+#include "Fl_Font.H"
+#include 
+#include 
+
+static int table_size;
+
+void Fl::set_font(Fl_Font fnum, const char *name) {
+  if (fnum >= table_size) {
+    int i = table_size;
+    if (!i) {	// don't realloc the built-in table
+      table_size = 2*FL_FREE_FONT;
+      i = FL_FREE_FONT;
+      Fl_Fontdesc *t = (Fl_Fontdesc*)malloc(table_size*sizeof(Fl_Fontdesc));
+      memcpy(t, fl_fonts, FL_FREE_FONT*sizeof(Fl_Fontdesc));
+      fl_fonts = t;
+    } else {
+      table_size = 2*table_size;
+      fl_fonts=(Fl_Fontdesc*)realloc(fl_fonts, table_size*sizeof(Fl_Fontdesc));
+    }
+    for (; i < table_size; i++) fl_fonts[i].name = 0;
+  }
+  Fl_Fontdesc *s = fl_fonts+fnum;
+  if (s->name) {
+    if (!strcmp(s->name, name)) {s->name = name; return;}
+#ifndef WIN32
+    if (s->xlist && s->n >= 0) XFreeFontNames(s->xlist);
+#endif
+    for (Fl_XFont *f = s->first; f;) {
+#ifndef WIN32
+      if (f == fl_fixed_xfont) break;
+#endif
+      Fl_XFont *n = f->next; delete f; f = n;
+    }
+    s->first = 0;
+  }
+  s->name = name;
+#ifndef WIN32
+  s->xlist = 0;
+#endif
+  s->first = 0;
+}
+
+const char *Fl::get_font(Fl_Font fnum) {return fl_fonts[fnum].name;}
diff --git a/src/fl_set_fonts.cxx b/src/fl_set_fonts.cxx
new file mode 100644
index 000000000..e3834d32b
--- /dev/null
+++ b/src/fl_set_fonts.cxx
@@ -0,0 +1,300 @@
+// fl_set_fonts.C
+
+// This function fills in the fltk font table with all the fonts that
+// are found on the X server.  It tries to place the fonts into families
+// and to sort them so the first 4 in a family are normal, bold, italic,
+// and bold italic.
+
+#ifdef WIN32
+#include "fl_set_fonts_win32.C"
+#else
+
+// Standard X fonts are matched by a pattern that is always of
+// this form, and this pattern is put in the table:
+// "-*-family-weight-slant-width1-style-*-registry-encoding"
+
+// Non-standard font names (those not starting with '-') are matched
+// by a pattern of the form "prefix*suffix", where the '*' is where
+// fltk thinks the point size is, or by the actual font name if no
+// point size is found.
+
+// Fltk knows how to pull an "attribute" out of a font name, such as
+// bold or italic, by matching known x font field values.  All words
+// that don't match a known attribute are combined into the "name"
+// of the font.  Names are compared before attributes for sorting, this
+// makes the bold and plain version of a font come out next to each
+// other despite the poor X font naming scheme.
+
+// By default fl_set_fonts() only does iso8859-1 encoded fonts.  You can
+// do all normal X fonts by passing "-*" or every possible font with "*".
+
+// Fl::set_font will take strings other than the ones this stores
+// and can identify any font on X that way.  You may want to write your
+// own system of font management and not use this code.
+
+#include 
+#include 
+#include "Fl_Font.H"
+#include 
+#include 
+#include 
+
+// turn word N of a X font name into either some attribute bits
+// (right now 0, FL_BOLD, or FL_ITALIC), or into -1 indicating that
+// the word should be put into the name:
+
+static int attribute(int n, const char *p) {
+  // don't put blank things into name:
+  if (!*p || *p=='-' || *p=='*') return 0;
+  if (n == 3) { // weight
+    if (!strncmp(p,"normal",6) ||
+	!strncmp(p,"light",5) ||
+	!strncmp(p,"medium",6) ||
+	!strncmp(p,"book",4)) return 0;
+    if (!strncmp(p,"bold",4) || !strncmp(p,"demi",4)) return FL_BOLD;
+  } else if (n == 4) { // slant
+    if (*p == 'r') return 0;
+    if (*p == 'i' || *p == 'o') return FL_ITALIC;
+  } else if (n == 5) { // sWidth
+    if (!strncmp(p,"normal",6)) return 0;
+  }
+  return -1;
+}
+
+// return non-zero if the registry-encoding should be used:
+extern const char* fl_encoding;
+static int use_registry(const char *p) {
+  return *p && *p!='*' && strcmp(p,fl_encoding);
+}
+
+// turn a stored (with *'s) X font name into a pretty name:
+const char* Fl::get_font_name(Fl_Font fnum, int* ap) {
+  const char* p = fl_fonts[fnum].name;
+  if (!p) return "";
+  static char *buffer; if (!buffer) buffer = new char[128];
+  char *o = buffer;
+
+  if (*p != '-') { // non-standard font, just replace * with spaces:
+    if (ap) {
+      int type = 0;
+      if (strstr(p,"bold")) type = FL_BOLD;
+      if (strstr(p,"ital")) type |= FL_ITALIC;
+      *ap = type;
+    }
+    for (;*p; p++) {
+      if (*p == '*' || *p == ' ' || *p == '-') {
+	do p++; while (*p == '*' || *p == ' ' || *p == '-');
+	if (!*p) break;
+	*o++ = ' ';
+      }
+      *o++ = *p;
+    }
+    *o = 0;
+    return buffer;
+  }
+
+  // get the family:
+  const char *x = fl_font_word(p,2); if (*x) x++; if (*x=='*') x++;
+  if (!*x) return p;
+  const char *e = fl_font_word(x,1);
+  strncpy(o,x,e-x); o += e-x;
+
+  // collect all the attribute words:
+  int type = 0;
+  for (int n = 3; n <= 6; n++) {
+    // get the next word:
+    if (*e) e++; x = e; e = fl_font_word(x,1);
+    int t = attribute(n,x);
+    if (t < 0) {*o++ = ' '; strncpy(o,x,e-x); o += e-x;}
+    else type |= t;
+  }
+
+  // skip over the '*' for the size and get the registry-encoding:
+  x = fl_font_word(e,2);
+  if (*x) {x++; *o++ = '('; while (*x) *o++ = *x++; *o++ = ')';}
+
+  *o = 0;
+  if (ap) *ap = type;
+
+  return buffer;
+}
+
+// sort raw (non-'*') X font names into perfect order:
+
+static int ultrasort(const void *aa, const void *bb) {
+  const char *a = *(char **)aa;
+  const char *b = *(char **)bb;
+
+  // sort all non x-fonts at the end:
+  if (*a != '-') {
+    if (*b == '-') return 1;
+    // 2 non-x fonts are matched by "numeric sort"
+    int ret = 0;
+    for (;;) {
+      if (isdigit(*a) && isdigit(*b)) {
+	int na = strtol(a, (char **)&a, 10);
+	int nb = strtol(b, (char **)&b, 10);
+	if (!ret) ret = na-nb;
+      } else if (*a != *b) {
+	return (*a-*b);
+      } else if (!*a) {
+	return ret;
+      } else {
+	a++; b++;
+      }
+    }
+  } else {
+    if (*b != '-') return -1;
+  }
+
+  // skip the foundry (assumme equal):
+  for (a++; *a && *a++!='-';);
+  for (b++; *b && *b++!='-';);
+
+  // compare the family and all the attribute words:
+  int atype = 0;
+  int btype = 0;
+  for (int n = 2; n <= 6; n++) {
+    int at = attribute(n,a);
+    int bt = attribute(n,b);
+    if (at < 0) {
+      if (bt >= 0) return 1;
+      for (;;) {if (*a!=*b) return *a-*b; b++; if (!*a || *a++=='-') break;}
+    } else {
+      if (bt < 0) return -1;
+      a = fl_font_word(a,1); if (*a) a++;
+      b = fl_font_word(b,1); if (*b) b++;
+      atype |= at; btype |= bt;
+    }
+  }
+
+  // remember the pixel size:
+  int asize = atoi(a);
+  int bsize = atoi(b);
+
+  // compare the registry/encoding:
+  a = fl_font_word(a,6); if (*a) a++;
+  b = fl_font_word(b,6); if (*b) b++;
+  if (use_registry(a)) {
+    if (!use_registry(b)) return 1;
+    int r = strcmp(a,b); if (r) return r;
+  } else {
+    if (use_registry(b)) return -1;
+  }
+
+  if (atype != btype) return atype-btype;
+  if (asize != bsize) return asize-bsize;
+
+  // something wrong, just do a string compare...
+  return strcmp(*(char**)aa, *(char**)bb);
+}
+
+// converts a X font name to a standard starname, returns point size:
+static int to_canonical(char *to, const char *from) {
+  char* c = fl_find_fontsize((char*)from);
+  if (!c) return -1; // no point size found...
+  char* endptr;
+  int size = strtol(c,&endptr,10);
+  if (from[0] == '-') {
+    // replace the "foundry" with -*-:
+    *to++ = '-'; *to++ = '*';
+    for (from++; *from && *from != '-'; from++);
+    // skip to the registry-encoding:
+    endptr = (char*)fl_font_word(endptr,6);
+    if (*endptr && !use_registry(endptr+1)) endptr = "";
+  }
+  int n = c-from;
+  strncpy(to,from,n);
+  to[n++] = '*';
+  strcpy(to+n,endptr);
+  return size;
+}
+
+static int fl_free_font = FL_FREE_FONT;
+
+Fl_Font Fl::set_fonts(const char* xstarname) {
+  fl_open_display();
+  int xlistsize;
+  char buf[20];
+  if (!xstarname) {
+    strcpy(buf,"-*-"); strcpy(buf+3,fl_encoding);
+    xstarname = buf;
+  }
+  char **xlist = XListFonts(fl_display, xstarname, 10000, &xlistsize);
+  if (!xlist) return (Fl_Font)fl_free_font;
+  qsort(xlist, xlistsize, sizeof(*xlist), ultrasort);
+  int used_xlist = 0;
+  for (int i=0; i= 0) {
+      for (;;) { // find all matching fonts:
+	if (i >= xlistsize) break;
+	const char *q = xlist[i];
+	char this_canon[1024];
+	if (to_canonical(this_canon, q) < 0) break;
+	if (strcmp(canon, this_canon)) break;
+	i++;
+      }
+      /*if (*p=='-' || i > first_xlist+1)*/ p = canon;
+    }
+    int j;
+    for (j = 0;; j++) {
+      if (j < FL_FREE_FONT) {
+	// see if it is one of our built-in fonts:
+	// if so, set the list of x fonts, since we have it anyway
+	if (fl_fonts[j].name && !strcmp(fl_fonts[j].name, p)) break;
+      } else {
+	j = fl_free_font++;
+	if (p == canon) p = strdup(p); else used_xlist = 1;
+	Fl::set_font((Fl_Font)j, p);
+	break;
+      }
+    }
+    if (!fl_fonts[j].xlist) {
+      fl_fonts[j].xlist = xlist+first_xlist;
+      fl_fonts[j].n = -(i-first_xlist);
+      used_xlist = 1;
+    }
+  }
+  if (!used_xlist) XFreeFontNames(xlist);
+  return (Fl_Font)fl_free_font;
+}
+
+int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) {
+  Fl_Fontdesc *s = fl_fonts+fnum;
+  if (!s->name) s = fl_fonts; // empty slot in table, use entry 0
+  if (!s->xlist) {
+    fl_open_display();
+    s->xlist = XListFonts(fl_display, s->name, 100, &(s->n));
+    if (!s->xlist) return 0;
+  }
+  int listsize = s->n; if (listsize<0) listsize = -listsize;
+  static int sizes[128];
+  int numsizes = 0;
+  for (int i = 0; i < listsize; i++) {
+    char *q = s->xlist[i];
+    char *d = fl_find_fontsize(q);
+    if (!d) continue;
+    int s = strtol(d,0,10);
+    if (!numsizes || sizes[numsizes-1] < s) {
+      sizes[numsizes++] = s;
+    } else {
+      // insert-sort the new size into list:
+      int n;
+      for (n = numsizes-1; n > 0; n--) if (sizes[n-1] < s) break;
+      if (sizes[n] != s) {
+	for (int m = numsizes; m > n; m--) sizes[m] = sizes[m-1];
+	sizes[n] = s;
+	numsizes++;
+      }
+    }
+  }
+  sizep = sizes;
+  return numsizes;
+}
+
+#endif
+// end of fl_set_fonts.C
diff --git a/src/fl_set_fonts_win32.cxx b/src/fl_set_fonts_win32.cxx
new file mode 100755
index 000000000..2a00363e9
--- /dev/null
+++ b/src/fl_set_fonts_win32.cxx
@@ -0,0 +1,58 @@
+// fl_set_fonts_win32.C
+
+// This function fills in the fltk font table with all the fonts that
+// are found on the X server.  It tries to place the fonts into families
+// and to sort them so the first 4 in a family are normal, bold, italic,
+// and bold italic.
+
+#include 
+#include 
+#include "Fl_Font.H"
+#include 
+#include 
+#include 
+
+// turn a stored font name into a pretty name:
+const char* Fl::get_font_name(Fl_Font fnum, int* ap) {
+  const char* p = fl_fonts[fnum].name;
+  if (!p || !*p) {if (ap) *ap = 0; return "";}
+  if (ap) switch (*p) {
+  case 'B': *ap = FL_BOLD; break;
+  case 'I': *ap = FL_ITALIC; break;
+  case 'P': *ap = FL_BOLD | FL_ITALIC; break;
+  default:  *ap = 0; break;
+  }
+  return p+1;
+}
+
+static int fl_free_font = FL_FREE_FONT;
+
+static int CALLBACK enumcb(ENUMLOGFONT FAR *lpelf,
+  NEWTEXTMETRIC FAR *lpntm, int FontType, LPARAM p) {
+  if (!p && lpelf->elfLogFont.lfCharSet != ANSI_CHARSET) return 1;
+  char *n = (char*)(lpelf->elfFullName);
+  for (int i=0; ielfLogFont.lfWeight <= 400)
+    buffer[0] = 'B', Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer));
+  buffer[0] = 'I'; Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer));
+  if (lpelf->elfLogFont.lfWeight <= 400)
+    buffer[0] = 'P', Fl::set_font((Fl_Font)(fl_free_font++), strdup(buffer));
+  return 1;
+}
+
+Fl_Font Fl::set_fonts(const char* xstarname) {
+  EnumFontFamilies(fl_gc, NULL, (FONTENUMPROC)enumcb, xstarname != 0);
+  return (Fl_Font)fl_free_font;
+}
+
+int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) {
+  // pretend all fonts are scalable (most are and I don't know how
+  // to tell anyways)
+  static int array[1];
+  sizep = array;
+  return 1;
+}
diff --git a/src/fl_set_gray.cxx b/src/fl_set_gray.cxx
new file mode 100644
index 000000000..c3b869f47
--- /dev/null
+++ b/src/fl_set_gray.cxx
@@ -0,0 +1,35 @@
+// fl_set_gray.C
+
+// -fg, -bg, and -bg2 switches
+
+#include 
+
+void Fl::background(uchar r, uchar g, uchar b) {
+  // replace the gray ramp so that color 47 is this color
+  int i;
+  for (i = 32; i <= 47; i++) {
+    int m = (i-32)*255/23;
+    Fl::set_color(i,r*m/166,g*m/166,b*m/166);
+  }
+  for (; i < 56; i++) {
+    int m = 255-(i-32)*255/23;
+    Fl::set_color(i,255-(255-r)*m/89,255-(255-g)*m/89,255-(255-b)*m/89);
+  }
+}
+
+static void set_others() {
+  uchar r,g,b; Fl::get_color(FL_BLACK,r,g,b);
+  uchar r1,g1,b1; Fl::get_color(FL_WHITE,r1,g1,b1);
+  Fl::set_color(FL_INACTIVE_COLOR,(2*r+r1)/3, (2*g+g1)/3, (2*b+b1)/3);
+  Fl::set_color(FL_SELECTION_COLOR,(2*r1+r)/3, (2*g1+g)/3, (2*b1+b)/3);
+}
+
+void Fl::foreground(uchar r, uchar g, uchar b) {
+  Fl::set_color(FL_BLACK,r,g,b);
+  set_others();
+}
+
+void Fl::background2(uchar r, uchar g, uchar b) {
+  Fl::set_color(FL_WHITE,r,g,b);
+  set_others();
+}
diff --git a/src/fl_shadow_box.cxx b/src/fl_shadow_box.cxx
new file mode 100644
index 000000000..d48b6ba96
--- /dev/null
+++ b/src/fl_shadow_box.cxx
@@ -0,0 +1,31 @@
+// fl_shadow_box.C
+
+// Box drawing code for an obscure box type.
+// These box types are in seperate files so they are not linked
+// in if not used.
+
+#include 
+#include 
+
+#define BW 3
+
+static void fl_shadow_frame(int x, int y, int w, int h, Fl_Color c) {
+  fl_color(FL_DARK3);
+  fl_rectf(x+BW, y+h,  w, BW);
+  fl_rectf(x+w,  y+BW, BW,  h);
+  fl_color(c);
+  fl_rect(x,y,w,h);
+}
+
+static void fl_shadow_box(int x, int y, int w, int h, Fl_Color c) {
+  fl_color(c);
+  fl_rectf(x+1,y+1,w-2,h-2);
+  fl_shadow_frame(x,y,w,h,FL_GRAY0);
+}
+
+extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*);
+Fl_Boxtype define_FL_SHADOW_BOX() {
+  fl_internal_boxtype(_FL_SHADOW_FRAME, fl_shadow_frame);
+  fl_internal_boxtype(_FL_SHADOW_BOX, fl_shadow_box);
+  return _FL_SHADOW_BOX;
+}
diff --git a/src/fl_shortcut.cxx b/src/fl_shortcut.cxx
new file mode 100644
index 000000000..b81853873
--- /dev/null
+++ b/src/fl_shortcut.cxx
@@ -0,0 +1,100 @@
+// fl_shortcut.C
+
+// Code to test and parse fltk shortcut numbers.
+
+// A shortcut is a keysym or'd with shift flags.  In the simplest
+// sense a shortcut is matched if the shift state is exactly as
+// given and the key returning that keysym is pressed.
+
+// To make it easier to match some things it is more complex:
+
+// Only FL_META, FL_ALT, FL_SHIFT, and FL_CTRL must be "off".  A
+// zero in the other shift flags indicates "dont care".
+
+// It also checks against the first character of Fl::event_text(),
+// and zero for FL_SHIFT means "don't care".
+// This allows punctuation shortcuts like "#" to work (rather than
+// calling it "shift+3")
+
+#include 
+#include 
+#include 
+#include 
+#ifndef WIN32
+#include 
+#endif
+
+int Fl::test_shortcut(int shortcut) {
+  if (!shortcut) return 0;
+
+  int shift = Fl::event_state();
+  // see if any required shift flags are off:
+  if ((shortcut&shift) != (shortcut&0x7fff0000)) return 0;
+  // record shift flags that are wrong:
+  int mismatch = (shortcut^shift)&0x7fff0000;
+  // these three must always be correct:
+  if (mismatch&(FL_META|FL_ALT|FL_CTRL)) return 0;
+
+  int key = shortcut & 0xffff;
+
+  // if shift is also correct, check for exactly equal keysyms:
+  if (!(mismatch&(FL_SHIFT)) && key == Fl::event_key()) return 1;
+
+  // try matching ascii, ignore shift:
+  if (key == event_text()[0]) return 1;
+
+  // kludge so that Ctrl+'_' works (as opposed to Ctrl+'^_'):
+  if ((shift&FL_CTRL) && key >= 0x3f && key <= 0x5F
+      && event_text()[0]==(key^0x40)) return 1;
+  return 0;
+}
+
+const char * fl_shortcut_label(int shortcut) {
+  static char buf[20];
+  char *p = buf;
+  if (!shortcut) {*p = 0; return buf;}
+  if (shortcut & FL_META) {strcpy(p,"Meta+"); p += 5;}
+  if (shortcut & FL_ALT) {strcpy(p,"Alt+"); p += 4;}
+  if (shortcut & FL_SHIFT) {strcpy(p,"Shift+"); p += 6;}
+  if (shortcut & FL_CTRL) {strcpy(p,"Ctrl+"); p += 5;}
+  int key = shortcut & 0xFFFF;
+#ifdef WIN32
+  if (key >= FL_F && key <= FL_F_Last) {
+    *p++ = 'F';
+    if (key > FL_F+9) *p++ = (key-FL_F)/10+'0';
+    *p++ = (key-FL_F)%10 + '0';
+  } else {
+    if (key == FL_Enter || key == '\r') {strcpy(p,"Enter"); return buf;}
+    *p++ = uchar(key);
+  }
+  *p = 0;
+  return buf;
+#else
+  const char* q;
+  if (key == FL_Enter || key == '\r') q="Enter"; // don't use Xlib's "Return"
+  else if (key > 32 && key < 0x100) q = 0;
+  else q = XKeysymToString(key);
+  if (!q) {*p++ = uchar(key); *p = 0; return buf;}
+  if (p > buf) {strcpy(p,q); return buf;} else return q;
+#endif
+}
+
+// Tests for &x shortcuts in button labels:
+
+int Fl_Widget::test_shortcut(const char *label) {
+  char c = Fl::event_text()[0];
+  if (!c || !label) return 0;
+  for (;;) {
+    if (!*label) return 0;
+    if (*label++ == '&' && *label) {
+      if (*label == '&') label++;
+      else if (*label == c) return 1;
+      else return 0;
+    }
+  }
+}
+
+int Fl_Widget::test_shortcut() {
+  if (!(flags()&SHORTCUT_LABEL)) return 0;
+  return test_shortcut(label());
+}
diff --git a/src/fl_show_colormap.cxx b/src/fl_show_colormap.cxx
new file mode 100644
index 000000000..5e3b18c88
--- /dev/null
+++ b/src/fl_show_colormap.cxx
@@ -0,0 +1,124 @@
+// fl_show_colormap.C
+
+// Select a color from the colormap.
+// Pretty much unchanged from Forms.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define BOXSIZE 14
+#define BORDER 4
+
+class ColorMenu : public Fl_Window {
+  Fl_Color initial;
+  Fl_Color which, previous;
+  int done;
+  void drawbox(Fl_Color);
+  void draw();
+  int handle(int);
+public:
+  ColorMenu(Fl_Color oldcol);
+  Fl_Color run();
+};
+
+ColorMenu::ColorMenu(Fl_Color oldcol) :
+  Fl_Window(BOXSIZE*8+1+2*BORDER, BOXSIZE*32+1+2*BORDER) {
+  clear_border();
+  set_modal();
+  initial = which = oldcol;
+}
+
+void ColorMenu::drawbox(Fl_Color c) {
+  if (c < 0 || c > 255) return;
+  int x = (c%8)*BOXSIZE+BORDER;
+  int y = (c/8)*BOXSIZE+BORDER;
+#if BORDER_WIDTH < 3
+  if (c == which) fl_draw_box(FL_DOWN_BOX, x+1, y+1, BOXSIZE-1, BOXSIZE-1, c);
+  else fl_draw_box(FL_BORDER_BOX, x, y, BOXSIZE+1, BOXSIZE+1, c);
+#else
+  fl_draw_box(c == which ? FL_DOWN_BOX : FL_BORDER_BOX,
+	      x, y, BOXSIZE+1, BOXSIZE+1, c);
+#endif
+}
+
+void ColorMenu::draw() {
+  if (damage() != 1) {
+    fl_draw_box(FL_UP_BOX,0,0,w(),h(),color());
+    for (int c = 0; c < 256; c++) drawbox((Fl_Color)c);
+  } else {
+    drawbox(previous);
+    drawbox(which);
+  }
+  previous = which;
+}
+
+int ColorMenu::handle(int e) {
+  int c = which;
+  switch (e) {
+  case FL_PUSH:
+  case FL_DRAG: {
+    int X = (Fl::event_x_root() - x() - BORDER);
+    if (X >= 0) X = X/BOXSIZE;
+    int Y = (Fl::event_y_root() - y() - BORDER);
+    if (Y >= 0) Y = Y/BOXSIZE;
+    if (X >= 0 && X < 8 && Y >= 0 && Y < 32)
+      c = 8*Y + X;
+    else
+      c = initial;
+    } break;
+  case FL_RELEASE:
+    done = 1;
+    return 1;
+  case FL_KEYBOARD:
+    switch (Fl::event_key()) {
+    case FL_Up: if (c > 7) c -= 8; break;
+    case FL_Down: if (c < 256-8) c += 8; break;
+    case FL_Left: if (c > 0) c--; break;
+    case FL_Right: if (c < 255) c++; break;
+    case FL_Escape: which = initial; done = 1; return 1;
+    case FL_Enter: done = 1; return 1;
+    default: return 0;
+    }
+    break;
+  default:
+    return 0;
+  }
+  if (c != which) {
+    which = (Fl_Color)c; damage(1);
+    int bx = (c%8)*BOXSIZE+BORDER;
+    int by = (c/8)*BOXSIZE+BORDER;
+    int px = x();
+    int py = y();
+    if (px+bx+BOXSIZE+BORDER >= Fl::w()) px = Fl::w()-bx-BOXSIZE-BORDER;
+    if (py+by+BOXSIZE+BORDER >= Fl::h()) py = Fl::h()-by-BOXSIZE-BORDER;
+    if (px+bx < BORDER) px = BORDER-bx;
+    if (py+by < BORDER) py = BORDER-by;
+    position(px,py);
+  }
+  return 1;
+}
+
+extern char fl_override_redirect; // hack for menus
+
+Fl_Color ColorMenu::run() {
+  if (which < 0 || which > 255) {
+    position(Fl::event_x_root()-w()/2, Fl::event_y_root()-y()/2);
+  } else {
+    position(Fl::event_x_root()-(initial%8)*BOXSIZE-BOXSIZE/2-BORDER,
+	     Fl::event_y_root()-(initial/8)*BOXSIZE-BOXSIZE/2-BORDER);
+  }
+  Fl::grab(*this);
+  show();
+  done = 0;
+  while (!done) Fl::wait();
+  Fl::release();
+  return which;
+}
+
+Fl_Color fl_show_colormap(Fl_Color oldcol) {
+  ColorMenu m(oldcol);
+  return m.run();
+}
diff --git a/src/fl_symbols.cxx b/src/fl_symbols.cxx
new file mode 100644
index 000000000..df2f20926
--- /dev/null
+++ b/src/fl_symbols.cxx
@@ -0,0 +1,364 @@
+// fl_symbols.C
+
+// These are small graphics drawn by the normal label-drawing
+// code when the string starts with an '@' sign.
+
+// Adapted from original code written by:
+
+// Written by Mark Overmars
+// Version 2.1 a
+// Date: Oct  2, 1992
+
+#include 
+#include 
+#include 
+
+typedef struct {
+  const char *name;
+  void (*drawit)(Fl_Color);
+  char scalable;
+  char notempty;
+} SYMBOL;
+
+#define MAXSYMBOL       211
+   /* Maximal number of symbols in table. Only half of them are
+      used. Should be prime. */
+
+static SYMBOL symbols[MAXSYMBOL];      /* The symbols */
+static int symbnumb = -1;              /* Their number */
+
+static int find(const char *name) {
+// returns hash entry if it exists, or first empty slot:
+  int pos = name[0] ? (
+    name[1] ? (
+      name[2] ? 71*name[0]+31*name[1]+name[2] : 31*name[0]+name[1]
+    ) :
+      name[0]
+  ) : 0;
+  pos %= MAXSYMBOL;
+  int hh2 = name[0] ? (
+    (name[1]) ? 51*name[0]+3*name[1] : 3*name[0]
+    ) : 1;
+  hh2 %= MAXSYMBOL; if (!hh2) hh2 = 1;
+  for (;;) {
+    if (!symbols[pos].notempty) return pos;
+    if (!strcmp(symbols[pos].name,name)) return pos;
+    pos = (pos + hh2) % MAXSYMBOL;
+  }
+}
+
+static void fl_init_symbols(void);
+
+/**************** The routines seen by the user *************************/
+
+int fl_add_symbol(const char *name, void (*drawit)(Fl_Color), int scalable)
+/* Adds a symbol to the system. Returns whether correct. */
+{
+  fl_init_symbols();
+  int pos;
+  if (symbnumb > MAXSYMBOL / 2) return 0;	// table is full
+  pos = find(name);
+  symbols[pos].name = name;
+  symbols[pos].drawit = drawit;
+  symbols[pos].notempty = 1;
+  symbols[pos].scalable = scalable;
+  symbnumb++;
+  return 1;
+}
+
+int fl_return_arrow(int x,int y,int w,int h);
+
+// provided for back compatability:
+int fl_draw_symbol(const char *label,int x,int y,int w,int h,Fl_Color col) {
+  const char *p = label;
+  if (*p++ != '@') return 0;
+  fl_init_symbols();
+  int equalscale = 0;
+  if (*p == '#') {equalscale = 1; p++;}
+  if (*p == '-' && p[1]>='1' && p[1]<='9') {
+    int n = p[1]-'0';
+    x += n; y += n; w -= 2*n; h -= 2*n;
+    p += 2;
+  } else if (*p == '+' && p[1]>='1' && p[1]<='9') {
+    int n = p[1]-'0';
+    x -= n; y -= n; w += 2*n; h += 2*n;
+    p += 2;
+  }
+  if (w < 10) {x -= (10-w)/2; w = 10;}
+  if (h < 10) {y -= (10-h)/2; h = 10;}
+  w = (w-1)|1; h = (h-1)|1;
+  int rotangle;
+  switch (*p++) {
+  case '0':
+    rotangle = 1000*(p[1]-'0') + 100*(p[2]-'0') + 10*(p[3]-'0');
+    p += 4;
+    break;
+  case '1': rotangle = 2250; break;
+  case '2': rotangle = 2700; break;
+  case '3': rotangle = 3150; break;
+  case '4': rotangle = 1800; break;
+  case '5':
+  case '6': rotangle = 0; break;
+  case '7': rotangle = 1350; break;
+  case '8': rotangle =  900; break;
+  case '9': rotangle =  450; break;
+  default: rotangle = 0; p--; break;
+  }
+  int pos = find(p);
+  if (!symbols[pos].notempty) return 0;
+  if (symbols[pos].scalable == 3) { // kludge to detect return arrow
+    fl_return_arrow(x,y,w,h);
+    return 1;
+  }
+  fl_push_matrix();
+  fl_translate(x+w/2,y+h/2);
+  if (symbols[pos].scalable) {
+    if (equalscale) {if (w",		draw_arrow1,		1);
+  fl_add_symbol(">",		draw_arrow2,		1);
+  fl_add_symbol(">>",		draw_arrow3,		1);
+  fl_add_symbol(">|",		draw_arrowbar,		1);
+  fl_add_symbol(">[]",		draw_arrowbox,		1);
+  fl_add_symbol("|>",		draw_bararrow,		1);
+  fl_add_symbol("<-",		draw_arrow01,		1);
+  fl_add_symbol("<",		draw_arrow02,		1);
+  fl_add_symbol("<<",		draw_arrow03,		1);
+  fl_add_symbol("|<",		draw_0arrowbar,		1);
+  fl_add_symbol("[]<",		draw_0arrowbox,		1);
+  fl_add_symbol("<|",		draw_0bararrow,		1);
+  fl_add_symbol("<->",		draw_doublearrow,	1);
+  fl_add_symbol("-->",		draw_arrow,		1);
+  fl_add_symbol("+",		draw_plus,		1);
+  fl_add_symbol("->|",		draw_arrow1bar,		1);
+  fl_add_symbol("arrow",	draw_arrow,		1);
+  fl_add_symbol("returnarrow",	0,			3);
+  fl_add_symbol("square",	draw_square,		1);
+  fl_add_symbol("circle",	draw_circle,		1);
+  fl_add_symbol("line",		draw_line,		1);
+  fl_add_symbol("plus",		draw_plus,		1);
+  fl_add_symbol("menu",		draw_menu,		1);
+  fl_add_symbol("UpArrow",	draw_uparrow,		1);
+  fl_add_symbol("DnArrow",	draw_downarrow,		1);
+  fl_add_symbol("||",		draw_doublebar,		1);
+}
+
+////////////////////////////////////////////////////////////////
+
+#include 
+
+// this is the labeltype function:
+extern void fl_normal_label(const Fl_Label*, int, int, int, int, Fl_Align);
+static void fl_symbol_label(
+    const Fl_Label* o, int x, int y, int w, int h, Fl_Align align)
+{
+  if (!fl_draw_symbol(o->value, x, y, w, h, (Fl_Color)o->color))
+    fl_normal_label(o, x, y, w, h, align);
+}
+
+Fl_Labeltype define_FL_SYMBOL_LABEL() {
+  Fl::set_labeltype(_FL_SYMBOL_LABEL, fl_symbol_label, 0);
+  return _FL_SYMBOL_LABEL;
+}
+
+void Fl::enable_symbols() {
+  Fl::set_labeltype(FL_NORMAL_LABEL, fl_symbol_label, 0);
+}
diff --git a/src/fl_vertex.cxx b/src/fl_vertex.cxx
new file mode 100644
index 000000000..cdf9b1df0
--- /dev/null
+++ b/src/fl_vertex.cxx
@@ -0,0 +1,200 @@
+// fl_vertex.C
+
+// Portable drawing code for drawing arbitrary shapes with
+// simple 2D transformations.  See also fl_arc.C
+
+#include 
+#include 
+#include 
+#include 
+
+struct matrix {double a, b, c, d, x, y;};
+
+static matrix m = {1, 0, 0, 1, 0, 0};
+
+static matrix stack[10];
+static int sptr = 0;
+
+void fl_push_matrix() {stack[sptr++] = m;}
+
+void fl_pop_matrix() {m = stack[--sptr];}
+
+void fl_mult_matrix(double a, double b, double c, double d, double x, double y) {
+  matrix o;
+  o.a = a*m.a + b*m.c;
+  o.b = a*m.b + b*m.d;
+  o.c = c*m.a + d*m.c;
+  o.d = c*m.b + d*m.d;
+  o.x = x*m.a + y*m.c + m.x;
+  o.y = x*m.b + y*m.d + m.y;
+  m = o;
+}
+
+void fl_scale(double x,double y) {fl_mult_matrix(x,0,0,y,0,0);}
+
+void fl_scale(double x) {fl_mult_matrix(x,0,0,x,0,0);}
+
+void fl_translate(double x,double y) {fl_mult_matrix(1,0,0,1,x,y);}
+
+void fl_rotate(double d) {
+  if (d) {
+    double s, c;
+    if (d == 0) {s = 0; c = 1;}
+    else if (d == 90) {s = 1; c = 0;}
+    else if (d == 180) {s = 0; c = -1;}
+    else if (d == 270 || d == -90) {s = -1; c = 0;}
+    else {s = sin(d*M_PI/180); c = cos(d*M_PI/180);}
+    fl_mult_matrix(c,-s,s,c,0,0);
+  }
+}
+
+static XPoint *p;
+// typedef what the x,y fields in a point are:
+#ifdef WIN32
+typedef int COORD_T;
+#else
+typedef short COORD_T;
+#endif
+
+static int p_size;
+static int n;
+static int what;
+enum {LINE, LOOP, POLYGON, POINT_};
+
+void fl_begin_points() {n = 0; what = POINT_;}
+
+void fl_begin_line() {n = 0; what = LINE;}
+
+void fl_begin_loop() {n = 0; what = LOOP;}
+
+void fl_begin_polygon() {n = 0; what = POLYGON;}
+
+double fl_transform_x(double x, double y) {return x*m.a + y*m.c + m.x;}
+
+double fl_transform_y(double x, double y) {return x*m.b + y*m.d + m.y;}
+
+double fl_transform_dx(double x, double y) {return x*m.a + y*m.c;}
+
+double fl_transform_dy(double x, double y) {return x*m.b + y*m.d;}
+
+static void fl_transformed_vertex(COORD_T x, COORD_T y) {
+  if (!n || x != p[n-1].x || y != p[n-1].y) {
+    if (n >= p_size) {
+      p_size = p ? 2*p_size : 16;
+      p = (XPoint *)realloc((void*)p, p_size*sizeof(*p));
+    }
+    p[n].x = x;
+    p[n].y = y;
+    n++;
+  }
+}
+
+void fl_transformed_vertex(double xf, double yf) {
+  fl_transformed_vertex(COORD_T(xf+.5), COORD_T(yf+.5));
+}
+
+void fl_vertex(double x,double y) {
+  fl_transformed_vertex(x*m.a + y*m.c + m.x, x*m.b + y*m.d + m.y);
+}
+
+void fl_end_points() {
+#ifdef WIN32
+  for (int i=0; i1) XDrawPoints(fl_display, fl_window, fl_gc, p, n, 0);
+#endif
+}
+
+void fl_end_line() {
+#ifdef WIN32
+  if (n>1) Polyline(fl_gc, p, n);
+#else
+  if (n>1) XDrawLines(fl_display, fl_window, fl_gc, p, n, 0);
+#endif
+}
+
+static void fixloop() {  // remove equal points from closed path
+  while (n>2 && p[n-1].x == p[0].x && p[n-1].y == p[0].y) n--;
+}
+
+void fl_end_loop() {
+  fixloop();
+  if (n>2) fl_transformed_vertex((COORD_T)p[0].x, (COORD_T)p[0].y);
+  fl_end_line();
+}
+
+void fl_end_polygon() {
+  fixloop();
+#ifdef WIN32
+  if (n>2) {
+    SelectObject(fl_gc, fl_brush());
+    Polygon(fl_gc, p, n);
+  }
+#else
+  if (n>2) XFillPolygon(fl_display, fl_window, fl_gc, p, n, Convex, 0);
+#endif
+}
+
+static int gap;
+#ifdef WIN32
+static int counts[20];
+static int numcount;
+#endif
+
+void fl_begin_complex_polygon() {
+  fl_begin_polygon();
+  gap = 0;
+#ifdef WIN32
+  numcount = 0;
+#endif
+}
+
+void fl_gap() {
+  while (n>gap+2 && p[n-1].x == p[gap].x && p[n-1].y == p[gap].y) n--;
+  if (n > gap+2) {
+    fl_transformed_vertex((COORD_T)p[gap].x, (COORD_T)p[gap].y);
+#ifdef WIN32
+    counts[numcount++] = n-gap;
+#endif
+    gap = n;
+  } else {
+    n = gap;
+  }
+}
+
+void fl_end_complex_polygon() {
+  fl_gap();
+#ifdef WIN32
+  if (n>2) {
+    SelectObject(fl_gc, fl_brush());
+    PolyPolygon(fl_gc, p, counts, numcount);
+  }
+#else
+  if (n>2) XFillPolygon(fl_display, fl_window, fl_gc, p, n, 0, 0);
+#endif
+}
+
+// shortcut the closed circles so they use XDrawArc:
+// warning: these do not draw rotated ellipses correctly!
+// See fl_arc.c for portable version.
+
+void fl_circle(double x, double y,double r) {
+  double xt = fl_transform_x(x,y);
+  double yt = fl_transform_y(x,y);
+  double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a));
+  double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d));
+  int llx = int(xt-rx+.5);
+  int w = int(xt+rx+.5)-llx;
+  int lly = int(yt-ry+.5);
+  int h = int(yt+ry+.5)-lly;
+#ifdef WIN32
+  if (what==POLYGON) {
+    SelectObject(fl_gc, fl_brush());
+    Pie(fl_gc, llx, lly, llx+w, lly+h, 0,0, 0,0); 
+  } else
+    Arc(fl_gc, llx, lly, llx+w, lly+h, 0,0, 0,0); 
+#else
+  (what == POLYGON ? XFillArc : XDrawArc)
+    (fl_display, fl_window, fl_gc, llx, lly, w, h, 0, 360*64);
+#endif
+}
diff --git a/src/forms_bitmap.cxx b/src/forms_bitmap.cxx
new file mode 100644
index 000000000..1b0eae749
--- /dev/null
+++ b/src/forms_bitmap.cxx
@@ -0,0 +1,24 @@
+// forms_bitmap.C
+// Forms compatability widget to draw a bitmap
+
+#include 
+
+Fl_FormsBitmap::Fl_FormsBitmap(
+  Fl_Boxtype t, int x, int y, int w, int h, const char* l)
+: Fl_Widget(x, y, w, h, l) {
+  box(t);
+  b = 0;
+  color(FL_BLACK);
+  align(FL_ALIGN_BOTTOM);
+}
+
+void Fl_FormsBitmap::set(int W, int H, const uchar *bits) {
+  delete b;
+  bitmap(new Fl_Bitmap(bits, W, H));
+}
+
+void Fl_FormsBitmap::draw() {
+  draw_box(box(), selection_color());
+  if (b) {fl_color(color()); b->draw(x(), y(), w(), h());}
+  draw_label();
+}
diff --git a/src/forms_compatability.cxx b/src/forms_compatability.cxx
new file mode 100755
index 000000000..763269af6
--- /dev/null
+++ b/src/forms_compatability.cxx
@@ -0,0 +1,153 @@
+// forms.C
+
+// Forms library compatability functions.
+// Many more functions are defined as inlines in forms.h!
+
+#include 
+#include 
+
+char fl_flip = 2;
+void fl_end_form() {
+  while (Fl_Group::current()) Fl_Group::current()->forms_end();
+}
+void Fl_Group::forms_end() {
+  // set the dimensions of a group to surround contents
+  if (children() && !w()) {
+    Fl_Widget*const* a = array();
+    Fl_Widget* o = *a++;
+    int rx = o->x();
+    int ry = o->y();
+    int rw = rx+o->w();
+    int rh = ry+o->h();
+    for (int i=children_-1; i--;) {
+      o = *a++;
+      if (o->x() < rx) rx = o->x();
+      if (o->y() < ry) ry = o->y();
+      if (o->x()+o->w() > rw) rw = o->x()+o->w();
+      if (o->y()+o->h() > rh) rh = o->y()+o->h();
+    }
+    x(rx);
+    y(ry);
+    w(rw-rx);
+    h(rh-ry);
+  }
+  // flip all the children's coordinate systems:
+  if (fl_flip) {
+    Fl_Widget* o = (type()>=FL_WINDOW) ? this : window();
+    int Y = o->h();
+    Fl_Widget*const* a = array();
+    for (int i=children(); i--;) {
+      Fl_Widget* o = *a++;
+      int newy = Y-o->y()-o->h();
+      o->y(newy);
+    }
+  }
+  end();
+}
+
+static int initargc;
+static char **initargv;
+
+void fl_initialize(int *argc, char **argv, const char *, FL_CMD_OPT *, int) {
+  initargc = *argc;
+  initargv = new char*[*argc+1];
+  int i,j;
+  for (i=0; i<=*argc; i++) initargv[i] = argv[i];
+  for (i=j=1; i<*argc; ) {
+    if (Fl::arg(*argc,argv,i));
+    else argv[j++] = argv[i++];
+  }
+  argv[j] = 0;
+  *argc = j;
+  if (fl_flip==2) fl_flip = 0;
+}
+
+char fl_modal_next; // set by fl_freeze_forms()
+
+void fl_show_form(Fl_Window *f,int place,int b,const char *n) {
+
+  Fl::enable_symbols();
+
+  f->label(n);
+  if (!b) f->clear_border();
+  if (fl_modal_next || b==FL_TRANSIENT) {f->set_modal(); fl_modal_next = 0;}
+
+  if (place & FL_PLACE_MOUSE) f->hotspot(f);
+
+  if (place & FL_PLACE_CENTER)
+    f->position((Fl::w()-f->w())/2, (Fl::h()-f->h())/2);
+
+  if (place & FL_PLACE_FULLSCREEN)
+    f->fullscreen();
+
+  if (place & (FL_PLACE_POSITION | FL_PLACE_GEOMETRY))
+    f->position(
+      (f->x() < 0) ? Fl::w()-f->w()+f->x()-1 : f->x(),
+      (f->y() < 0) ? Fl::h()-f->h()+f->y()-1 : f->y());
+
+// if (place & FL_PLACE_ASPECT) {
+// this is not yet implemented
+// it can be done by setting size_range().
+
+  if (place == FL_PLACE_FREE || place == FL_PLACE_SIZE)
+    f->free_position();
+
+  if (place == FL_PLACE_FREE || place & FL_FREE_SIZE)
+    if (!f->resizable()) f->resizable(f);
+
+  if (initargc) {f->show(initargc,initargv); initargc = 0;}
+  else f->show();
+}
+
+Fl_Widget *fl_do_forms(void) {
+  Fl_Widget *obj;
+  while (!(obj = Fl::readqueue())) if (!Fl::wait()) exit(0);
+  return obj;
+}
+
+Fl_Widget *fl_check_forms() {
+  Fl::check();
+  return Fl::readqueue();
+}
+
+void fl_set_graphics_mode(int /*r*/,int /*d*/) {}
+
+void Fl_FormsText::draw() {
+  draw_box();
+  align(align()|FL_ALIGN_INSIDE); // questionable method of compatability
+  draw_label();
+}
+
+// Create a forms button by selecting correct fltk subclass:
+
+#include 
+#include 
+
+Fl_Button *fl_add_button(uchar t,int x,int y,int w,int h,const char *l) {
+  Fl_Button *b;
+  switch (t) {
+  case FL_RETURN_BUTTON:
+  case FL_HIDDEN_RET_BUTTON:
+    b = new Fl_Return_Button(x,y,w,h,l);
+    break;
+  case FL_TOUCH_BUTTON:
+    b = new Fl_Repeat_Button(x,y,w,h,l);
+    break;
+  default:
+    b = new Fl_Button(x,y,w,h,l);
+  }
+  switch (t) {
+  case FL_TOGGLE_BUTTON:
+  case FL_RADIO_BUTTON:
+    b->type(t);
+    break;
+  case FL_HIDDEN_BUTTON:
+  case FL_HIDDEN_RET_BUTTON:
+    b->type(FL_HIDDEN_BUTTON);
+    break;
+  case FL_INOUT_BUTTON:
+    b->when(FL_WHEN_CHANGED);
+    break;
+  }
+  return b;
+}
diff --git a/src/forms_free.cxx b/src/forms_free.cxx
new file mode 100644
index 000000000..826211620
--- /dev/null
+++ b/src/forms_free.cxx
@@ -0,0 +1,50 @@
+// forms_free.C
+
+// Emulation of the Forms "free" widget.
+// This emulation allows the free demo to run, and has allowed
+// me to port several other programs, but it is in no way
+// complete.
+
+#include 
+#include 
+
+void Fl_Free::step(void *v) {
+  Fl_Free *f = (Fl_Free *)v;
+  f->handle(FL_STEP);
+  Fl::add_timeout(.01,step,v);
+}
+
+Fl_Free::Fl_Free(uchar t,int x,int y,int w,int h,const char *l,
+		 FL_HANDLEPTR hdl) :
+Fl_Widget(x,y,w,h,l) {
+  type(t);
+  hfunc = hdl;
+  if (t == FL_SLEEPING_FREE) deactivate();
+  if (t == FL_CONTINUOUS_FREE || t == FL_ALL_FREE)
+    Fl::add_timeout(.01,step,this);
+}
+
+Fl_Free::~Fl_Free() {
+  Fl::remove_timeout(step,this);
+  hfunc(this,FL_FREEMEM,0,0,0);
+}
+
+void Fl_Free::draw() {hfunc(this,FL_DRAW,0,0,0);}
+
+int Fl_Free::handle(int e) {
+  char key = Fl::event_key();
+  switch (e) {
+  case FL_FOCUS:
+    if (type()!=FL_INPUT_FREE && type()!=FL_ALL_FREE) return 0;
+    break;
+  case FL_PUSH:
+  case FL_DRAG:
+  case FL_RELEASE:
+    key = 4-Fl::event_button();
+    break;
+  case FL_SHORTCUT:
+    return 0;
+  }
+  if (hfunc(this, e, float(Fl::event_x()), float(Fl::event_y()), key)) do_callback();
+  return 1;
+}
diff --git a/src/forms_fselect.cxx b/src/forms_fselect.cxx
new file mode 100644
index 000000000..077f69f32
--- /dev/null
+++ b/src/forms_fselect.cxx
@@ -0,0 +1,38 @@
+// fselect.C
+
+// Emulate the Forms file chooser using the fltk file chooser.
+
+#include 
+#include 
+
+static char fl_directory[1024];
+static const char *fl_pattern;  // assummed passed value is static
+static char fl_filename[256];
+
+char* fl_show_file_selector(const char *message,const char *dir,
+			    const char *pat,const char *fname) {
+  if (dir && dir[0]) strncpy(fl_directory,dir,1023);
+  if (pat && pat[0]) fl_pattern = pat;
+  if (fname && fname[0]) strncpy(fl_filename,fname,255);
+  char *p = fl_directory+strlen(fl_directory);
+  if (p > fl_directory && *(p-1)!='/'
+#ifdef WIN32
+      && *(p-1)!='\\' && *(p-1)!=':'
+#endif
+      ) *p++ = '/';
+  strcpy(p,fl_filename);
+  const char *q = fl_file_chooser(message,fl_pattern,fl_directory);
+  if (!q) return 0;
+  strcpy(fl_directory, q);
+  p = (char *)filename_name(fl_directory);
+  strcpy(fl_filename, p);
+  if (p > fl_directory+1) p--;
+  *p = 0;
+  return (char *)q;
+}
+
+char*	fl_get_directory() {return fl_directory;}
+
+char*	fl_get_pattern() {return (char *)fl_pattern;}
+
+char*	fl_get_filename() {return fl_filename;}
diff --git a/src/forms_pixmap.cxx b/src/forms_pixmap.cxx
new file mode 100644
index 000000000..5263531ba
--- /dev/null
+++ b/src/forms_pixmap.cxx
@@ -0,0 +1,24 @@
+// forms_pixmap.C
+// Forms compatability widget to draw a pixmap
+
+#include 
+
+Fl_FormsPixmap::Fl_FormsPixmap(
+  Fl_Boxtype t, int x, int y, int w, int h, const char* l)
+: Fl_Widget(x, y, w, h, l) {
+  box(t);
+  b = 0;
+  color(FL_BLACK);
+  align(FL_ALIGN_BOTTOM);
+}
+
+void Fl_FormsPixmap::set(char*const* bits) {
+  delete b;
+  b = new Fl_Pixmap(bits);
+}
+
+void Fl_FormsPixmap::draw() {
+  draw_box(box(), selection_color());
+  if (b) {fl_color(color()); b->draw(x(), y(), w(), h());}
+  draw_label();
+}
diff --git a/src/forms_timer.cxx b/src/forms_timer.cxx
new file mode 100644
index 000000000..2b7694f80
--- /dev/null
+++ b/src/forms_timer.cxx
@@ -0,0 +1,127 @@
+// forms_timer.H
+
+// Emulate the Forms Timer object
+// You don't want to use this if you just want a timeout, call
+// Fl::add_timeout directly!
+
+#include 
+#include 
+#include 
+#ifdef WIN32
+# include  
+# include 
+#else
+# include 
+#endif
+#include 
+
+#define FL_TIMER_BLINKRATE	0.2
+
+void fl_gettime(long* sec, long* usec) {
+#ifdef WIN32
+  struct timeb tp;
+  ftime(&tp);
+  *sec = tp.time;
+  *usec = tp.millitm * 1000;
+#else
+  struct timeval tp;
+  struct timezone tzp;
+  gettimeofday(&tp, &tzp);
+  *sec = tp.tv_sec;
+  *usec = tp.tv_usec;
+#endif
+}
+
+void Fl_Timer::draw() {
+  int tt;
+  Fl_Color col;
+  char str[32];
+  if (!on || delay>0.0)
+    col = color();
+  else if ((int) (delay / FL_TIMER_BLINKRATE) % 2)
+    col = color();
+  else
+    col = selection_color();
+  draw_box(box(), col);
+  if (type() == FL_VALUE_TIMER && delay>0.0) {
+    double d = direction_ ? total-delay : delay;
+    if (d < 60.0)
+      sprintf(str, "%.1f", d);
+    else {
+      tt = (int) ((d+0.05) / 60.0);
+      sprintf(str, "%d:%04.1f", tt, d - 60.0 * tt);
+    }
+    fl_font(labelfont(), labelsize());
+    fl_color(labelcolor());
+    fl_draw(str, x(), y(), w(), h(), FL_ALIGN_CENTER);
+  } else
+    draw_label();
+}
+
+void Fl_Timer::stepcb(void* v) {
+  ((Fl_Timer*)v)->step();
+}
+
+void Fl_Timer::step() {
+  if (!on) return;
+  double lastdelay = delay;
+  long sec, usec; fl_gettime(&sec, &usec);
+  delay -= (double) (sec - lastsec) + (double) (usec - lastusec) / 1000000.0;
+  lastsec = sec; lastusec = usec;
+  if (lastdelay > 0.0 && delay <= 0.0) {
+    if (type() == FL_HIDDEN_TIMER) {
+      on = 0;
+      delay = 0;
+    } else {
+      redraw();
+      Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this);
+    }
+    do_callback();
+  } else {
+    if (type() == FL_VALUE_TIMER) redraw();
+    Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this);
+  }
+}
+
+int Fl_Timer::handle(int event) {
+  if (event == FL_RELEASE && delay <= 0) value(0.0);
+  return 0;
+}
+
+Fl_Timer::~Fl_Timer() {
+  Fl::remove_timeout(stepcb, this);
+}
+
+Fl_Timer::Fl_Timer(uchar t, int x, int y, int w, int h, const char* l)
+: Fl_Widget(x, y, w, h, l) {
+  box(FL_DOWN_BOX);
+  selection_color(FL_RED);
+  delay = 0;
+  on = 0;
+  direction_ = 0;
+  type(t);
+  if (t == FL_HIDDEN_TIMER) clear_visible();
+  if (t == FL_VALUE_TIMER) align(FL_ALIGN_LEFT);
+}
+
+void Fl_Timer::value(double d) {
+  delay = total = d;
+  on = (d > 0.0);
+  fl_gettime(&(lastsec), &(lastusec));
+  if (type() != FL_HIDDEN_TIMER) redraw();
+  Fl::remove_timeout(stepcb, this);
+  if (on) Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this);
+}
+
+void Fl_Timer::suspended(char d) {
+  if (!d) {
+    if (on) return;
+    on = (delay > 0.0);
+    fl_gettime(&(lastsec), &(lastusec));
+    if (on) Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this);
+  } else {
+    if (!on) return;
+    on = 0;
+    Fl::remove_timeout(stepcb, this);
+  }
+}
diff --git a/src/gl_draw.cxx b/src/gl_draw.cxx
new file mode 100644
index 000000000..574b50ced
--- /dev/null
+++ b/src/gl_draw.cxx
@@ -0,0 +1,121 @@
+// gl_draw.C
+
+// Functions from 
+// See also Fl_Gl_Window and gl_start.C
+
+#include 
+#if HAVE_GL
+
+#include 
+#include 
+#include 
+#include "Fl_Gl_Choice.H"
+#include "Fl_Font.H"
+#include 
+
+// stuff from fl_draw.H:
+void  fl_font(int fontid, int size);
+int   fl_height();	// using "size" should work ok
+int   fl_descent();
+void fl_measure(const char*, int& x, int& y);
+double fl_width(const char*);
+double fl_width(const char*, int n);
+double fl_width(uchar);
+unsigned long fl_xpixel(uchar i);
+
+void  gl_font(int fontid, int size) {fl_font(fontid, size);}
+int   gl_height() {return fl_height();}
+int   gl_descent() {return fl_descent();}
+double gl_width(const char* s) {return fl_width(s);}
+double gl_width(const char* s, int n) {return fl_width(s,n);}
+double gl_width(uchar c) {return fl_width(c);}
+
+void gl_draw(const char* str, int n) {
+#ifdef WIN32
+  if (!fl_current_xfont->listbase) {
+    int base = fl_current_xfont->metr.tmFirstChar;
+    int size = fl_current_xfont->metr.tmLastChar-base+1;
+    HFONT oldFid = (HFONT)SelectObject(fl_gc, fl_current_xfont->fid);
+    fl_current_xfont->listbase = glGenLists(size)-base;
+    wglUseFontBitmaps(fl_gc, base, size, fl_current_xfont->listbase+base); 
+    SelectObject(fl_gc, oldFid);
+  }
+#else
+  if (!fl_current_xfont->listbase) {
+    int base = fl_current_xfont->font->min_char_or_byte2;
+    int size = fl_current_xfont->font->max_char_or_byte2-base+1;
+//  int base = 0; int size = 256;
+    fl_current_xfont->listbase = glGenLists(size)-base;
+    glXUseXFont(fl_current_xfont->font->fid, base, size, 
+		fl_current_xfont->listbase+base);
+  }
+#endif
+  glListBase(fl_current_xfont->listbase);
+  glCallLists(n, GL_UNSIGNED_BYTE, str);
+}
+
+void gl_draw(const char* str, int n, int x, int y) {
+  glRasterPos2i(x, y);
+  gl_draw(str, n);
+}
+
+void gl_draw(const char* str) {
+  gl_draw(str, strlen(str));
+}
+
+void gl_draw(const char* str, int x, int y) {
+  gl_draw(str, strlen(str), x, y);
+}
+
+static void gl_draw_invert(const char* str, int n, int x, int y) {
+  glRasterPos2i(x, -y);
+  gl_draw(str, n);
+}
+
+void gl_draw(
+  const char* str, 	// the (multi-line) string
+  int x, int y, int w, int h, 	// bounding box
+  Fl_Align align) {
+  fl_draw(str, x, -y-h, w, h, align, gl_draw_invert);
+}
+
+void gl_measure(const char* str, int& x, int& y) {fl_measure(str,x,y);}
+
+void gl_rect(int x, int y, int w, int h) {
+  if (w < 0) {w = -w; x = x-w;}
+  if (h < 0) {h = -h; y = y-h;}
+  glBegin(GL_LINE_STRIP);
+  glVertex2i(x+w-1, y+h-1);
+  glVertex2i(x+w-1, y);
+  glVertex2i(x, y);
+  glVertex2i(x, y+h-1);
+  glVertex2i(x+w, y+h-1);
+  glEnd();
+}
+
+#if HAVE_GL_OVERLAY
+extern uchar fl_overlay;
+#endif
+
+void gl_color(Fl_Color i) {
+#if HAVE_GL_OVERLAY
+#ifdef WIN32
+  if (fl_overlay) {glIndexi(i ? i : FL_GRAY_RAMP); return;}
+#else
+  if (fl_overlay) {glIndexi(int(fl_xpixel(i))); return;}
+#endif
+#endif
+  uchar red, green, blue;
+  Fl::get_color(i, red, green, blue);
+  glColor3ub(red, green, blue);
+}
+  
+void gl_draw_image(const uchar* b, int x, int y, int w, int h, int d, int ld) {
+  if (!ld) ld = w*d;
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, ld/d);
+  glRasterPos2i(x,y);
+  glDrawPixels(w,h,d<4?GL_RGB:GL_RGBA,GL_UNSIGNED_BYTE,(const ulong*)b);
+}
+
+#endif
+
diff --git a/src/gl_start.cxx b/src/gl_start.cxx
new file mode 100644
index 000000000..255a78127
--- /dev/null
+++ b/src/gl_start.cxx
@@ -0,0 +1,98 @@
+// Code to switch current fltk drawing context in/out of GL "mode":
+
+// You MUST use gl_visual() to select the default visual before doing
+// show() of any windows.  Mesa will crash if you try to use a visual
+// not returned by glxChooseVisual.
+
+// This does not work with Fl_Double_Window's!  It will try to draw
+// into the front buffer.  Depending on the system this will either
+// crash or do nothing (when pixmaps are being used as back buffer
+// and GL is being done by hardware), work correctly (when GL is done
+// with software, such as Mesa), or draw into the front buffer and
+// be erased when the buffers are swapped (when double buffer hardware
+// is being used)
+
+#include 
+#if HAVE_GL
+
+#include 
+#include 
+#include 
+#include 
+
+#include "Fl_Gl_Choice.H"
+
+extern GLXContext fl_first_context; // in Fl_Gl_Choice.C
+extern int fl_clip_state_number; // in fl_rect.C
+
+static GLXContext context;
+static int clip_state_number;
+static int pw, ph;
+
+#ifdef WIN32
+static int default_mode;
+#endif
+
+Region XRectangleRegion(int x, int y, int w, int h); // in fl_rect.C
+
+void gl_start() {
+#ifdef WIN32
+  HDC hdc = fl_private_dc(Fl_Window::current(), default_mode,0);
+  if (!context) {
+    context = wglCreateContext(hdc);
+    if (!fl_first_context) fl_first_context = context;
+    else wglShareLists(fl_first_context, context);
+  }
+  wglMakeCurrent(hdc, context);
+#else
+  if (!context) {
+    context = glXCreateContext(fl_display, fl_visual, fl_first_context, 1);
+    if (!context) Fl::fatal("OpenGL does not support this visual");
+    if (!fl_first_context) fl_first_context = context;
+  }
+  glXMakeCurrent(fl_display, fl_window, context);
+  glXWaitX();
+#endif
+  if (pw != Fl_Window::current()->w() || ph != Fl_Window::current()->h()) {
+    pw = Fl_Window::current()->w();
+    ph = Fl_Window::current()->h();
+    glLoadIdentity();
+    glViewport(0, 0, pw, ph);
+    glOrtho(0, pw, 0, ph, -1, 1);
+    glDrawBuffer(GL_FRONT);
+  }
+  if (clip_state_number != fl_clip_state_number) {
+    clip_state_number = fl_clip_state_number;
+    int x, y, w, h;
+    if (fl_clip_box(0, 0, Fl_Window::current()->w(), Fl_Window::current()->h(),
+		    x, y, w, h)) {
+      fl_clip_region(XRectangleRegion(x,y,w,h));
+      glScissor(x, Fl_Window::current()->h()-(y+h), w, h);
+      glEnable(GL_SCISSOR_TEST);
+    } else {
+      glDisable(GL_SCISSOR_TEST);
+    }
+  }
+}
+
+void gl_finish() {
+#ifdef WIN32
+  glFlush();
+#else
+  glXWaitGL();
+#endif
+}
+
+int Fl::gl_visual(int mode, int *alist) {
+#ifdef WIN32
+  default_mode = mode;
+#else
+  Fl_Gl_Choice *c = Fl_Gl_Choice::find(mode,alist);
+  if (!c) return 0;
+  fl_visual = c->vis;
+  fl_colormap = c->colormap;
+#endif
+  return 1;
+}
+
+#endif
diff --git a/src/glut_compatability.cxx b/src/glut_compatability.cxx
new file mode 100755
index 000000000..e5d93bdc5
--- /dev/null
+++ b/src/glut_compatability.cxx
@@ -0,0 +1,377 @@
+// glut.C
+
+// Emulation of Glut using fltk.
+
+// GLUT is Copyright (c) Mark J. Kilgard, 1994, 1995, 1996.
+// "This program is freely distributable without licensing fees  and is
+// provided without guarantee or warrantee expressed or  implied. This
+// program is -not- in the public domain."
+
+// Although I have copied the GLUT API, none of my code is based on
+// any Glut implementation details and is therefore covered by the LGPL.
+
+#include 
+#if HAVE_GL
+
+#include 
+
+#define MAXWINDOWS 32
+static Fl_Glut_Window *windows[MAXWINDOWS+1];
+
+Fl_Glut_Window *glut_window;
+int glut_menu;
+void (*glut_menustate_function)(int);
+void (*glut_menustatus_function)(int,int,int);
+
+static void default_reshape(int w, int h) {glViewport(0,0,w,h);}
+
+void Fl_Glut_Window::make_current() {
+  glut_window = this;
+  if (shown()) Fl_Gl_Window::make_current();
+}
+
+static int indraw;
+void Fl_Glut_Window::draw() {
+  glut_window = this;
+  indraw = 1;
+  if (!valid()) {reshape(w(),h()); valid(1);}
+  display();
+  indraw = 0;
+}
+
+void glutSwapBuffers() {
+  if (!indraw) glut_window->swap_buffers();
+}
+
+void Fl_Glut_Window::draw_overlay() {
+  glut_window = this;
+  if (!valid()) {reshape(w(),h()); valid(1);}
+  overlaydisplay();
+}
+
+static void domenu(int, int, int);
+
+int Fl_Glut_Window::handle(int event) {
+  make_current();
+  int ex = Fl::event_x();
+  int ey = Fl::event_y();
+  int button;
+  switch (event) {
+
+  case FL_PUSH:
+    button = Fl::event_button()-1;
+    if (button<0) button = 0;
+    if (button>2) button = 2;
+    if (menu[button]) {domenu(menu[button],ex,ey); return 1;}
+    mouse_down |= 1<= FL_F && i < FL_F_Last) i = i-FL_F+1;
+	special(i,ex,ey);
+	return 1;
+      }
+      break;
+    }
+
+  case FL_HIDE:
+    if (visibility) visibility(GLUT_NOT_VISIBLE);
+    break;
+
+  case FL_SHOW:
+    if (visibility) visibility(GLUT_VISIBLE);
+    break;
+  }
+
+  return Fl_Gl_Window::handle(event);
+}
+
+static int glut_mode = GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH;
+
+void Fl_Glut_Window::_init() {
+  for (number=1; numberresizable(W);
+  if (initargc) {
+    W->show(initargc,initargv);
+    initargc = 0;
+  } else {
+    W->show();
+  }
+  W->make_current();
+  return W->number;
+}
+
+int glutCreateSubWindow(int win, int x, int y, int w, int h) {
+  Fl_Glut_Window *W = new Fl_Glut_Window(x,y,w,h,0);
+  windows[win]->add(W);
+  if (windows[win]->shown()) W->show();
+  W->make_current();
+  return W->number;
+}
+
+Fl_Glut_Window::~Fl_Glut_Window() {
+  if (glut_window == this) glut_window = 0;
+  windows[number] = 0;
+}
+
+void glutDestroyWindow(int win) {
+  // should destroy children!!!
+  delete windows[win];
+}
+
+void glutSetWindow(int win) {
+  windows[win]->make_current();
+}
+
+////////////////////////////////////////////////////////////////
+#include 
+
+struct menu {
+  void (*cb)(int);
+  Fl_Menu_Item *m;
+  int size;
+  int alloc;
+};
+
+#define MAXMENUS 32
+static menu menus[MAXMENUS+1];
+
+static void domenu(int n, int ex, int ey) {
+  glut_menu = n;
+  menu *m = &menus[n];
+  if (glut_menustate_function) glut_menustate_function(1);
+  if (glut_menustatus_function) glut_menustatus_function(1,ex,ey);
+  const Fl_Menu_Item* g = m->m->popup(Fl::event_x(), Fl::event_y(), 0);
+  if (g && g->callback_) ((void (*)(int))(g->callback_))(int(g->argument()));
+  if (glut_menustatus_function) glut_menustatus_function(0,ex,ey);
+  if (glut_menustate_function) glut_menustate_function(0);
+}
+
+int glutCreateMenu(void (*cb)(int)) {
+  int i;
+  for (i=1; icb = cb;
+  return glut_menu = i;
+}
+
+void glutDestroyMenu(int n) {
+  menu *m = &menus[n];
+  delete[] m->m;
+  m->m = 0;
+  m->cb = 0;
+  m->size = m->alloc = 0;
+}
+
+static Fl_Menu_Item* additem(menu *m) {
+  if (m->size+1 >= m->alloc) {
+    m->alloc = m->size*2+10;
+    Fl_Menu_Item* nm = new Fl_Menu_Item[m->alloc];
+    for (int i=0; isize; i++) nm[i] = m->m[i];
+    delete[] m->m;
+    m->m = nm;
+  }
+  int n = m->size++;
+  m->m[n+1].text = 0;
+  Fl_Menu_Item* i = &(m->m[n]);
+  i->shortcut_ = 0;
+  i->flags = 0;
+  i->labeltype_ = i->labelfont_ = i->labelsize_ = i->labelcolor_ = 0;
+  return i;
+}
+
+void glutAddMenuEntry(char *label, int value) {
+  menu *m = &menus[glut_menu];
+  Fl_Menu_Item* i = additem(m);
+  i->text = label;
+  i->callback_ = (Fl_Callback*)(m->cb);
+  i->user_data_ = (void *)value;
+}
+
+void glutAddSubMenu(char *label, int submenu) {
+  menu *m = &menus[glut_menu];
+  Fl_Menu_Item* i = additem(m);
+  i->text = label;
+  i->callback_ = 0;
+  i->user_data_ = (void *)(menus[submenu].m);
+  i->flags = FL_PUP_SUBMENU;
+}
+
+void glutChangeToMenuEntry(int item, char *label, int value) {
+  menu *m = &menus[glut_menu];
+  Fl_Menu_Item* i = &m->m[item-1];
+  i->text = label;
+  i->callback_ = (Fl_Callback*)(m->cb);
+  i->user_data_ = (void *)value;
+  i->flags = 0;
+}
+
+void glutChangeToSubMenu(int item, char *label, int submenu) {
+  menu *m = &menus[glut_menu];
+  Fl_Menu_Item* i = &m->m[item-1];
+  i->text = label;
+  i->callback_ = 0;
+  i->user_data_ = (void *)(menus[submenu].m);
+  i->flags = FL_PUP_SUBMENU;
+}
+
+void glutRemoveMenuItem(int item) {
+  menu *m = &menus[glut_menu];
+  if (item > m->size || item < 1) return;
+  for (int i = item-1; i <= m->size; i++) m->m[i] = m->m[i+1];
+  m->size--;
+}
+
+////////////////////////////////////////////////////////////////
+
+int glutGet(GLenum type) {
+  switch (type) {
+  case GLUT_RETURN_ZERO: return 0;
+  case GLUT_WINDOW_X: return glut_window->x();
+  case GLUT_WINDOW_Y: return glut_window->y();
+  case GLUT_WINDOW_WIDTH: return glut_window->w();
+  case GLUT_WINDOW_HEIGHT: return glut_window->h();
+  case GLUT_WINDOW_PARENT:
+    if (glut_window->parent())
+      return ((Fl_Glut_Window *)(glut_window->parent()))->number;
+    else
+      return 0;
+//case GLUT_WINDOW_NUM_CHILDREN:
+//case GLUT_WINDOW_CURSOR: return 
+  case GLUT_SCREEN_WIDTH: return Fl::w();
+  case GLUT_SCREEN_HEIGHT: return Fl::h();
+//case GLUT_SCREEN_WIDTH_MM:
+//case GLUT_SCREEN_HEIGHT_MM:
+  case GLUT_MENU_NUM_ITEMS: return menus[glut_menu].size;
+  case GLUT_DISPLAY_MODE_POSSIBLE: return Fl_Gl_Window::can_do(glut_mode);
+  case GLUT_INIT_WINDOW_X: return initx;
+  case GLUT_INIT_WINDOW_Y: return inity;
+  case GLUT_INIT_WINDOW_WIDTH: return initw;
+  case GLUT_INIT_WINDOW_HEIGHT: return inith;
+  case GLUT_INIT_DISPLAY_MODE: return glut_mode;
+//case GLUT_ELAPSED_TIME:
+  case GLUT_WINDOW_BUFFER_SIZE:
+    if (glutGet(GLUT_WINDOW_RGBA))
+      return glutGet(GLUT_WINDOW_RED_SIZE)+
+	glutGet(GLUT_WINDOW_GREEN_SIZE)+
+	glutGet(GLUT_WINDOW_BLUE_SIZE)+
+	glutGet(GLUT_WINDOW_ALPHA_SIZE);
+    else
+      return glutGet(GLUT_WINDOW_COLORMAP_SIZE);
+  default: {GLint p; glGetIntegerv(type, &p); return p;}
+  }
+}
+
+int glutLayerGet(GLenum type) {
+  switch (type) {
+  case GLUT_OVERLAY_POSSIBLE: return glut_window->can_do_overlay();
+//case GLUT_LAYER_IN_USE:
+//case GLUT_HAS_OVERLAY:
+  case GLUT_TRANSPARENT_INDEX: return 0; // true for SGI
+  case GLUT_NORMAL_DAMAGED: return glut_window->damage();
+  case GLUT_OVERLAY_DAMAGED: return 1; // kind of works...
+  default: return 0;
+  }
+}
+
+#endif
+// End of glut.C
diff --git a/src/glut_font.cxx b/src/glut_font.cxx
new file mode 100644
index 000000000..751fd6f8c
--- /dev/null
+++ b/src/glut_font.cxx
@@ -0,0 +1,32 @@
+// glut_font.C
+
+// (sort of) emulation of Glut's bitmap drawing functions, using FL's
+// font stuff.  Not all the fonts match!
+
+#include 
+#if HAVE_GL
+
+#include 
+#include 
+
+Glut_Bitmap_Font glutBitmap9By15 = {FL_SCREEN, 15};
+Glut_Bitmap_Font glutBitmap8By13 = {FL_SCREEN, 13};
+Glut_Bitmap_Font glutBitmapTimesRoman10 = {FL_TIMES, 10};
+Glut_Bitmap_Font glutBitmapTimesRoman24 = {FL_TIMES, 24};
+Glut_Bitmap_Font glutBitmapHelvetica10 = {FL_HELVETICA, 10};
+Glut_Bitmap_Font glutBitmapHelvetica12 = {FL_HELVETICA, 12};
+Glut_Bitmap_Font glutBitmapHelvetica18 = {FL_HELVETICA, 18};
+
+void glutBitmapCharacter(void *font, int character) {
+  gl_font(((Glut_Bitmap_Font *)font)->font,((Glut_Bitmap_Font *)font)->size);
+  char a[1]; a[0] = character;
+  gl_draw(a,1);
+}
+
+int glutBitmapWidth(int font, int character) {
+  gl_font(((Glut_Bitmap_Font *)font)->font,((Glut_Bitmap_Font *)font)->size);
+  return int(gl_width(character)+.5);
+}
+
+#endif
+
diff --git a/src/mediumarrow.h b/src/mediumarrow.h
new file mode 100644
index 000000000..8a1fe8cbc
--- /dev/null
+++ b/src/mediumarrow.h
@@ -0,0 +1,6 @@
+#define mediumarrow_width 16
+#define mediumarrow_height 16
+static unsigned char mediumarrow_bits[] = {
+   0x40, 0x00, 0x60, 0x00, 0x70, 0x00, 0x78, 0x00, 0xfc, 0x3f, 0x78, 0x00,
+   0x70, 0x00, 0x60, 0x02, 0x40, 0x06, 0x00, 0x0e, 0x00, 0x1e, 0xfc, 0x3f,
+   0x00, 0x1e, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x02};
diff --git a/src/ns.xbm b/src/ns.xbm
new file mode 100644
index 000000000..f1ea18e1b
--- /dev/null
+++ b/src/ns.xbm
@@ -0,0 +1,8 @@
+#define ns_width 16
+#define ns_height 16
+#define ns_x_hot 8
+#define ns_y_hot 8
+static unsigned char ns_bits[] = {
+   0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0x80, 0x01, 0x80, 0x01,
+   0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
+   0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00};
diff --git a/src/ns_mask.xbm b/src/ns_mask.xbm
new file mode 100644
index 000000000..a69f261bb
--- /dev/null
+++ b/src/ns_mask.xbm
@@ -0,0 +1,8 @@
+#define ns_mask_width 16
+#define ns_mask_height 16
+#define ns_mask_x_hot 8
+#define ns_mask_y_hot 8
+static unsigned char ns_mask_bits[] = {
+   0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xc0, 0x03,
+   0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xf0, 0x0f,
+   0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01};
diff --git a/src/numericsort.c b/src/numericsort.c
new file mode 100644
index 000000000..17149be6f
--- /dev/null
+++ b/src/numericsort.c
@@ -0,0 +1,53 @@
+/* My own scandir sorting function, useful for the film industry where
+   we have many files with numbers in their names: */
+
+#include 
+#include 
+#include 
+#include 
+
+#ifdef WIN32
+#include 
+#else
+#if HAVE_DIRENT_H
+# include 
+#else
+# define dirent direct
+# if HAVE_SYS_NDIR_H
+#  include 
+# endif
+# if HAVE_SYS_DIR_H
+#  include 
+# endif
+# if HAVE_NDIR_H
+#  include 
+# endif
+#endif
+#endif
+
+int numericsort(const struct dirent **A, const struct dirent **B) {
+  const char* a = (*A)->d_name;
+  const char* b = (*B)->d_name;
+  int ret = 0;
+  for (;;) {
+    if (isdigit(*a) && isdigit(*b)) {
+      int zdiff,diff,magdiff;
+      zdiff = 0;
+      while (*a == '0') {a++; zdiff++;}
+      while (*b == '0') {b++; zdiff--;}
+      while (isdigit(*a) && *a == *b) {a++; b++;}
+      diff = (isdigit(*a) && isdigit(*b)) ? *a - *b : 0;
+      magdiff = 0;
+      while (isdigit(*a)) {magdiff++; a++;}
+      while (isdigit(*b)) {magdiff--; b++;}
+      if (ret);
+      else if (magdiff) ret = magdiff;
+      else if (diff) ret = diff;
+      else if (zdiff) ret = zdiff;
+    } else if (*a == *b) {
+      if (!*a) return ret;
+      a++; b++;
+    } else
+      return (*a-*b);
+  }
+}
diff --git a/src/scandir.c b/src/scandir.c
new file mode 100644
index 000000000..e3b60bedf
--- /dev/null
+++ b/src/scandir.c
@@ -0,0 +1,128 @@
+/* Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library 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.  */
+
+#ifdef WIN32
+#include "scandir_win32.c"
+#else
+
+#include 
+
+#if HAVE_SCANDIR
+#else
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if HAVE_DIRENT_H
+# include 
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+#  include 
+# endif
+# if HAVE_SYS_DIR_H
+#  include 
+# endif
+# if HAVE_NDIR_H
+#  include 
+# endif
+#endif
+
+int
+scandir (const char *dir, struct dirent ***namelist,
+	 int (*select)(const struct dirent *),
+	 int (*compar)(const struct dirent **, const struct dirent **))
+{
+  DIR *dp = opendir (dir);
+  struct dirent **v = NULL;
+  size_t vsize = 0, i;
+  struct dirent *d;
+  int save;
+
+  if (dp == NULL)
+    return -1;
+
+  save = errno;
+  errno = 0;
+
+  i = 0;
+  while ((d = readdir (dp)) != NULL)
+    if (select == NULL || (*select) (d))
+      {
+      size_t dsize;
+
+      if (i == vsize)
+        {
+          struct dirent **new;
+          if (vsize == 0)
+            vsize = 10;
+          else
+            vsize *= 2;
+          new = (struct dirent **) realloc (v, vsize * sizeof (*v));
+          if (new == NULL)
+            {
+            lose:
+              errno = ENOMEM;
+              break;
+            }
+          v = new;
+        }
+
+#define _D_EXACT_NAMLEN(d) (strlen ((d)->d_name))
+#define _D_ALLOC_NAMLEN(d) (sizeof (d)->d_name > 1 ? sizeof (d)->d_name : \
+                              _D_EXACT_NAMLEN (d) + 1)
+
+      dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d;
+      v[i] = (struct dirent *) malloc (dsize);
+      if (v[i] == NULL)
+        goto lose;
+
+      memcpy (v[i++], d, dsize);
+      }
+
+  if (errno != 0)
+    {
+      save = errno;
+      (void) closedir (dp);
+      while (i > 0)
+      free (v[--i]);
+      free (v);
+      errno = save;
+      return -1;
+    }
+
+  (void) closedir (dp);
+  errno = save;
+
+  /* Sort the list if we have a comparison function to sort with.  */
+  if (compar) qsort (v, i, sizeof (*v), compar);
+  *namelist = v;
+  return i;
+}
+
+int alphasort (const struct dirent **a, const struct dirent **b) {
+  return strcmp ((*a)->d_name, (*b)->d_name);
+}
+
+#endif
+#endif
diff --git a/src/scandir_win32.c b/src/scandir_win32.c
new file mode 100644
index 000000000..ea3d18723
--- /dev/null
+++ b/src/scandir_win32.c
@@ -0,0 +1,79 @@
+// scandir_win32.C
+
+// Emulation of posix scandir() call
+
+#include 
+#include 
+#include 
+#include 
+
+int scandir(const char *dirname, struct dirent ***namelist,
+    int (*select)(const struct dirent *),
+    int (*compar)(const struct dirent **, const struct dirent **)) {
+
+  int len = strlen(dirname);
+  char *findIn = new char[len+5]; strcpy(findIn, dirname);
+  for (char *d = findIn; *d; d++) if (*d=='/') *d='\\';
+  if ((len==0)) { strcpy(findIn, ".\\*"); }
+  if ((len==1)&& (d[-1]=='.')) { strcpy(findIn, ".\\*"); }
+  if ((len>0) && (d[-1]=='\\')) { *d++ = '*'; *d = 0; }
+  if ((len>1) && (d[-1]=='.') && (d[-2]=='\\')) { d[-1] = '*'; }
+  
+  WIN32_FIND_DATA find;
+  HANDLE h;
+  int nDir = 0, NDir = 0;
+  struct dirent **dir = 0, *selectDir;
+  /*
+  selectDir = (struct dirent*)new char[sizeof(dirent)+1];
+  strcpy(selectDir->d_name, ".");
+  dir[0] = selectDir;
+  selectDir = (struct dirent*)new char[sizeof(dirent)+2];
+  strcpy(selectDir->d_name, "..");
+  dir[1] = selectDir;
+  */
+  unsigned long ret;
+
+  if ((h=FindFirstFile(findIn, &find))==INVALID_HANDLE_VALUE) {
+    ret = GetLastError();
+    if (ret != ERROR_NO_MORE_FILES) {
+      // TODO: return some error code
+    }
+    *namelist = dir;
+    return nDir;
+  }
+  do {
+    selectDir=(struct dirent*)new char[sizeof(dirent)+strlen(find.cFileName)];
+    strcpy(selectDir->d_name, find.cFileName);
+    if (!select || (*select)(selectDir)) {
+      if (nDir==NDir) {
+	struct dirent **tempDir = new struct dirent*[NDir+33];
+	if (NDir) memcpy(tempDir, dir, sizeof(struct dirent*)*NDir);
+	if (dir) delete dir;
+	dir = tempDir;
+	NDir += 32;
+      }
+      dir[nDir] = selectDir;
+      nDir++;
+      dir[nDir] = 0;
+    } else {
+      delete selectDir;
+    }
+  } while (FindNextFile(h, &find));
+  ret = GetLastError();
+  if (ret != ERROR_NO_MORE_FILES) {
+    // TODO: return some error code
+  }
+  FindClose(h);
+
+  delete findIn;
+
+  if (compar) qsort (dir, nDir, sizeof(*dir),
+		     (int(*)(const void*, const void*))compar);
+
+  *namelist = dir;
+  return nDir;
+}
+
+int alphasort (const struct dirent **a, const struct dirent **b) {
+  return strcmp ((*a)->d_name, (*b)->d_name);
+}
diff --git a/src/slowarrow.h b/src/slowarrow.h
new file mode 100644
index 000000000..46a572c97
--- /dev/null
+++ b/src/slowarrow.h
@@ -0,0 +1,6 @@
+#define slowarrow_width 16
+#define slowarrow_height 16
+static unsigned char slowarrow_bits[] = {
+   0x40, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0xf0, 0x0f, 0x60, 0x00,
+   0x60, 0x00, 0x40, 0x02, 0x40, 0x02, 0x00, 0x06, 0x00, 0x06, 0xf0, 0x0f,
+   0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0x02};
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 000000000..384a05103
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,51 @@
+ALL =	adjuster arc ask bitmap boxtype browser button buttons checkers \
+	clock colbrowser color_chooser cube cursor curve demo doublebuffer \
+	file_chooser fonts forms fractals fullscreen gl_overlay glpuzzle \
+	hello iconize image input keyboard label list_visuals mandelbrot \
+	menubar message minimum navigation output overlay pixmap \
+	pixmap_browser radio resizebox scroll shape shiny subwindow \
+	symbols tabs tile valuators fast_slow resize pack inactive style
+
+all:	${ALL}
+
+include ../makeinclude
+
+${ALL} :  ../lib/$(LIBNAME)
+
+.SUFFIXES : .C .c .o .do
+
+.C:
+	@echo $@:
+	@$(CXX) -I.. $(CXXFLAGS) $< -L../lib -lfltk ${LDLIBS} -o $@
+
+# Programs needing the OpenGL libraries:
+cube: cube.C
+	@echo $@:
+	@${CXX} -I.. ${CXXFLAGS} cube.C -L../lib -lfltk ${GLDLIBS} -o $@
+fullscreen: fullscreen.C
+	@echo $@:
+	@${CXX} -I.. ${CXXFLAGS} fullscreen.C -L../lib -lfltk ${GLDLIBS} -o $@
+fractals: fractals.C
+	@echo $@:
+	@${CXX} -I.. ${CXXFLAGS} fractals.C -L../lib -lfltk ${GLDLIBS} -o $@
+gl_overlay: gl_overlay.C
+	@echo $@:
+	@${CXX} -I.. ${CXXFLAGS} gl_overlay.C -L../lib -lfltk ${GLDLIBS} -o $@
+glpuzzle: glpuzzle.C
+	@echo $@:
+	@${CXX} -I.. ${CXXFLAGS} glpuzzle.C -L../lib -lfltk ${GLDLIBS} -o $@
+shape: shape.C
+	@echo $@:
+	@${CXX} -I.. ${CXXFLAGS} shape.C -L../lib -lfltk ${GLDLIBS} -o $@
+shiny: shiny.C
+	@echo $@:
+	@${CXX} -I.. ${CXXFLAGS} shiny.C -L../lib -lfltk ${GLDLIBS} -o $@
+
+# If you have libjpeg installed, you might want to try this test program:
+
+jpeg_image: jpeg_image.C
+	@echo $@:
+	@${CXX} -I.. ${CXXFLAGS} -I../../../local/jpeg-6b -L../../../local/jpeg-6b jpeg_image.C -L../lib -lfltk ${LDLIBS} -ljpeg -lXext -o $@
+
+clean:
+	-rm -f ${ALL} jpeg_image *~
diff --git a/test/README b/test/README
new file mode 100644
index 000000000..ee63859aa
--- /dev/null
+++ b/test/README
@@ -0,0 +1,32 @@
+This directory contains tests and demos of FL.  In most cases you can
+learn a lot about how to program FL by looking at the source code.
+
+Type "make" to compile them all.
+
+The program "demo" is a graphical interface to run all the demos.
+(you may recognize this as a rewrite of an XForms program).
+
+Some of the more interesting programs:
+
+fractals:	A GLUT program with FL controls added to it
+
+glpuzzle:	A GLUT program with no modifications
+
+fullscreen:	Demo of how to make your window toggle to fill screen
+
+list_visuals:	necessary to debug X visual stuff
+
+mandelbrot:	A true application, using panels built in Fluid
+
+menubar:	Demo of how FL's menus work
+
+shiny:		Demo of drawing FL's controls using OpenGL
+
+forms:		An XForms program to demonstrate emulation
+
+colbrowser:	Another XForms program that is actually useful
+
+The program "fl_image" can be compiled if you have the jpeg library.
+The makefile assummes that the jpeg distribution resides in
+../../jpeg-6a/.  Perhaps edit the Makefile to fix this, and type
+"make fl_image" to make this jpeg file viewer.
diff --git a/test/adjuster.cxx b/test/adjuster.cxx
new file mode 100644
index 000000000..68e4c5d7d
--- /dev/null
+++ b/test/adjuster.cxx
@@ -0,0 +1,37 @@
+/* 	Test the adjuster	*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+void adjcb(Fl_Widget *o, void *v) {
+  Fl_Adjuster *a = (Fl_Adjuster*)o;
+  Fl_Box *b = (Fl_Box *)v;
+  a->format((char *)(b->label()));
+  b->redraw();
+}
+
+int main(int, char ** argv) {
+   Fl_Window window(320,100,argv[0]);
+
+   char buf1[100];
+   Fl_Box b1(FL_DOWN_BOX,20,30,80,25,buf1);
+   b1.color(FL_WHITE);
+   Fl_Adjuster a1(20+80,30,3*25,25);
+   a1.callback(adjcb,&b1);
+   adjcb(&a1,&b1);
+
+   char buf2[100];
+   Fl_Box b2(FL_DOWN_BOX,20+80+4*25,30,80,25,buf2);
+   b2.color(FL_WHITE);
+   Fl_Adjuster a2(b2.x()+b2.w(),10,25,3*25);
+   a2.callback(adjcb,&b2);
+   adjcb(&a2,&b2);
+
+   window.resizable(window);
+   window.end();
+   window.show();
+   return Fl::run();
+}
diff --git a/test/arc.cxx b/test/arc.cxx
new file mode 100755
index 000000000..1c574cde5
--- /dev/null
+++ b/test/arc.cxx
@@ -0,0 +1,70 @@
+// Test fl_arc
+
+#include 
+#include 
+#include 
+#include 
+
+double args[6] = {140, 140, 50, 0, 360, 0};
+const char* name[6] = {"X", "Y", "R", "start", "end", "rotate"};
+
+class Drawing : public Fl_Widget {
+  void draw() {
+    fl_clip(x(),y(),w(),h());
+    fl_color(FL_DARK3);
+    fl_rectf(x(),y(),w(),h());
+    fl_push_matrix();
+    if (args[5]) {
+      fl_translate(x()+w()/2.0, y()+h()/2.0);
+      fl_rotate(args[5]);
+      fl_translate(-(x()+w()/2.0), -(y()+h()/2.0));
+    }
+    fl_color(FL_WHITE);
+    fl_translate(x(),y());
+    fl_begin_complex_polygon();
+    fl_arc(args[0],args[1],args[2],args[3],args[4]);
+    fl_gap();
+    fl_arc(140,140,20,0,-360);
+    fl_end_complex_polygon();
+    fl_color(FL_RED);
+    fl_begin_line();
+    fl_arc(args[0],args[1],args[2],args[3],args[4]);
+    fl_end_line();
+    fl_pop_matrix();
+    fl_pop_clip();
+  }
+public:
+  Drawing(int X,int Y,int W,int H) : Fl_Widget(X,Y,W,H) {}
+};
+
+Drawing *d;
+
+void slider_cb(Fl_Widget* o, void* v) {
+  Fl_Slider* s = (Fl_Slider*)o;
+  args[long(v)] = s->value();
+  d->redraw();
+}
+
+int main(int argc, char** argv) {
+  Fl_Double_Window window(300,500);
+  Drawing drawing(10,10,280,280);
+  d = &drawing;
+
+  int y = 300;
+  for (int n = 0; n<6; n++) {
+    Fl_Slider* s = new Fl_Hor_Value_Slider(50,y,240,25,name[n]); y += 25;
+    if (n<3) {s->minimum(0); s->maximum(300);}
+    else if (n==5) {s->minimum(0); s->maximum(360);}
+    else {s->minimum(-360); s->maximum(360);}
+    s->step(1);
+    s->value(args[n]);
+    s->align(FL_ALIGN_LEFT);
+    s->callback(slider_cb, (void*)n);
+  }
+
+  window.end();
+  window.show(argc,argv);
+  return Fl::run();
+}
+
+
diff --git a/test/ask.cxx b/test/ask.cxx
new file mode 100644
index 000000000..304ae1d71
--- /dev/null
+++ b/test/ask.cxx
@@ -0,0 +1,90 @@
+/* 	ask.C
+
+	Demonstrates how to use readqueue to see if a button has been
+	pushed, and to see if a window has been closed, thus avoiding
+	the need to define callbacks.
+
+	This also demonstrates how to trap attempts by the user to
+	close the last window by overriding Fl::exit
+
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int get_string(char*buffer) {
+  Fl_Window window(320,75);
+  Fl_Input input(60, 10, 250, 25, "Input:");
+  input.value(buffer);
+  Fl_Button cancel(60, 40, 80, 25, "cancel");
+  Fl_Return_Button ok(150, 40, 80, 25, "OK");
+  window.hotspot(&cancel); // you must position modal windows
+  window.end();
+  window.set_modal();
+  window.show();
+  for (;;) {
+    Fl::wait();
+    Fl_Widget *o;
+    while ((o = Fl::readqueue())) {
+      if (o == &ok) {
+	strcpy(buffer,input.value());
+	return 1;
+      } else if (o == &cancel || o == &window) {
+	return 0;
+      }
+    }
+  }
+}
+
+void rename_me(Fl_Widget*o) {
+  if (get_string((char*)(o->label()))) o->redraw();
+}
+
+#if 1
+#include 
+#include 
+
+void window_callback(Fl_Widget*, void*) {
+  if (!fl_ask("Are you sure you want to quit?")) return;
+  exit(0);
+}
+#endif
+
+int main(int argc, char **argv) {
+  char buffer[128] = "test text";
+
+#if 1
+// this is a test to make sure automatic destructors work.  Pop up
+// the question dialog several times and make sure it don't crash.
+
+  Fl_Window window(200, 55);
+  Fl_Return_Button b(20, 10, 160, 35, buffer); b.callback(rename_me);
+  window.add(b);
+  window.resizable(&b);
+  window.show(argc, argv);
+
+// Also we test to see if the exit callback works:
+  window.callback(window_callback);
+
+  return Fl::run();
+
+#else
+// This is the demo as written in the documentation, it only creates
+// the popup window once:
+
+  if (get_string(buffer)) {
+    puts(buffer);
+  } else {
+    puts("cancel");
+  }
+  return 0;
+
+#endif
+
+}
+    
diff --git a/test/bitmap.cxx b/test/bitmap.cxx
new file mode 100644
index 000000000..245397843
--- /dev/null
+++ b/test/bitmap.cxx
@@ -0,0 +1,114 @@
+//	test how bitmap label type draws
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define sorceress_width 75
+#define sorceress_height 75
+static uchar sorceress_bits[] = {
+   0xfc, 0x7e, 0x40, 0x20, 0x90, 0x00, 0x07, 0x80, 0x23, 0x00, 0x00, 0xc6,
+   0xc1, 0x41, 0x98, 0xb8, 0x01, 0x07, 0x66, 0x00, 0x15, 0x9f, 0x03, 0x47,
+   0x8c, 0xc6, 0xdc, 0x7b, 0xcc, 0x00, 0xb0, 0x71, 0x0e, 0x4d, 0x06, 0x66,
+   0x73, 0x8e, 0x8f, 0x01, 0x18, 0xc4, 0x39, 0x4b, 0x02, 0x23, 0x0c, 0x04,
+   0x1e, 0x03, 0x0c, 0x08, 0xc7, 0xef, 0x08, 0x30, 0x06, 0x07, 0x1c, 0x02,
+   0x06, 0x30, 0x18, 0xae, 0xc8, 0x98, 0x3f, 0x78, 0x20, 0x06, 0x02, 0x20,
+   0x60, 0xa0, 0xc4, 0x1d, 0xc0, 0xff, 0x41, 0x04, 0xfa, 0x63, 0x80, 0xa1,
+   0xa4, 0x3d, 0x00, 0x84, 0xbf, 0x04, 0x0f, 0x06, 0xfc, 0xa1, 0x34, 0x6b,
+   0x01, 0x1c, 0xc9, 0x05, 0x06, 0xc7, 0x06, 0xbe, 0x11, 0x1e, 0x43, 0x30,
+   0x91, 0x05, 0xc3, 0x61, 0x02, 0x30, 0x1b, 0x30, 0xcc, 0x20, 0x11, 0x00,
+   0xc1, 0x3c, 0x03, 0x20, 0x0a, 0x00, 0xe8, 0x60, 0x21, 0x00, 0x61, 0x1b,
+   0xc1, 0x63, 0x08, 0xf0, 0xc6, 0xc7, 0x21, 0x03, 0xf8, 0x08, 0xe1, 0xcf,
+   0x0a, 0xfc, 0x4d, 0x99, 0x43, 0x07, 0x3c, 0x0c, 0xf1, 0x9f, 0x0b, 0xfc,
+   0x5b, 0x81, 0x47, 0x02, 0x16, 0x04, 0x31, 0x1c, 0x0b, 0x1f, 0x17, 0x89,
+   0x4d, 0x06, 0x1a, 0x04, 0x31, 0x38, 0x02, 0x07, 0x56, 0x89, 0x49, 0x04,
+   0x0b, 0x04, 0xb1, 0x72, 0x82, 0xa1, 0x54, 0x9a, 0x49, 0x04, 0x1d, 0x66,
+   0x50, 0xe7, 0xc2, 0xf0, 0x54, 0x9a, 0x58, 0x04, 0x0d, 0x62, 0xc1, 0x1f,
+   0x44, 0xfc, 0x51, 0x90, 0x90, 0x04, 0x86, 0x63, 0xe0, 0x74, 0x04, 0xef,
+   0x31, 0x1a, 0x91, 0x00, 0x02, 0xe2, 0xc1, 0xfd, 0x84, 0xf9, 0x30, 0x0a,
+   0x91, 0x00, 0x82, 0xa9, 0xc0, 0xb9, 0x84, 0xf9, 0x31, 0x16, 0x81, 0x00,
+   0x42, 0xa9, 0xdb, 0x7f, 0x0c, 0xff, 0x1c, 0x16, 0x11, 0x00, 0x02, 0x28,
+   0x0b, 0x07, 0x08, 0x60, 0x1c, 0x02, 0x91, 0x00, 0x46, 0x29, 0x0e, 0x00,
+   0x00, 0x00, 0x10, 0x16, 0x11, 0x02, 0x06, 0x29, 0x04, 0x00, 0x00, 0x00,
+   0x10, 0x16, 0x91, 0x06, 0xa6, 0x2a, 0x04, 0x00, 0x00, 0x00, 0x18, 0x24,
+   0x91, 0x04, 0x86, 0x2a, 0x04, 0x00, 0x00, 0x00, 0x18, 0x27, 0x93, 0x04,
+   0x96, 0x4a, 0x04, 0x00, 0x00, 0x00, 0x04, 0x02, 0x91, 0x04, 0x86, 0x4a,
+   0x0c, 0x00, 0x00, 0x00, 0x1e, 0x23, 0x93, 0x04, 0x56, 0x88, 0x08, 0x00,
+   0x00, 0x00, 0x90, 0x21, 0x93, 0x04, 0x52, 0x0a, 0x09, 0x80, 0x01, 0x00,
+   0xd0, 0x21, 0x95, 0x04, 0x57, 0x0a, 0x0f, 0x80, 0x27, 0x00, 0xd8, 0x20,
+   0x9d, 0x04, 0x5d, 0x08, 0x1c, 0x80, 0x67, 0x00, 0xe4, 0x01, 0x85, 0x04,
+   0x79, 0x8a, 0x3f, 0x00, 0x00, 0x00, 0xf4, 0x11, 0x85, 0x06, 0x39, 0x08,
+   0x7d, 0x00, 0x00, 0x18, 0xb7, 0x10, 0x81, 0x03, 0x29, 0x12, 0xcb, 0x00,
+   0x7e, 0x30, 0x28, 0x00, 0x85, 0x03, 0x29, 0x10, 0xbe, 0x81, 0xff, 0x27,
+   0x0c, 0x10, 0x85, 0x03, 0x29, 0x32, 0xfa, 0xc1, 0xff, 0x27, 0x94, 0x11,
+   0x85, 0x03, 0x28, 0x20, 0x6c, 0xe1, 0xff, 0x07, 0x0c, 0x01, 0x85, 0x01,
+   0x28, 0x62, 0x5c, 0xe3, 0x8f, 0x03, 0x4e, 0x91, 0x80, 0x05, 0x39, 0x40,
+   0xf4, 0xc2, 0xff, 0x00, 0x9f, 0x91, 0x84, 0x05, 0x31, 0xc6, 0xe8, 0x07,
+   0x7f, 0x80, 0xcd, 0x00, 0xc4, 0x04, 0x31, 0x06, 0xc9, 0x0e, 0x00, 0xc0,
+   0x48, 0x88, 0xe0, 0x04, 0x79, 0x04, 0xdb, 0x12, 0x00, 0x30, 0x0c, 0xc8,
+   0xe4, 0x04, 0x6d, 0x06, 0xb6, 0x23, 0x00, 0x18, 0x1c, 0xc0, 0x84, 0x04,
+   0x25, 0x0c, 0xff, 0xc2, 0x00, 0x4e, 0x06, 0xb0, 0x80, 0x04, 0x3f, 0x8a,
+   0xb3, 0x83, 0xff, 0xc3, 0x03, 0x91, 0x84, 0x04, 0x2e, 0xd8, 0x0f, 0x3f,
+   0x00, 0x00, 0x5f, 0x83, 0x84, 0x04, 0x2a, 0x70, 0xfd, 0x7f, 0x00, 0x00,
+   0xc8, 0xc0, 0x84, 0x04, 0x4b, 0xe2, 0x2f, 0x01, 0x00, 0x08, 0x58, 0x60,
+   0x80, 0x04, 0x5b, 0x82, 0xff, 0x01, 0x00, 0x08, 0xd0, 0xa0, 0x84, 0x04,
+   0x72, 0x80, 0xe5, 0x00, 0x00, 0x08, 0xd2, 0x20, 0x44, 0x04, 0xca, 0x02,
+   0xff, 0x00, 0x00, 0x08, 0xde, 0xa0, 0x44, 0x04, 0x82, 0x02, 0x6d, 0x00,
+   0x00, 0x08, 0xf6, 0xb0, 0x40, 0x02, 0x82, 0x07, 0x3f, 0x00, 0x00, 0x08,
+   0x44, 0x58, 0x44, 0x02, 0x93, 0x3f, 0x1f, 0x00, 0x00, 0x30, 0x88, 0x4f,
+   0x44, 0x03, 0x83, 0x23, 0x3e, 0x00, 0x00, 0x00, 0x18, 0x60, 0xe0, 0x07,
+   0xe3, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x70, 0x70, 0xe4, 0x07, 0xc7, 0x1b,
+   0xfe, 0x01, 0x00, 0x00, 0xe0, 0x3c, 0xe4, 0x07, 0xc7, 0xe3, 0xfe, 0x1f,
+   0x00, 0x00, 0xff, 0x1f, 0xfc, 0x07, 0xc7, 0x03, 0xf8, 0x33, 0x00, 0xc0,
+   0xf0, 0x07, 0xff, 0x07, 0x87, 0x02, 0xfc, 0x43, 0x00, 0x60, 0xf0, 0xff,
+   0xff, 0x07, 0x8f, 0x06, 0xbe, 0x87, 0x00, 0x30, 0xf8, 0xff, 0xff, 0x07,
+   0x8f, 0x14, 0x9c, 0x8f, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x07, 0x9f, 0x8d,
+   0x8a, 0x0f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x07, 0xbf, 0x0b, 0x80, 0x1f,
+   0x00, 0x00, 0xff, 0xff, 0xff, 0x07, 0x7f, 0x3a, 0x80, 0x3f, 0x00, 0x80,
+   0xff, 0xff, 0xff, 0x07, 0xff, 0x20, 0xc0, 0x3f, 0x00, 0x80, 0xff, 0xff,
+   0xff, 0x07, 0xff, 0x01, 0xe0, 0x7f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x07,
+   0xff, 0x0f, 0xf8, 0xff, 0x40, 0xe0, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff,
+   0xff, 0xff, 0x40, 0xf0, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff,
+   0x41, 0xf0, 0xff, 0xff, 0xff, 0x07};
+
+Fl_Bitmap fl_bitmap(sorceress_bits, sorceress_width, sorceress_height);
+
+#include 
+
+Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb;
+Fl_Button *b;
+Fl_Window *w;
+
+void button_cb(Fl_Widget *,void *) {
+  int i = 0;
+  if (leftb->value()) i |= FL_ALIGN_LEFT;
+  if (rightb->value()) i |= FL_ALIGN_RIGHT;
+  if (topb->value()) i |= FL_ALIGN_TOP;
+  if (bottomb->value()) i |= FL_ALIGN_BOTTOM;
+  if (insideb->value()) i |= FL_ALIGN_INSIDE;
+  b->align(i);
+  w->redraw();
+}
+
+int main(int argc, char **argv) {
+  Fl_Window window(400,400); ::w = &window;
+  Fl_Button b(140,160,120,120,0); ::b = &b;
+  //(new Fl_Bitmap(sorceress_bits,sorceress_width,sorceress_height))->label(&b);
+  fl_bitmap.label(&b);
+  leftb = new Fl_Toggle_Button(50,75,50,25,"left");
+  leftb->callback(button_cb);
+  rightb = new Fl_Toggle_Button(100,75,50,25,"right");
+  rightb->callback(button_cb);
+  topb = new Fl_Toggle_Button(150,75,50,25,"top");
+  topb->callback(button_cb);
+  bottomb = new Fl_Toggle_Button(200,75,50,25,"bottom");
+  bottomb->callback(button_cb);
+  insideb = new Fl_Toggle_Button(250,75,50,25,"inside");
+  insideb->callback(button_cb);
+  window.resizable(window);
+  window.end();
+  window.show(argc, argv);
+  return Fl::run();
+}
diff --git a/test/black_1.xbm b/test/black_1.xbm
new file mode 100644
index 000000000..a9d800f98
--- /dev/null
+++ b/test/black_1.xbm
@@ -0,0 +1,60 @@
+#define black_1_width 56
+#define black_1_height 56
+static unsigned char black_1_bits[] = {
+0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 
+0x00, 0xc0, 0xff, 0xff, 0x00, 0x00, 0x00, 
+0x00, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00, 
+0x00, 0xfc, 0xff, 0xff, 0x1f, 0x00, 0x00, 
+0x00, 0xfe, 0xff, 0xff, 0x3f, 0x00, 0x00, 
+0x80, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 
+0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 
+0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 
+0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 
+0xf0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 
+0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 
+0xfc, 0xff, 0xff, 0xff, 0xff, 0x17, 0x00, 
+0xfc, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 
+0xfc, 0xff, 0xff, 0xff, 0xff, 0x5f, 0x00, 
+0xfe, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x00, 
+0xfe, 0xff, 0xff, 0xff, 0xff, 0x5f, 0x00, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x00, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x02, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x02, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x02, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x05, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x02, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x05, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x02, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x05, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x02, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x05, 
+0xfe, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x02, 
+0xfe, 0xff, 0xff, 0xff, 0xff, 0x5f, 0x05, 
+0xfe, 0xff, 0xff, 0xff, 0xff, 0xaf, 0x02, 
+0xfc, 0xff, 0xff, 0xff, 0xff, 0x5f, 0x05, 
+0xf8, 0xff, 0xff, 0xff, 0xff, 0xaf, 0x02, 
+0xf8, 0xff, 0xff, 0xff, 0xff, 0x57, 0x01, 
+0xf8, 0xff, 0xff, 0xff, 0xff, 0xab, 0x02, 
+0xf0, 0xff, 0xff, 0xff, 0xff, 0x55, 0x01, 
+0xe0, 0xff, 0xff, 0xff, 0xff, 0xab, 0x00, 
+0xc0, 0xff, 0xff, 0xff, 0xff, 0x55, 0x01, 
+0x80, 0xff, 0xff, 0xff, 0xff, 0xaa, 0x00, 
+0x00, 0xff, 0xff, 0xff, 0x5f, 0x55, 0x00, 
+0x00, 0xfe, 0xff, 0xff, 0xaf, 0x2a, 0x00, 
+0x00, 0xf4, 0xff, 0xff, 0x57, 0x15, 0x00, 
+0x00, 0xe8, 0xff, 0xff, 0xaa, 0x0a, 0x00, 
+0x00, 0x50, 0xff, 0x7f, 0x55, 0x05, 0x00, 
+0x00, 0xa0, 0xaa, 0xaa, 0xaa, 0x02, 0x00, 
+0x00, 0x40, 0x55, 0x55, 0x55, 0x01, 0x00, 
+0x00, 0x00, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 
+0x00, 0x00, 0x50, 0x55, 0x15, 0x00, 0x00, 
+0x00, 0x00, 0x80, 0xaa, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
diff --git a/test/black_2.xbm b/test/black_2.xbm
new file mode 100644
index 000000000..b324fd124
--- /dev/null
+++ b/test/black_2.xbm
@@ -0,0 +1,60 @@
+#define black_2_width 56
+#define black_2_height 56
+static unsigned char black_2_bits[] = {
+0x00, 0x00, 0x0f, 0x3c, 0x00, 0x00, 0x00, 
+0x00, 0x40, 0x40, 0x81, 0x00, 0x00, 0x00, 
+0x00, 0x10, 0x49, 0x09, 0x02, 0x00, 0x00, 
+0x00, 0x44, 0x52, 0x49, 0x08, 0x00, 0x00, 
+0x00, 0x90, 0x52, 0x25, 0x01, 0x00, 0x00, 
+0x80, 0x94, 0x54, 0x95, 0x44, 0x00, 0x00, 
+0x40, 0x24, 0x01, 0x40, 0x92, 0x00, 0x00, 
+0x20, 0x49, 0xfc, 0x0f, 0x09, 0x01, 0x00, 
+0x00, 0x11, 0x57, 0x35, 0x64, 0x00, 0x00, 
+0x40, 0xc2, 0x00, 0xc0, 0x10, 0x00, 0x00, 
+0x88, 0x64, 0x55, 0x55, 0x89, 0x05, 0x00, 
+0x20, 0x11, 0x00, 0x08, 0x42, 0x00, 0x00, 
+0x44, 0x58, 0x55, 0x55, 0x21, 0x0b, 0x00, 
+0x90, 0x04, 0x80, 0x0a, 0x80, 0x00, 0x00, 
+0x22, 0x56, 0x55, 0x55, 0x45, 0x14, 0x00, 
+0x48, 0x02, 0xa8, 0x2a, 0x00, 0x03, 0x00, 
+0x11, 0x55, 0x55, 0x55, 0x95, 0x28, 0x00, 
+0x21, 0x81, 0xaa, 0x2a, 0x00, 0x26, 0x00, 
+0x8d, 0x55, 0x55, 0x55, 0x15, 0x21, 0x00, 
+0xb1, 0xe0, 0xaa, 0xaa, 0x00, 0x20, 0x00, 
+0x80, 0xf5, 0x55, 0x55, 0x15, 0x07, 0x00, 
+0xbe, 0xf0, 0xab, 0xaa, 0x00, 0x00, 0x00, 
+0x80, 0xf5, 0x55, 0x55, 0x15, 0x1f, 0x00, 
+0xbe, 0xe0, 0xab, 0xaa, 0x02, 0x00, 0x00, 
+0x80, 0xf5, 0x57, 0x55, 0x15, 0x1f, 0x00, 
+0xb8, 0xc0, 0xaf, 0xaa, 0x00, 0x00, 0x00, 
+0x81, 0xd5, 0x57, 0x15, 0x14, 0x23, 0x00, 
+0xa1, 0x80, 0xaf, 0x0a, 0x00, 0x2c, 0x00, 
+0x19, 0xd5, 0x5f, 0x01, 0x14, 0x21, 0x00, 
+0x45, 0x01, 0xaf, 0x00, 0x00, 0x22, 0x00, 
+0x30, 0x56, 0x1f, 0x40, 0x85, 0x04, 0x00, 
+0x8a, 0x02, 0x0e, 0x00, 0x00, 0x11, 0x00, 
+0x40, 0x54, 0x0f, 0x54, 0x45, 0x02, 0x00, 
+0x34, 0x09, 0x04, 0x00, 0x80, 0x08, 0x00, 
+0x80, 0x40, 0x45, 0x55, 0x21, 0x01, 0x00, 
+0x68, 0x04, 0x00, 0x00, 0x48, 0x04, 0x00, 
+0x00, 0x82, 0x55, 0x95, 0x90, 0x00, 0x00, 
+0x80, 0x09, 0x02, 0x20, 0x22, 0x00, 0x00, 
+0x20, 0x24, 0xa8, 0x8a, 0x24, 0x01, 0x00, 
+0x40, 0x92, 0x00, 0x20, 0x89, 0x00, 0x00, 
+0x80, 0x48, 0xaa, 0x4a, 0x4a, 0x00, 0x00, 
+0x00, 0x20, 0xa9, 0x52, 0x02, 0x00, 0x00, 
+0x00, 0x84, 0xa4, 0x92, 0x08, 0x00, 0x00, 
+0x00, 0x10, 0xa4, 0x24, 0x02, 0x00, 0x00, 
+0x00, 0x40, 0xa0, 0x80, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x0f, 0x3c, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
diff --git a/test/black_3.xbm b/test/black_3.xbm
new file mode 100644
index 000000000..ead6e086a
--- /dev/null
+++ b/test/black_3.xbm
@@ -0,0 +1,60 @@
+#define black_3_width 56
+#define black_3_height 56
+static unsigned char black_3_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 
+0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 
+0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 
+0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x54, 0x05, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
diff --git a/test/black_4.xbm b/test/black_4.xbm
new file mode 100644
index 000000000..4132263e6
--- /dev/null
+++ b/test/black_4.xbm
@@ -0,0 +1,60 @@
+#define black_4_width 56
+#define black_4_height 56
+static unsigned char black_4_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
diff --git a/test/blackking_1.xbm b/test/blackking_1.xbm
new file mode 100644
index 000000000..f764eade6
--- /dev/null
+++ b/test/blackking_1.xbm
@@ -0,0 +1,60 @@
+#define blackking_1_width 56
+#define blackking_1_height 56
+static unsigned char blackking_1_bits[] = {
+0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 
+0x00, 0xc0, 0xff, 0xff, 0x00, 0x00, 0x00, 
+0x00, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00, 
+0x00, 0xfc, 0xff, 0xff, 0x1f, 0x00, 0x00, 
+0x00, 0xfe, 0xff, 0xff, 0x3f, 0x00, 0x00, 
+0x80, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 
+0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 
+0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 
+0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 
+0xf0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 
+0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 
+0xfc, 0xff, 0xff, 0xff, 0xff, 0x17, 0x00, 
+0xfc, 0xff, 0xff, 0xff, 0xff, 0x2f, 0x00, 
+0xfc, 0xff, 0xff, 0xff, 0xff, 0x5f, 0x00, 
+0xfe, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x00, 
+0xfe, 0xff, 0xff, 0xff, 0xff, 0x5f, 0x01, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x02, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x05, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x0a, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x15, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x0a, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x15, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x2a, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x55, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x2a, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x55, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x2a, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x55, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x55, 
+0xfe, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xaa, 
+0xfe, 0xff, 0xff, 0xff, 0xff, 0x5f, 0x55, 
+0xfe, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 
+0xfc, 0xff, 0xff, 0xff, 0xff, 0x5f, 0x55, 
+0xf8, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xaa, 
+0xf8, 0xff, 0xff, 0xff, 0xff, 0x57, 0x55, 
+0xf8, 0xff, 0xff, 0xff, 0xff, 0xab, 0xaa, 
+0xf0, 0xff, 0xff, 0xff, 0xff, 0x55, 0x55, 
+0xe0, 0xff, 0xff, 0xff, 0xff, 0xab, 0xaa, 
+0xc0, 0xff, 0xff, 0xff, 0xff, 0x55, 0x55, 
+0x80, 0xff, 0xff, 0xff, 0xff, 0xaa, 0x2a, 
+0x00, 0xff, 0xff, 0xff, 0x5f, 0x55, 0x55, 
+0x00, 0xfe, 0xff, 0xff, 0xaf, 0xaa, 0x2a, 
+0x00, 0xf4, 0xff, 0xff, 0x57, 0x55, 0x15, 
+0x00, 0xe8, 0xff, 0xff, 0xaa, 0xaa, 0x2a, 
+0x00, 0x50, 0xff, 0x7f, 0x55, 0x55, 0x15, 
+0x00, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 
+0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x05, 
+0x00, 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 
+0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x01, 
+0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 
+0x00, 0x00, 0x54, 0x55, 0x55, 0x55, 0x00, 
+0x00, 0x00, 0xa8, 0xaa, 0xaa, 0x2a, 0x00, 
+0x00, 0x00, 0x40, 0x55, 0x55, 0x15, 0x00, 
+0x00, 0x00, 0x00, 0xaa, 0xaa, 0x02, 0x00, 
+0x00, 0x00, 0x00, 0x50, 0x15, 0x00, 0x00, 
+};
diff --git a/test/blackking_2.xbm b/test/blackking_2.xbm
new file mode 100644
index 000000000..9be617b5a
--- /dev/null
+++ b/test/blackking_2.xbm
@@ -0,0 +1,60 @@
+#define blackking_2_width 56
+#define blackking_2_height 56
+static unsigned char blackking_2_bits[] = {
+0x00, 0x00, 0x0f, 0x3c, 0x00, 0x00, 0x00, 
+0x00, 0x40, 0x40, 0x81, 0x00, 0x00, 0x00, 
+0x00, 0x10, 0x49, 0x09, 0x02, 0x00, 0x00, 
+0x00, 0x44, 0x52, 0x49, 0x08, 0x00, 0x00, 
+0x00, 0x90, 0x52, 0x25, 0x01, 0x00, 0x00, 
+0x80, 0x94, 0x54, 0x95, 0x44, 0x00, 0x00, 
+0x40, 0x24, 0x01, 0x40, 0x92, 0x00, 0x00, 
+0x20, 0x49, 0xfc, 0x0f, 0x09, 0x01, 0x00, 
+0x00, 0x11, 0x57, 0x35, 0x64, 0x00, 0x00, 
+0x40, 0xc2, 0x00, 0xc0, 0x10, 0x00, 0x00, 
+0x88, 0x64, 0xd5, 0x55, 0x89, 0x05, 0x00, 
+0x20, 0x11, 0xc0, 0x00, 0x42, 0x00, 0x00, 
+0x44, 0x58, 0x57, 0x74, 0x21, 0x0b, 0x00, 
+0x90, 0x04, 0x03, 0x30, 0x80, 0x00, 0x00, 
+0x22, 0x76, 0x51, 0x15, 0x47, 0x14, 0x00, 
+0x48, 0x32, 0x08, 0x02, 0x03, 0x03, 0x00, 
+0x11, 0x15, 0x5d, 0x57, 0x91, 0x28, 0x00, 
+0x21, 0x01, 0x0c, 0x03, 0x00, 0x26, 0x00, 
+0x8d, 0x55, 0xcf, 0xd3, 0x15, 0x21, 0x00, 
+0xb1, 0x18, 0x86, 0xe1, 0x00, 0x20, 0x00, 
+0x80, 0x5d, 0xd7, 0x75, 0x11, 0x07, 0x00, 
+0xbe, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x80, 0x75, 0x55, 0x55, 0x11, 0x1f, 0x00, 
+0xbe, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x80, 0x75, 0x55, 0x55, 0x10, 0x1f, 0x00, 
+0xb8, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x81, 0x75, 0x55, 0x55, 0x14, 0x23, 0x00, 
+0xa1, 0x60, 0x00, 0x00, 0x00, 0x2c, 0x00, 
+0x19, 0xd5, 0x55, 0x55, 0x14, 0x21, 0x00, 
+0x45, 0xc1, 0x00, 0x00, 0x00, 0x22, 0x00, 
+0x30, 0xd6, 0x00, 0x00, 0x85, 0x04, 0x00, 
+0x8a, 0x82, 0x00, 0x00, 0x00, 0x11, 0x00, 
+0x40, 0x54, 0x00, 0x00, 0x45, 0x02, 0x00, 
+0x34, 0x09, 0x00, 0x00, 0x80, 0x08, 0x00, 
+0x80, 0x40, 0x55, 0x55, 0x21, 0x01, 0x00, 
+0x68, 0x04, 0x00, 0x00, 0x48, 0x04, 0x00, 
+0x00, 0x82, 0x55, 0x95, 0x90, 0x00, 0x00, 
+0x80, 0x09, 0x02, 0x20, 0x22, 0x00, 0x00, 
+0x20, 0x24, 0xa8, 0x8a, 0x24, 0x01, 0x00, 
+0x40, 0x92, 0x00, 0x20, 0x89, 0x00, 0x00, 
+0x80, 0x48, 0xaa, 0x4a, 0x4a, 0x00, 0x00, 
+0x00, 0x20, 0xa9, 0x52, 0x02, 0x00, 0x00, 
+0x00, 0x84, 0xa4, 0x92, 0x08, 0x00, 0x00, 
+0x00, 0x10, 0xa4, 0x24, 0x02, 0x00, 0x00, 
+0x00, 0x40, 0xa0, 0x80, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x0f, 0x3c, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
diff --git a/test/blackking_3.xbm b/test/blackking_3.xbm
new file mode 100644
index 000000000..b4a688360
--- /dev/null
+++ b/test/blackking_3.xbm
@@ -0,0 +1,60 @@
+#define blackking_3_width 56
+#define blackking_3_height 56
+static unsigned char blackking_3_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 
+0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 
+0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 
+0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x54, 0x05, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
diff --git a/test/blackking_4.xbm b/test/blackking_4.xbm
new file mode 100644
index 000000000..a7078623e
--- /dev/null
+++ b/test/blackking_4.xbm
@@ -0,0 +1,60 @@
+#define blackking_4_width 56
+#define blackking_4_height 56
+static unsigned char blackking_4_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
diff --git a/test/boxtype.cxx b/test/boxtype.cxx
new file mode 100644
index 000000000..b358f228e
--- /dev/null
+++ b/test/boxtype.cxx
@@ -0,0 +1,66 @@
+//	produce the diagram of boxtypes for the documentation
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int N = 0;
+#define W 150
+#define H 50
+#define ROWS 8
+
+Fl_Window *window;
+
+void bt(const char *name, Fl_Boxtype type, int square=0) {
+  int x = N%4;
+  int y = N/4;
+  N++;
+  x = x*W+10;
+  y = y*H+10;
+  Fl_Box *b = new Fl_Box(type,x,y,square ? H-20 : W-20,H-20,name);
+  b->labelsize(11);
+  if (square) b->align(FL_ALIGN_RIGHT);
+}
+
+int main(int argc, char ** argv) {
+  window = new Fl_Single_Window(4*W,ROWS*H);
+  window->box(FL_FLAT_BOX);
+  window->color(12);// light blue
+  bt("FL_NO_BOX",FL_NO_BOX);
+  bt("FL_FLAT_BOX",FL_FLAT_BOX);
+  N += 2; // go to start of next row to line up boxes & frames
+  bt("FL_UP_BOX",FL_UP_BOX);
+  bt("FL_DOWN_BOX",FL_DOWN_BOX);
+  bt("FL_UP_FRAME",FL_UP_FRAME);
+  bt("FL_DOWN_FRAME",FL_DOWN_FRAME);
+  bt("FL_THIN_UP_BOX",FL_THIN_UP_BOX);
+  bt("FL_THIN_DOWN_BOX",FL_THIN_DOWN_BOX);
+  bt("FL_THIN_UP_FRAME",FL_THIN_UP_FRAME);
+  bt("FL_THIN_DOWN_FRAME",FL_THIN_DOWN_FRAME);
+  bt("FL_ENGRAVED_BOX",FL_ENGRAVED_BOX);
+  bt("FL_EMBOSSED_BOX",FL_EMBOSSED_BOX);
+  bt("FL_ENGRAVED_FRAME",FL_ENGRAVED_FRAME);
+  bt("FL_EMBOSSED_FRAME",FL_EMBOSSED_FRAME);
+  bt("FL_BORDER_BOX",FL_BORDER_BOX);
+  bt("FL_SHADOW_BOX",FL_SHADOW_BOX);
+  bt("FL_BORDER_FRAME",FL_BORDER_FRAME);
+  bt("FL_SHADOW_FRAME",FL_SHADOW_FRAME);
+  bt("FL_ROUNDED_BOX",FL_ROUNDED_BOX);
+  bt("FL_RSHADOW_BOX",FL_RSHADOW_BOX);
+  bt("FL_ROUNDED_FRAME",FL_ROUNDED_FRAME);
+  bt("FL_RFLAT_BOX",FL_RFLAT_BOX);
+  bt("FL_OVAL_BOX",FL_OVAL_BOX);
+  bt("FL_OSHADOW_BOX",FL_OSHADOW_BOX);
+  bt("FL_OVAL_FRAME",FL_OVAL_FRAME);
+  bt("FL_OFLAT_BOX",FL_OFLAT_BOX);
+  bt("FL_ROUND_UP_BOX",FL_ROUND_UP_BOX);
+  bt("FL_ROUND_DOWN_BOX",FL_ROUND_DOWN_BOX);
+  bt("FL_DIAMOND_UP_BOX",FL_DIAMOND_UP_BOX);
+  bt("FL_DIAMOND_DOWN_BOX",FL_DIAMOND_DOWN_BOX);
+  window->resizable(window);
+  window->end();
+  window->show(argc,argv);
+  return Fl::run();
+}
diff --git a/test/browser.cxx b/test/browser.cxx
new file mode 100644
index 000000000..3a1510185
--- /dev/null
+++ b/test/browser.cxx
@@ -0,0 +1,71 @@
+/*
+This is a test of how the browser draws lines.
+This is a second line.
+This is a third.
+
+That was a blank line above this.
+
+@r@_Right justify
+@c@_Center justify
+@_Left justify
+
+@bBold text
+@iItalic text
+@b@iBold Italic
+@fFixed width
+@f@bBold Fixed
+@f@iItalic Fixed
+@f@i@bBold Italic Fixed
+@lLarge
+@l@bLarge bold
+@sSmall
+@s@bSmall bold
+@s@iSmall italic
+@s@i@bSmall italic bold
+@uunderscore
+@C1RED
+@C2Green
+@C4Blue
+
+	You should try different browser types:
+	Fl_Browser
+	Fl_Select_Browser
+	Fl_Hold_Browser
+	Fl_Multi_Browser
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+void b_cb(Fl_Widget* o, void*) {
+  printf("callback, selection = %d, event_clicks = %d\n",
+	 ((Fl_Browser*)o)->value(), Fl::event_clicks());
+}
+
+int main(int argc, char **argv) {
+  int i;
+  if (!Fl::args(argc,argv,i)) Fl::fatal(Fl::help);
+  const char* fname = (i < argc) ? argv[i] : "browser.C";
+  Fl_Window window(400,400,fname);
+  window.box(FL_NO_BOX); // because it is filled with browser
+  Fl_Select_Browser browser(0,0,400,400,0);
+  browser.type(FL_MULTI_BROWSER);
+  browser.callback(b_cb);
+  // browser.scrollbar_right();
+  //browser.has_scrollbar(Fl_Browser::BOTH_ALWAYS);
+  if (!browser.load(fname)) {
+    printf("Can't load %s, %s\n", fname, strerror(errno));
+    exit(1);
+  }
+  browser.position(0);
+  window.resizable(&browser);
+  window.show(argc,argv);
+  return Fl::run();
+}
+
+
diff --git a/test/browserop.cxx b/test/browserop.cxx
new file mode 100644
index 000000000..19f920d2b
--- /dev/null
+++ b/test/browserop.cxx
@@ -0,0 +1,81 @@
+/* This demo shows the different routines on browsers */
+
+#include "forms.h"
+
+FL_FORM *form;
+FL_OBJECT *browserobj, *inputobj, *exitobj;
+
+void addit(FL_OBJECT *, long)
+{
+  /* append and show the last line. Don't use this if you just want
+   * to add some lines. use fl_add_browser_line
+   */
+  fl_addto_browser(browserobj,fl_get_input(inputobj));
+}
+
+void insertit(FL_OBJECT *, long)
+{
+  int n;
+  if (! ( n = fl_get_browser(browserobj))) return;
+  fl_insert_browser_line(browserobj,n,fl_get_input(inputobj));
+}
+
+void replaceit(FL_OBJECT *, long)
+{
+  int n;
+  if (! (n=fl_get_browser(browserobj))) return;
+  fl_replace_browser_line(browserobj,n,fl_get_input(inputobj));
+}
+
+void deleteit(FL_OBJECT *, long)
+{
+  int n;
+  if (! (n = fl_get_browser(browserobj))) return;
+  fl_delete_browser_line(browserobj,n);
+}
+
+void clearit(FL_OBJECT *, long)
+{
+  fl_clear_browser(browserobj);
+}
+
+/*---------------------------------------*/
+
+void create_form(void)
+{
+  FL_OBJECT *obj;
+
+  form = fl_bgn_form(FL_UP_BOX,390,420);
+  browserobj = fl_add_browser(FL_HOLD_BROWSER,20,20,210,330,"");
+//  fl_set_object_dblbuffer(browserobj, 1);
+  inputobj = obj = fl_add_input(FL_NORMAL_INPUT,20,370,210,30,"");
+    fl_set_object_callback(obj,addit,0);
+    obj->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED);
+  obj = fl_add_button(FL_NORMAL_BUTTON,250,20,120,30,"Add");
+    fl_set_object_callback(obj,addit,0);
+  obj = fl_add_button(FL_NORMAL_BUTTON,250,60,120,30,"Insert");
+    fl_set_object_callback(obj,insertit,0);
+  obj = fl_add_button(FL_NORMAL_BUTTON,250,100,120,30,"Replace");
+    fl_set_object_callback(obj,replaceit,0);
+  obj = fl_add_button(FL_NORMAL_BUTTON,250,160,120,30,"Delete");
+    fl_set_object_callback(obj,deleteit,0);
+  obj = fl_add_button(FL_NORMAL_BUTTON,250,200,120,30,"Clear");
+    fl_set_object_callback(obj,clearit,0);
+  exitobj = fl_add_button(FL_NORMAL_BUTTON,250,370,120,30,"Exit");
+  fl_end_form();
+}
+
+/*---------------------------------------*/
+
+int
+main(int argc, char *argv[])
+{
+  FL_OBJECT *obj;
+
+  fl_initialize(&argc, argv, "FormDemo", 0, 0);
+  create_form();
+  fl_show_form(form,FL_PLACE_CENTER,FL_TRANSIENT,"Browser Op");
+  do obj = fl_do_forms(); while (obj != exitobj);
+  fl_hide_form(form);
+  return 0;
+}
diff --git a/test/button.cxx b/test/button.cxx
new file mode 100644
index 000000000..78c8f135b
--- /dev/null
+++ b/test/button.cxx
@@ -0,0 +1,27 @@
+// 	Demonstration of how to do callbacks
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+void beepcb(Fl_Widget *, void *) {
+  printf("\007"); fflush(stdout);
+}
+
+void exitcb(Fl_Widget *, void *) {
+  exit(0);
+}
+
+int main(int argc, char ** argv) {
+  Fl_Window *window = new Fl_Window(320,65);
+  Fl_Button *b1 = new Fl_Button(20, 20, 80, 25, "&Beep");
+  b1->callback(beepcb,0);
+  /*Fl_Button *b2 =*/ new Fl_Button(120,20, 80, 25, "&no op");
+  Fl_Button *b3 = new Fl_Button(220,20, 80, 25, "E&xit");
+  b3->callback(exitcb,0);
+  window->end();
+  window->show(argc,argv);
+  return Fl::run();
+}
diff --git a/test/buttons.cxx b/test/buttons.cxx
new file mode 100644
index 000000000..5dfb4f4e3
--- /dev/null
+++ b/test/buttons.cxx
@@ -0,0 +1,25 @@
+//	produce image for the documentation
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int main(int argc, char ** argv) {
+  Fl_Window *window = new Fl_Window(320,130);
+  new Fl_Button(10, 10, 130, 30, "Fl_Button");
+  new Fl_Return_Button(150, 10, 160, 30, "Fl_Return_Button");
+  new Fl_Repeat_Button(10,50,130,30,"Fl_Repeat_Button");
+  new Fl_Light_Button(10,90,130,30,"Fl_Light_Button");
+  new Fl_Round_Button(150,50,160,30,"Fl_Round_Button");
+  new Fl_Check_Button(150,90,160,30,"Fl_Check_Button");
+  window->end();
+  window->show(argc,argv);
+  return Fl::run();
+}
diff --git a/test/checkers.cxx b/test/checkers.cxx
new file mode 100644
index 000000000..fe9aa700f
--- /dev/null
+++ b/test/checkers.cxx
@@ -0,0 +1,1340 @@
+// Hours of fun: the FLTK checkers game!
+// Based on a very old algorithim, but it still works!
+
+const char* copyright = 
+"Checkers game\n"
+"Copyright (C) 1997 Bill Spitzak    spitzak@d2.com\n"
+"Original Pascal code:\n"
+"Copyright 1978, Oregon Minicomputer Software, Inc.\n"
+"2340 SW Canyon Road, Portland, Oregon 97201\n"
+"Written by Steve Poulsen 18-Jan-79\n"
+"\n"
+"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.\n"
+"\n"
+"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.\n"
+"\n"
+"You should have received a copy of the GNU Library 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.";
+
+// Define FLTK to get the fltk interface
+// Define VT100 to get the VT100 interface
+// Define both to get a program that takes a -t switch
+
+#define FLTK
+//#define VT100
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+////////////////////////////////////////////////////////////////
+// The algorithim:
+
+int maxevaluate=2500;		// max number of moves to examine on a turn
+int maxnodes = 2500;		// maximum number of nodes in search tree
+int maxply = 20;		// maximum depth to look ahead
+char forcejumps = 1;		// is forced jumps rule in effect?
+
+// scoring parameters: (all divided by 5 from original code)
+// some signs seem to be backwards, marked them with (-) in comment
+const int spiece = 800;		// value of a piece
+const int sking = 1200;		// value of a king
+const int sadvan = 160;		// value of mypieces/theirpieces-1
+// const int smobil = ?		// moves *enemy* can make w/o being jumped
+const int sallpin = 80;		// mobil == 0
+const int sdeny = 10;		// moves enemy can make that will be jumped
+const int spin = 32;		// enemy pieces that have no move except jumped
+const int sthreat = -10;	// enemy pieces we can jump if not moved (-)
+const int sgrad = 1;		// score of piece positions
+const int sback = 10;		// back row occupied so enemy can't make king
+const int smoc2 = 200;		// more mobility, more center
+const int smoc3 = -8;		// less mobility, less center
+const int smoc4 = -80;		// more mobility, less center
+const int smode2 = -14;		// less mobility, less denied
+const int smode3 = -40;		// more mobility, more denied (-)
+const int sdemmo = -20;		// more denied, more moves (-)
+const int scent = 10;		// pieces in center
+const int skcent = 100;		// kings in center
+
+const int depthpenalty=4;	// guess
+const int noise=2;		// values less or eq to this apart are eq
+
+// const int sattackking = 4;	// not used
+// const int sattackpiece = 3;
+
+struct node {
+  node *father;
+  node *son;		// best son
+  node *brother;	// next brother
+  short int value;	// value of this board position to player making move
+  unsigned char from,to; // the move to reach this board
+  long int jump;	// bit map of locations jumped
+  unsigned char mobil;
+  unsigned char deny;
+  unsigned char pin;
+  unsigned char threat;
+  short int gradient;
+  unsigned who:1;	// 0 = black's move, 1 = white's move
+  unsigned king:1;	// 1 = move causes piece to be kinged
+  unsigned back:1;
+  unsigned moc2:1;
+  unsigned moc3:1;
+  unsigned moc4:1;
+  unsigned mode2:1;
+  unsigned mode3:1;
+  unsigned demmo:1;
+};
+
+int nodes;		// count of nodes
+
+/*	Board positions:	Border positions:
+
+	      WHITE		  00  01  02  03  04
+	  05  06  07  08	04  XX  XX  XX  XX
+	09  10  11  12		  XX  XX  XX  XX  13
+	  14  15  16  17	13  XX  XX  XX  XX
+	18  19  20  21		  XX  XX  XX  XX  22
+	  23  24  25  26	22  XX  XX  XX  XX
+	27  28  29  30		  XX  XX  XX  XX  31
+	  32  33  34  36	31  XX  XX  XX  XX
+	36  37  38  39		  XX  XX  XX  XX  40
+	      BLACK		40  41  42  43  44
+
+*/
+
+typedef char piece;
+
+// Piece values so that BLACK and WHITE are bit flags:
+#define EMPTY 0
+#define BLACK 1
+#define WHITE 2
+#define KING 4
+#define BLACKKING 5
+#define WHITEKING 6
+#define BLUE 8
+
+const piece flip[9] = {
+  EMPTY, WHITE, BLACK, 0, 0, WHITEKING, BLACKKING, 0, BLUE};
+
+const int offset[9][4] = {	// legal move directions
+  {0,0,0,0},
+  {-5,-4,0,0},
+  {4,5,0,0},
+  {0,0,0,0},
+  {0,0,0,0},
+  {4,5,-4,-5},
+  {4,5,-4,-5},
+  {0,0,0,0},
+  {0,0,0,0}
+};
+
+piece b[45];		// current board position being considered
+
+int evaluated;		// number of moves evaluated this turn
+
+char centralsquares[45];
+char is_protected[45];
+
+piece flipboard[45];	// swapped if enemy is black
+piece *tb;		// pointer to real or swapped board
+#define FRIEND BLACK
+#define FRIENDKING BLACKKING
+#define ENEMY WHITE
+#define ENEMYKING WHITEKING
+
+char check(int target,int direction) {
+  // see if enemy at target can be jumped from direction by our piece
+  int dst = target-direction;
+  if (tb[dst]) return(0);
+  int src = target+direction;
+  if (tb[src] == FRIENDKING);
+  else if (direction < 0 || tb[src] != FRIEND) return(0);
+  piece a = tb[target]; piece b = tb[src];
+  tb[target] = EMPTY; tb[src] = EMPTY;
+  int safe =
+    (tb[src-4]&FRIEND && tb[src-8]&ENEMY
+     ||tb[src-5]&FRIEND && tb[src-10]&ENEMY
+     ||tb[dst-4]&ENEMY && !tb[dst+4]
+     ||tb[dst-5]&ENEMY && !tb[dst+5]
+     ||tb[src+4]&FRIEND && tb[src+8]==ENEMYKING
+     ||tb[src+5]&FRIEND && tb[src+10]==ENEMYKING
+     ||tb[dst+4]==ENEMYKING && !tb[dst-4]
+     ||tb[dst+5]==ENEMYKING && !tb[dst-5]);
+  tb[target] = a; tb[src] = b;
+  return(safe);
+}
+
+int deniedmoves,undeniedmoves;
+void analyzemove(int direction,int src) {
+  int target = src+direction;
+  if (!tb[target]) {
+    if (!tb[target+direction]) is_protected[target] = 1;
+    piece a = tb[src]; tb[src] = EMPTY;
+    if (check(target,4) || check(target,5) ||
+	check(target,-4) || check(target,-5) ||
+	(tb[src+4]&ENEMY && check(src+4,4)) ||
+	(tb[src+5]&ENEMY && check(src+5,5)) ||
+	(tb[src-4]&ENEMY && check(src-4,-4)) ||
+	(tb[src-5]&ENEMY && check(src-5,-5)))
+      deniedmoves++;
+    else undeniedmoves++;
+    tb[src] = a;
+  }
+}
+
+void evaluateboard(node *n,int print) {
+
+  if (!n->who) tb = b;	// move was black's
+  else {
+    for (int i=0; i<45; i++) flipboard[44-i] = flip[b[i]];
+    tb = flipboard;
+  }
+
+  memset(is_protected,0,sizeof(is_protected));
+  int friendpieces = 0;
+  int enemypieces = 0;
+  int friendkings = 0;
+  int enemykings = 0;
+  int friendkcent = 0;
+  int friendcent = 0;
+  int enemykcent = 0;
+  int enemycent = 0;
+  n->mobil = n->deny = n->pin = n->threat = 0;
+
+  int i;
+  for (i=5; i<40; i++) switch(tb[i]) {
+  case ENEMYKING:
+    enemykings++;
+    enemykcent += centralsquares[i];
+    deniedmoves = 0;
+    undeniedmoves = 0;
+    if (i>8) {
+      analyzemove(-4,i);
+      analyzemove(-5,i);
+    }
+    goto J1;
+  case ENEMY:
+    deniedmoves = 0;
+    undeniedmoves = 0;
+  J1:	enemypieces++;
+    enemycent += centralsquares[i];
+    if (i<36) {
+      analyzemove(4,i);
+      analyzemove(5,i);
+    }
+    if (deniedmoves && !undeniedmoves) n->pin++;
+    n->deny += deniedmoves;
+    n->mobil += undeniedmoves;
+    break;
+  case FRIENDKING:
+    friendkings++;
+    friendkcent += centralsquares[i];
+    if (tb[i+4]&ENEMY && !tb[i+8] && !(tb[i+4]==ENEMYKING && !tb[i-4]))
+      n->threat++;
+    if (tb[i+5]&ENEMY && !tb[i+10] && !(tb[i+5]==ENEMYKING && !tb[i-5]))
+      n->threat++;
+  case FRIEND:
+    friendpieces++;
+    friendcent += centralsquares[i];
+    if (tb[i-4]&ENEMY && !tb[i-8] && tb[i+4]) n->threat++;
+    if (tb[i-5]&ENEMY && !tb[i-10] && tb[i+5]) n->threat++;
+    break;
+  }
+
+  int gradient[40];
+  for (i=4; i<9; i++) gradient[i] = tb[i] ? 0 : 32;
+  int total = 0;
+  for (i=9; i<40; i++) {
+    int x = (gradient[i-4]+gradient[i-5])/2;
+    if (tb[i]==FRIEND) total += x;
+    gradient[i] = (tb[i]&FRIEND || !tb[i] && !is_protected[i]) ? x : 0;
+  }
+  n->gradient = total;
+
+  n->back = tb[39]==FRIEND && tb[37]==FRIEND && !enemykings;
+
+  node* f = n->father;
+
+  n->moc2 = f->mobil>n->mobil && friendcent>enemycent;
+  n->moc3 = f->mobil<=n->mobil && friendcentmoc4 = f->mobil>n->mobil && friendcentmode2 = f->mobil<=n->mobil && n->denydeny;
+  n->mode3 = f->mobil>n->mobil && n->deny>f->deny;
+  n->demmo = n->deny>f->deny && f->deny+f->mobil>n->deny+n->mobil;
+
+  total =
+    spiece	* (friendpieces - enemypieces) +
+    (sking-spiece) * (friendkings	- enemykings) +
+    //	mobil?
+    sdeny	* (n->deny	- f->deny) +
+    spin	* (n->pin	- f->pin) +
+    sthreat	* (n->threat	- f->threat) +
+    sgrad	* (n->gradient	- f->gradient) +
+    sback	* (n->back	- f->back) +
+    smoc2	* (n->moc2	- f->moc2) +
+    smoc3	* (n->moc3	- f->moc3) +
+    smoc4	* (n->moc4	- f->moc4) +
+    smode2	* (n->mode2	- f->mode2) +
+    smode3	* (n->mode3	- f->mode3) +
+    sdemmo	* (n->demmo	- f->demmo) +
+    scent	* (friendcent	- enemycent) +
+    (skcent-scent) * (friendkcent	- enemykcent);
+  if (!n->mobil) total += sallpin;
+
+  if (!enemypieces) total = 30000;
+  else if (friendpieces > enemypieces)
+    total += (sadvan*friendpieces)/enemypieces-sadvan;
+  else total -= (sadvan*enemypieces)/friendpieces-sadvan;
+
+  if (print) {
+    printf("\tParent\tNew\tScore\n");
+    printf("pieces\t%d\t%d\t%d\n",enemypieces,friendpieces,
+	   spiece*(friendpieces-enemypieces));
+    printf("kings\t%d\t%d\t%d\n",enemykings,friendkings,
+	   (sking-spiece)*(friendkings-enemykings));
+    printf("mobil\t%d\t%d\n",f->mobil,n->mobil);
+    printf("deny\t%d\t%d\t%d\n",f->deny,n->deny,sdeny*(n->deny-f->deny));
+    printf("pin\t%d\t%d\t%d\n",f->pin,n->pin,spin*(n->pin-f->pin));
+    printf("threat\t%d\t%d\t%d\n",f->threat,n->threat,sthreat*(n->threat-f->threat));
+    printf("grad\t%d\t%d\t%d\n",f->gradient,n->gradient,sgrad*(n->gradient-f->gradient));
+    printf("back\t%d\t%d\t%d\n",f->back,n->back,sback*(n->back-f->back));
+    printf("moc2\t%d\t%d\t%d\n",f->moc2,n->moc2,smoc2*(n->moc2-f->moc2));
+    printf("moc3\t%d\t%d\t%d\n",f->moc3,n->moc3,smoc3*(n->moc3-f->moc3));
+    printf("moc4\t%d\t%d\t%d\n",f->moc4,n->moc4,smoc4*(n->moc4-f->moc4));
+    printf("mode2\t%d\t%d\t%d\n",f->mode2,n->mode2,smode2*(n->mode2-f->mode2));
+    printf("mode3\t%d\t%d\t%d\n",f->mode3,n->mode3,smode3*(n->mode3-f->mode3));
+    printf("demmo\t%d\t%d\t%d\n",f->demmo,n->demmo,sdemmo*(n->demmo-f->demmo));
+    printf("cent\t%d\t%d\t%dn",enemycent,friendcent,scent*(friendcent-enemycent));
+    printf("kcent\t%d\t%d\t%d\n",enemykcent,friendkcent,skcent*(friendkcent-enemykcent));
+    printf("total:\t\t\t%d\n",total);
+  }
+  else {
+    n->value = total;
+    evaluated++;
+  }
+}	// end of evaluateboard
+
+// --------------------- Tree management -----------------
+
+node *freelist;
+
+node *newnode(void) {
+  node *n;
+  if (freelist) {
+    n = freelist;
+    freelist = n->brother;
+  }
+  else n = (node *)malloc(sizeof(node));
+  memset(n,0,sizeof(node));
+  nodes++;
+  return(n);
+}
+
+void extract(node *n) {
+  node* i = n->father;
+  if (i) {
+    node* j = i->son;
+    if (j==n) i->son = n->brother;
+    else while (j) {
+      i = j; j = j->brother;
+      if (j==n) {i->brother = n->brother; break;}
+    }
+  }
+  n->brother = 0;
+}
+
+void killnode(node *x) {
+  if (!x) return;
+  node *y;
+  for (y = x; ; y = y->brother) {
+    nodes--;
+    killnode(y->son); y->son = 0;
+    if (!y->brother) break;
+  }
+  y->brother = freelist;
+  freelist = x;
+}
+
+int seed;		// current random number
+
+void insert(node *n) {
+  int val = n->value;
+  node **pp;
+  for (pp = &(n->father->son); *pp; pp = &((*pp)->brother)) {
+    int val1 = (*pp)->value;
+    if (abs(val-val1) <= noise) {
+      seed = (seed*13077+5051)%0100000;
+      if ((seed & 070) >= 060) break;
+    }
+    else if (val > val1) break;
+  }
+  n->brother = *pp;
+  *pp = n;
+}
+
+// --------------------------------------------------------------
+
+void movepiece(node* f, int i, node* jnode) {
+  static char jumphappened;
+
+  for (int k=0; k<4; k++) {
+    int direction = offset[b[i]][k];
+    if (!direction) break;
+    int j = i+direction;
+    if (b[j] == EMPTY) {
+      if (!jnode && (!forcejumps || !f->son || !f->son->jump)) {
+	node* n = newnode();
+	n->father = f;
+	n->who = !f->who;
+	n->from = i;
+	n->to = j;
+	piece oldpiece = b[i]; b[i] = EMPTY;
+	if (!(oldpiece&KING) && n->who ? (j>=36) : (j<=8)) {
+	  n->king = 1;
+	  b[j] = oldpiece|KING;
+	}
+	else b[j] = oldpiece;
+	evaluateboard(n,0);
+	insert(n);
+	b[i] = oldpiece; b[j] = EMPTY;
+      }
+    } else if (((b[j]^b[i])&(WHITE|BLACK))==(WHITE|BLACK) && !b[j+direction]) {
+      if (forcejumps && f->son && !f->son->jump) {
+	killnode(f->son);
+	f->son = 0;
+      }
+      int jumploc = j;
+      j += direction;
+      node* n = newnode();
+      n->father = f;
+      n->who = !f->who;
+      n->from = i;
+      n->to = j;
+      n->jump = (1<<(jumploc-10));
+      piece oldpiece = b[i]; b[i] = EMPTY;
+      if (!(oldpiece&KING) && n->who ? (j>=36) : (j<=8)) {
+	n->king = 1;
+	b[j] = oldpiece|KING;
+      }
+      else b[j] = oldpiece;
+      if (jnode) {
+	n->from = jnode->from;
+	n->jump |= jnode->jump;
+	n->king |= jnode->king;
+      }
+      piece jumpedpiece = b[jumploc];
+      b[jumploc] = EMPTY;
+      jumphappened = 0;
+      movepiece(f,j,n);
+      if (forcejumps && jumphappened) killnode(n);
+      else {evaluateboard(n,0); insert(n);}
+      b[i] = oldpiece; b[j] = EMPTY;
+      b[jumploc] = jumpedpiece;
+      jumphappened = 1;
+    }
+  }
+}
+
+void expandnode(node *f) {
+  if (f->son || f->value > 28000) return;	// already done
+  piece turn = f->who ? BLACK : WHITE;
+  for (int i=5; i<40; i++) if (b[i]&turn) movepiece(f,i,0);
+  if (f->son) {
+    f->value = -f->son->value;
+    if (f->brother) f->value -= depthpenalty;
+  }
+  else f->value = 30000;
+}
+
+void makemove(node *n) {
+  b[n->to] = b[n->from];
+  if (n->king) b[n->to] |= KING;
+  b[n->from] = EMPTY;
+  if (n->jump) for(int i=0; i<32; i++) {
+    if (n->jump & (1< maxnodes-(maxply*10) || evaluated > maxevaluate) return(0);
+  expandnode(f);
+  if (!f->son) return(1);
+  piece oldboard[45];
+  memmove(oldboard,b,sizeof(b));
+  node* n = f->son;
+  if (!n->jump && n->brother) {if (level<1) return(1); level--;}
+  int i;
+  node* sons[32]; for (i=0; (sons[i++] = n); n = n->brother);
+  int ret = 1;
+  for (i=0; ret && (n = sons[i++]);) {
+    makemove(n);
+    ret = fullexpand(n,level);
+    memmove(b,oldboard,sizeof(b));
+    extract(n);
+    insert(n);
+  }
+  f->value = -f->son->value;
+  return(ret);
+}
+
+int descend(node *f) {
+  static int depth;
+  if (didabort() || nodes > maxnodes || depth >= maxply) return(0);
+  if (f->son) {
+    node* n = f->son;
+    makemove(n);
+    depth++;
+    int ret = descend(n);
+    depth--;
+    extract(n);
+    insert(n);
+    f->value = -f->son->value;
+    return(ret);
+  }
+  else {expandnode(f); return(1);}
+}
+
+char debug;
+
+node *calcmove(node *root) {	// return best move after root
+  expandnode(root);
+  if (!root->son) return(0);	// no move due to loss
+  if (debug) printf("calcmove() initial nodes = %d\n",nodes);
+  evaluated = 0;
+  if (root->son->brother) {
+    int x;
+    for (x = 1; abs(root->value)<28000 && fullexpand(root,x); x++);
+    piece saveboard[45]; memmove(saveboard,b,sizeof(b));
+    while (abs(root->value)<28000) {
+      x = descend(root);
+      memmove(b,saveboard,sizeof(b));
+      if (!x) break;
+    }
+  }
+  if (debug) printf(" evaluated %d, nodes = %d\n", evaluated, nodes);
+  return(root->son);
+}
+
+// the actual game state ----------------
+
+node *root,*undoroot;
+
+piece jumpboards[24][45];	// saved boards for undoing jumps
+int nextjump;
+
+char user;	// 0 = black, 1 = white
+char playing;
+char autoplay;
+
+void newgame(void) {
+
+  int n;
+  for (n=0; n<5; n++) b[n] = BLUE;
+  for (n=5; n<18; n++) b[n] = WHITE;
+  for (n=18; n<27; n++) b[n] = EMPTY;
+  for (n=27; n<40; n++) b[n] = BLACK;
+  for (n=40; n<45; n++) b[n] = BLUE;
+  b[13] = b[22] = b[31] = BLUE;
+
+  centralsquares[15] = centralsquares[16] =
+    centralsquares[19] = centralsquares[20] =
+    centralsquares[24] = centralsquares[25] =
+    centralsquares[28] = centralsquares[29] = 1;
+
+  // set up initial search tree:
+  nextjump = 0;
+  killnode(undoroot);
+  undoroot = root = newnode();
+
+  // make it white's move, so first move is black:
+  root->who = 1;
+  user = 0;
+  playing = 1;
+}
+
+void domove(node* move) {
+  if (move->jump) memmove(jumpboards[nextjump++],b,sizeof(b));
+  makemove(move);
+  extract(move);
+  killnode(root->son);
+  root->son = move;
+  root = move;
+  if (debug) evaluateboard(move,1);
+}
+
+node* undomove() {
+  node *n = root;
+  if (n == undoroot) return 0; // no more undo possible
+  if (n->jump) memmove(b,jumpboards[--nextjump],sizeof(b));
+  else {
+    b[n->from] = b[n->to];
+    if (n->king) b[n->from] &= (WHITE|BLACK);
+    b[n->to] = EMPTY;
+  }
+  root = n->father;
+  killnode(n);
+  root->son = 0;
+  root->value = 0;	// prevent it from thinking game is over
+  playing = 1;
+  if (root == undoroot) user = 0;
+  return n;
+}
+
+const char _usermoves[] =
+"B1D1F1H1A2C2E2G2??B3D3F3H3A4C4E4G4??B5D5F5H5A6C6E6G6??B7D7F7H7A8C8E8G8??";
+#define usermoves(x,y) _usermoves[2*((x)-5)+(y)-1]
+
+void dumpnode(node *n, int help) {
+  int x = n->from;
+  int y = n->to;
+  if (help) printf("%c%c %c%c\t- ",
+		   usermoves(x,1),usermoves(x,2),
+		   usermoves(y,1),usermoves(y,2));
+  printf("%s %ss from %c%c to %c%c",
+	 n->who ? "White" : "Black",
+	 n->jump ? "jump" : "move",
+	 usermoves(x,1),usermoves(x,2),
+	 usermoves(y,1),usermoves(y,2));
+  if (n->jump) {
+    for (int i=0; i<32; i++) if (n->jump & (1<value);
+}
+
+int abortflag;
+
+////////////////////////////////////////////////////////////////
+// VT100 Interface:
+#ifdef VT100
+
+void positioncursor(int i) {
+  printf("\033[%d;%dH",
+	 usermoves(i,2)-'0'+1,
+	 2*(usermoves(i,1)-'A')+1);
+}
+
+void outpiecename(piece n) {
+  printf(n&BLACK ? "\033[1;7m" : "\033[1m");
+  putchar(" BW??BW??"[n]);
+  putchar(" BW??KK??"[n]);
+  printf("\033[0m");
+}
+
+void VT100board(void) {
+  printf("\033<\033[H\033[J\033[10r");
+  int l = 0;
+  puts(" A B C D E F G H");
+  for (int i=0; i<4; i++) {
+    int j = 9*i+5;
+    int k;
+    for (k=0; k<4; k++) {
+      printf("\033[7m  \033[0m");
+      outpiecename(b[j+k]);
+    }
+    l++;
+    printf("%d\n",l);
+    j += 4;
+    for (k=0; k<4; k++) {
+      outpiecename(b[j+k]);
+      printf("\033[7m  \033[0m");
+    }
+    l++;
+    printf("%d\n",l);
+  }
+}
+
+void VT100move(node *n, int) {
+  if (!n) return;
+  printf("\0337");
+  positioncursor(n->from);
+  outpiecename(b[n->from]);
+  positioncursor(n->to);
+  outpiecename(b[n->to]);
+  if (n->jump) for(int i=0; i<32; i++) {
+    if (n->jump & (1<
+
+static void sigint(...) {
+  abortflag = 1;
+  signal(SIGINT,sigint);
+}
+
+void fixexit(int x) {
+  printf("\0337\033[r\0338");
+  exit(x);
+}
+
+// Returns a son, or 0 if no move specified, or root to cause "help"
+node *getusermove(void) {
+  int i,j;
+  node *t;
+  char line[100],*m1,*m2;
+
+  if (playing)
+    printf("\033[1m%s's move?\033[0m ",root->who ? "Black" : "White");
+  else
+    printf("\033[1mCommand?\033[0m ");
+  abortflag = 0;
+  if (!gets(line)) {
+    putchar('\n');
+    if (feof(stdin)) fixexit(0);
+    return 0;
+  }
+  for (m1 = line; *m1 && *m1<=' '; m1++);
+  if (!*m1) return(0);
+  m2 = m1+1;
+  if (*m2) m2++;
+  for (; *m2 && *m2<'0'; m2++);
+  if (playing && m1[1]>='0' && m1[1]<='9') {
+    i = decode(m1);
+    j = decode(m2);
+    if (i && j) for (t = root->son; t; t = t->brother)
+      if (t->from == i && t->to == j) return(t);
+    puts("Valid moves are:");
+    m1[0] = 'L';
+  }
+  switch(toupper(m1[0])) {
+  case 0: return(0);
+  case 'A':
+    if (playing) autoplay = 1;
+    return(root);
+  case 'C':
+    puts(copyright);
+    break;
+  case 'D':
+    debug = !debug;
+    printf("Debug is now %s.", debug ? "on" : "off");
+    break;
+  case 'F':
+    forcejumps = !forcejumps;
+    printf("Forced jumps rule is now %s.",forcejumps ? "on" : "off");
+    killnode(root->son); root->son = 0;
+    return(0);
+  case 'L':
+    expandnode(root);
+    if (playing) for (t = root->son; t; t = t->brother) dumpnode(t,1);
+    break;
+  case 'M':
+    return(playing ? root : 0);
+  case 'N':
+    newgame();
+    VT100board();
+    return(0);
+  case 'P':
+    printf("I expect the following moves:\n");
+    for (t = root->son; t; t = t->son) dumpnode(t,0);
+    break;
+  case 'Q':
+    fixexit(0);
+  case 'R':
+    VT100board();
+    break;
+  case 'S':
+    user = !user;
+    return(root);
+  case 'U':
+    VT100move(undomove(),1);
+    VT100move(undomove(),1);
+    return(0);
+  case '+':
+    maxevaluate = maxnodes = 2*maxevaluate;
+    goto J2;
+  case '-':
+    if (maxevaluate > 1)
+      maxevaluate = maxnodes = maxevaluate/2;
+  J2: printf("Moves evaluated set to %d.",maxevaluate);
+    break;
+  default:
+    puts(
+	 "A(utoplay)\n"
+	 "C(opyright)\n"
+	 "D(ebug on/off)\n"
+	 "F(orce jumps rule on/off)\n"
+	 "L(ist legal moves)\n"
+	 "M(ake a move for me)\n"
+	 "N(ew game)\n"
+	 "P(redict next few moves)\n"
+	 "Q(uit)\n"
+	 "R(edraw screen)\n"
+	 "S(witch sides)\n"
+	 "U(ndo)\n"
+	 "+	- smarter\n"
+	 "-	- stupider");
+    expandnode(root);
+    for (t = root->son; t; t = t->brother) dumpnode(t,1);
+  }
+  return(0);
+}
+
+int VT100main() {
+  signal(SIGINT,sigint);
+  VT100board();
+  for (;;) {
+    if (playing) {
+      expandnode(root);
+      if (!root->son) {
+	printf("%s has no move.  Game over.",root->who ? "Black" : "White");
+	playing = autoplay = 0;
+      }
+    }
+    node* move;
+    if (playing && (autoplay || root->who == user)) {
+      move = calcmove(root);
+      if (move->value <= -30000) {
+ 	printf("%s resigns.", move->who ? "White" : "Black");
+ 	move = 0;
+ 	playing = autoplay = 0;
+      }
+    } else {
+      move = getusermove();
+      if (move == root) move = calcmove(root);
+    }
+    if (move) {
+      dumpnode(move,0);
+      domove(move);
+      VT100move(move,0);
+    }
+  }
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////
+// fltk interface:
+#ifdef FLTK
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+//----------------------------------------------------------------
+// old 4-level NeXT images have been seperated into bitmaps so they
+// can be drawn with arbitrary colors and real transparency.  This is
+// rather tedious and perhaps fltk should provide a direct support
+// to do this:
+
+#include "black_1.xbm"
+#include "black_2.xbm"
+#include "black_3.xbm"
+#include "black_4.xbm"
+#include "white_1.xbm"
+#include "white_2.xbm"
+#include "white_3.xbm"
+#include "white_4.xbm"
+#include "blackking_1.xbm"
+#include "blackking_2.xbm"
+#include "blackking_3.xbm"
+#include "blackking_4.xbm"
+#include "whiteking_1.xbm"
+#include "whiteking_2.xbm"
+#include "whiteking_3.xbm"
+#include "whiteking_4.xbm"
+
+Fl_Bitmap *bm[4][4];
+
+void make_bitmaps() {
+  if (bm[0][0]) return;
+  bm[0][0] = new Fl_Bitmap(black_1_bits, black_1_width, black_1_height);
+  bm[0][1] = new Fl_Bitmap(black_2_bits, black_1_width, black_1_height);
+  bm[0][2] = new Fl_Bitmap(black_3_bits, black_1_width, black_1_height);
+  bm[0][3] = new Fl_Bitmap(black_4_bits, black_1_width, black_1_height);
+  bm[1][0] = new Fl_Bitmap(white_1_bits, black_1_width, black_1_height);
+  bm[1][1] = new Fl_Bitmap(white_2_bits, black_1_width, black_1_height);
+  bm[1][2] = new Fl_Bitmap(white_3_bits, black_1_width, black_1_height);
+  bm[1][3] = new Fl_Bitmap(white_4_bits, black_1_width, black_1_height);
+  bm[2][0] = new Fl_Bitmap(blackking_1_bits, black_1_width, black_1_height);
+  bm[2][1] = new Fl_Bitmap(blackking_2_bits, black_1_width, black_1_height);
+  bm[2][2] = new Fl_Bitmap(blackking_3_bits, black_1_width, black_1_height);
+  bm[2][3] = new Fl_Bitmap(blackking_4_bits, black_1_width, black_1_height);
+  bm[3][0] = new Fl_Bitmap(whiteking_1_bits, black_1_width, black_1_height);
+  bm[3][1] = new Fl_Bitmap(whiteking_2_bits, black_1_width, black_1_height);
+  bm[3][2] = new Fl_Bitmap(whiteking_3_bits, black_1_width, black_1_height);
+  bm[3][3] = new Fl_Bitmap(whiteking_4_bits, black_1_width, black_1_height);
+}
+
+#define ISIZE black_1_width
+
+void draw_piece(int which, int x, int y) {
+  if (!fl_not_clipped(x,y,ISIZE,ISIZE)) return;
+  switch (which) {
+  case BLACK: which = 0; break;
+  case WHITE: which = 1; break;
+  case BLACKKING: which = 2; break;
+  case WHITEKING: which = 3; break;
+  default: return;
+  }
+  fl_color(FL_BLACK); bm[which][0]->draw(x, y);
+  fl_color(FL_INACTIVE_COLOR); bm[which][1]->draw(x, y);
+  fl_color(FL_SELECTION_COLOR);bm[which][2]->draw(x, y);
+  fl_color(FL_WHITE); bm[which][3]->draw(x, y);
+}
+
+//----------------------------------------------------------------
+
+class Board : public Fl_Double_Window {
+  void draw();
+  int handle(int);
+public:
+  void drag_piece(int, int, int);
+  void drop_piece(int);
+  void animate(node* move, int backwards);
+  void computer_move(int);
+  Board(int w, int h) : Fl_Double_Window(w,h) {color(15);}
+};
+
+#define BOXSIZE 52
+#define BORDER 4
+#define BOARDSIZE (8*BOXSIZE+BORDER)
+#define BMOFFSET 5
+
+static int erase_this;  // real location of dragging piece, don't draw it
+static int dragging;	// piece being dragged
+static int dragx;	// where it is
+static int dragy;
+static int showlegal;	// show legal moves
+
+int squarex(int i) {return (usermoves(i,1)-'A')*BOXSIZE+BMOFFSET;}
+int squarey(int i) {return (usermoves(i,2)-'1')*BOXSIZE+BMOFFSET;}
+
+void Board::draw() {
+  make_bitmaps();
+  fl_draw_box(box(),0,0,w(),h(),color());
+  fl_color((Fl_Color)10 /*107*/);
+  int x; for (x=0; x<8; x++) for (int y=0; y<8; y++) {
+    if (!((x^y)&1)) fl_rectf(BORDER+x*BOXSIZE, BORDER+y*BOXSIZE,
+			     BOXSIZE-BORDER, BOXSIZE-BORDER);
+  }
+  fl_color(FL_DARK3 /*FL_GRAY_RAMP+4*/);
+  for (x=0; x<9; x++) {
+    fl_rectf(x*BOXSIZE,0,BORDER,h());
+    fl_rectf(0,x*BOXSIZE,w(),BORDER);
+  }
+  for (int i = 5; i < 40; i++) if (i != erase_this) {
+    draw_piece(b[i], squarex(i), squarey(i));
+  }
+  if (showlegal) {
+    fl_color(FL_WHITE);
+    node* n;
+    for (n = root->son; n; n = showlegal==2 ? n->son : n->brother) {
+      int x1 = squarex(n->from)+BOXSIZE/2-5;
+      int y1 = squarey(n->from)+BOXSIZE/2-5;
+      int x2 = squarex(n->to)+BOXSIZE/2-5;
+      int y2 = squarey(n->to)+BOXSIZE/2-5;
+      fl_line(x1,y1,x2,y2);
+      fl_push_matrix();
+      fl_mult_matrix(x2-x1,y2-y1,y1-y2,x2-x1,x2,y2);
+      fl_begin_polygon();
+      fl_vertex(0,0);
+      fl_vertex(-.3, .1);
+      fl_vertex(-.3, -.1);
+      fl_end_polygon();
+      fl_pop_matrix();
+    }
+    int num = 1;
+    fl_color(FL_BLACK);
+    fl_font(FL_BOLD,10);
+    for (n = root->son; n; n = showlegal==2 ? n->son : n->brother) {
+      int x1 = squarex(n->from)+BOXSIZE/2-5;
+      int y1 = squarey(n->from)+BOXSIZE/2-5;
+      int x2 = squarex(n->to)+BOXSIZE/2-5;
+      int y2 = squarey(n->to)+BOXSIZE/2-5;
+      char buf[20]; sprintf(buf,"%d",num);
+      fl_draw(buf, x1+int((x2-x1)*.85)-3, y1+int((y2-y1)*.85)+5);
+      num++;
+    }
+  }
+  if (dragging) draw_piece(dragging, dragx, dragy);
+}
+
+// drag the piece on square i to dx dy, or undo drag if i is zero:
+void Board::drag_piece(int i, int dx, int dy) {
+  dy = (dy&-2) | dx&1; // make halftone shadows line up
+  if (i != erase_this) drop_piece(erase_this); // should not happen
+  if (!erase_this) { // pick up old piece
+    dragx = squarex(i); dragy = squarey(i);
+    erase_this = i;
+    dragging = b[i];
+  }
+  if (dx != dragx || dy != dragy) {
+    damage(4, dragx, dragy, ISIZE, ISIZE);
+    damage(4, dx, dy, ISIZE, ISIZE);
+  }
+  dragx = dx;
+  dragy = dy;
+}
+
+// drop currently dragged piece on square i
+void Board::drop_piece(int i) {
+  if (!erase_this) return; // should not happen!
+  erase_this = 0;
+  dragging = 0;
+  int x = squarex(i);
+  int y = squarey(i);
+  if (x != dragx || y != dragy) {
+    damage(4, dragx, dragy, ISIZE, ISIZE);
+    damage(4, x, y, ISIZE, ISIZE);
+  }
+}
+
+// show move (call this *before* the move, *after* undo):
+void Board::animate(node* move, int backwards) {
+  if (showlegal) {showlegal = 0; redraw();}
+  if (!move) return;
+  int f = move->from;
+  int t = move->to;
+  if (backwards) {int x = f; f = t; t = x;}
+  int x1 = squarex(f);
+  int y1 = squarey(f);
+  int x2 = squarex(t);
+  int y2 = squarey(t);
+  const int STEPS=35;
+  for (int i=0; ifrom,x,y);
+    Fl::flush();
+  }
+  drop_piece(t);
+  if (move->jump) redraw();
+}
+
+int busy; // causes pop-up abort menu
+
+void message(const char* m, ...) {
+  char buffer[2048];
+  va_list a;
+  va_start(a,m);
+  vsprintf(buffer, m, a);
+  va_end(a);
+  fl_message(buffer);
+}
+
+void Board::computer_move(int help) {
+  if (!playing) return;
+  cursor(FL_CURSOR_WAIT);
+  Fl::flush();
+  busy = 1; abortflag = 0;
+  node* move = calcmove(root);
+  busy = 0;
+  if (move) {
+    if (!help && move->value <= -30000) {
+      message("%s resigns", move->who ? "White" : "Black");
+      playing = autoplay = 0;
+      cursor(FL_CURSOR_DEFAULT);
+      return;
+    }
+    animate(move,0);
+    domove(move);
+  }
+  expandnode(root);
+  if (!root->son) {
+    message("%s has no move", root->who ? "Black" : "White");
+    playing = autoplay = 0;
+  }
+  if (!autoplay) cursor(FL_CURSOR_DEFAULT);
+}
+
+extern Fl_Menu_Item menu[];
+extern Fl_Menu_Item busymenu[];
+
+int Board::handle(int e) {
+  if (busy) {
+    const Fl_Menu_Item* m;
+    switch(e) {
+    case FL_PUSH:
+      m = busymenu->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0);
+      if (m) m->do_callback(this, (void*)m);
+      return 1;
+    case FL_SHORTCUT:
+      m = busymenu->test_shortcut();
+      if (m) {m->do_callback(this, (void*)m); return 1;}
+      return 0;
+    default:
+      return 0;
+    }
+  }
+  node *t, *n;
+  static int deltax, deltay;
+  int dist;
+  const Fl_Menu_Item* m;
+  switch (e) {
+  case FL_PUSH:
+    if (Fl::event_button() > 1) {
+      m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0);
+      if (m) m->do_callback(this, (void*)m);
+      return 1;
+    }
+    if (playing) {
+      expandnode(root);
+      for (t = root->son; t; t = t->brother) {
+	int x = squarex(t->from);
+	int y = squarey(t->from);
+	if (Fl::event_inside(x,y,BOXSIZE,BOXSIZE)) {
+	  deltax = Fl::event_x()-x;
+	  deltay = Fl::event_y()-y;
+	  drag_piece(t->from,x,y);
+	  return 1;
+	}
+      }
+    }
+    return 0;
+  case FL_SHORTCUT:
+    m = menu->test_shortcut();
+    if (m) {m->do_callback(this, (void*)m); return 1;}
+    return 0;
+  case FL_DRAG:
+    drag_piece(erase_this, Fl::event_x()-deltax, Fl::event_y()-deltay);
+    return 1;
+  case FL_RELEASE:
+    // find the closest legal move he dropped it on:
+    dist = 50*50; n = 0;
+    for (t = root->son; t; t = t->brother) if (t->from==erase_this) {
+      int d1 = Fl::event_x()-deltax-squarex(t->to);
+      int d = d1*d1;
+      d1 = Fl::event_y()-deltay-squarey(t->to);
+      d += d1*d1;
+      if (d < dist) {dist = d; n = t;}
+    }
+    if (!n) {drop_piece(erase_this); return 1;} // none found
+    drop_piece(n->to);
+    domove(n);
+    if (showlegal) {showlegal = 0; redraw();}
+    if (n->jump) redraw();
+    computer_move(0);
+    return 1;
+  default:
+    return 0;
+  }
+}
+
+void quit_cb(Fl_Widget*, void*) {exit(0);}
+
+int FLTKmain(int argc, char** argv) {
+  Board b(BOARDSIZE,BOARDSIZE);
+  b.callback(quit_cb);
+  b.show(argc,argv);
+  return Fl::run();
+} 
+
+void autoplay_cb(Fl_Widget*bp, void*) {
+  if (autoplay) {autoplay = 0; return;}
+  if (!playing) return;
+  Board* b = (Board*)bp;
+  autoplay = 1;
+  while (autoplay) {b->computer_move(0); b->computer_move(0);}
+}
+
+#include 
+Fl_Window *copyright_window;
+void copyright_cb(Fl_Widget*, void*) {
+  if (!copyright_window) {
+    copyright_window = new Fl_Window(400,270,"Copyright");
+    copyright_window->color(FL_WHITE);
+    Fl_Box *b = new Fl_Box(20,0,380,270,copyright);
+    b->labelsize(10);
+    b->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
+    copyright_window->end();
+  }
+  copyright_window->hotspot(copyright_window);
+  copyright_window->set_non_modal();
+  copyright_window->show();
+}
+
+void debug_cb(Fl_Widget*, void*v) {
+  debug = !debug;
+  ((Fl_Menu_Item*)v)->flags =
+    debug ? FL_MENU_TOGGLE|FL_MENU_VALUE : FL_MENU_TOGGLE;
+}
+
+void forced_cb(Fl_Widget*b, void*v) {
+  forcejumps = !forcejumps;
+  ((Fl_Menu_Item*)v)->flags =
+    forcejumps ? FL_MENU_TOGGLE|FL_MENU_VALUE : FL_MENU_TOGGLE;
+  killnode(root->son); root->son = 0;
+  if (showlegal) {expandnode(root); b->redraw();}
+}
+
+void move_cb(Fl_Widget*pb, void*) {
+  Board* b = (Board*)pb;
+  if (playing) b->computer_move(1);
+  if (playing) b->computer_move(0);
+}
+
+void newgame_cb(Fl_Widget*b, void*) {
+  showlegal = 0;
+  newgame();
+  b->redraw();
+}
+
+void legal_cb(Fl_Widget*pb, void*) {
+  if (showlegal == 1) {showlegal = 0; ((Board*)pb)->redraw(); return;}
+  if (!playing) return;
+  expandnode(root);
+  showlegal = 1; ((Board*)pb)->redraw();
+}
+
+void predict_cb(Fl_Widget*pb, void*) {
+  if (showlegal == 2) {showlegal = 0; ((Board*)pb)->redraw(); return;}
+  if (playing) expandnode(root);
+  showlegal = 2; ((Board*)pb)->redraw();
+}
+
+void switch_cb(Fl_Widget*pb, void*) {
+  user = !user;
+  ((Board*)pb)->computer_move(0);
+}
+
+void undo_cb(Fl_Widget*pb, void*) {
+  Board* b = (Board*)pb;
+  b->animate(undomove(),1);
+  b->animate(undomove(),1);
+}
+
+//--------------------------
+
+#include 
+#include 
+
+Fl_Window *intel_window;
+Fl_Value_Output *intel_output;
+
+void intel_slider_cb(Fl_Widget*w, void*) {
+  double v = ((Fl_Slider*)w)->value();
+  int n = int(v*v);
+  intel_output->value(n);
+  maxevaluate = maxnodes = n;
+}
+
+void intel_cb(Fl_Widget*, void*) {
+  if (!intel_window) {
+    intel_window = new Fl_Window(200,25,"Checkers Intelligence");
+    Fl_Slider* s = new Fl_Slider(60,0,140,25);
+    s->type(FL_HOR_NICE_SLIDER);
+    s->minimum(1); s->maximum(500); s->value(50);
+    s->callback(intel_slider_cb);
+    intel_output = new Fl_Value_Output(0,0,60,25);
+    intel_output->value(maxevaluate);
+    intel_window->resizable(s);
+  }
+  intel_window->hotspot(intel_window);
+  intel_window->set_non_modal();
+  intel_window->show();
+}
+
+//---------------------------
+
+void stop_cb(Fl_Widget*, void*) {abortflag = 1;}
+
+void continue_cb(Fl_Widget*, void*) {}
+
+Fl_Menu_Item menu[] = {
+  {"Autoplay", 'a', autoplay_cb},
+  {"Legal moves", 'l', legal_cb},
+  {"Move for me", 'm', move_cb},
+  {"New game", 'n', newgame_cb},
+  {"Predict", 'p', predict_cb},
+  {"Switch sides", 's', switch_cb},
+  {"Undo", 'u', undo_cb, 0, FL_MENU_DIVIDER},
+  {"Forced jumps rule", 'f', forced_cb, 0, FL_MENU_TOGGLE|FL_MENU_VALUE},
+  {"Debug", 'd', debug_cb, "d", FL_MENU_TOGGLE},
+  {"Intelligence...", 'i', intel_cb, 0, FL_MENU_DIVIDER},
+  {"Copyright", 'c', copyright_cb},
+  {"Quit", 'q', quit_cb},
+  {0}};
+
+Fl_Menu_Item busymenu[] = {
+  {"Stop", '.', stop_cb},
+  {"Autoplay", 'a', autoplay_cb},
+  {"Continue", 0, continue_cb},
+  {"Debug", 'd', debug_cb, "d", FL_MENU_TOGGLE},
+  {"Intelligence...", 'i', intel_cb},
+  {"Copyright", 'c', copyright_cb},
+  {"Quit", 'q', quit_cb},
+  {0}};
+
+#endif
+
+////////////////////////////////////////////////////////////////
+// parts shared by both interface:
+
+#ifdef FLTK
+#ifdef VT100
+#define BOTH
+#endif
+#endif
+
+#ifdef BOTH
+int terminal;
+int arg(int, char **argv, int &i) {
+  if (argv[i][1] == 't') {terminal = 1; i++; return 1;}
+  return 0;
+}
+#endif
+
+int didabort(void) {
+#ifdef FLTK
+#ifdef BOTH
+  if (!terminal)
+#endif
+    Fl::check();
+#endif
+  if (abortflag) {
+    autoplay = 0;
+    abortflag = 0;
+    return 1;
+  }
+  return(0);
+}
+
+int main(int argc, char **argv) {
+  seed = time(0);
+  newgame();
+#ifdef BOTH
+  int i = 1;
+  if (Fl::args(argc, argv, i, arg) < argc) {
+    fprintf(stderr," -t : use VT100 display\n", Fl::help);
+    exit(1);
+  }
+  if (!getenv("DISPLAY")) terminal = 1;
+  if (!terminal)
+#endif
+#ifdef FLTK
+    return FLTKmain(argc,argv);
+#endif
+#ifdef VT100
+  return VT100main();
+#endif
+}
diff --git a/test/clock.cxx b/test/clock.cxx
new file mode 100644
index 000000000..0210a4e2a
--- /dev/null
+++ b/test/clock.cxx
@@ -0,0 +1,24 @@
+//	produce images for documentation
+
+#include 
+#include 
+#include 
+#include 
+
+int main(int argc, char **argv) {
+  Fl_Window window(220,220,"Fl_Clock");
+  Fl_Clock c1(0,0,220,220); // c1.color(2,1);
+  window.resizable(c1);
+  window.end();
+  Fl_Window window2(220,220,"Fl_Round_Clock");
+  Fl_Round_Clock c2(0,0,220,220); // c2.color(3,4);
+  window2.resizable(c2);
+  window2.end();
+  // my machine had a clock* Xresource set for another program, so
+  // I don't want the class to be "clock":
+  window.xclass("Fl_Clock");
+  window2.xclass("Fl_Clock");
+  window.show(argc,argv);
+  window2.show();
+  return Fl::run();
+}
diff --git a/test/colbrowser.cxx b/test/colbrowser.cxx
new file mode 100644
index 000000000..8ee56d3ee
--- /dev/null
+++ b/test/colbrowser.cxx
@@ -0,0 +1,316 @@
+// This is an XForms program from the 0.86 distribution of XForms.
+// It has been modified as little as possible to work under fltk by
+// using fltk's Forms emulation.
+// Search for "fltk" to find all the changes
+
+#include 	// changed for fltk
+#include 
+#include 	// added for fltk
+#include 	// added for fltk
+
+#define MAX_RGB 3000
+
+static FL_FORM *cl;
+static Fl_Widget *rescol, *dbobj, *colbr, *rs, *gs, *bs;
+char dbname[FL_PATH_MAX];
+static void create_form_cl(void);
+static int load_browser(char *);
+
+/* the RGB data file does not have a standard location on unix. */
+
+#ifdef __VMS
+  static char *rgbfile = "SYS$MANAGER:DECW$RGB.DAT";
+#else
+#ifdef __EMX__   /* OS2 */
+  static char *rgbfile = "/XFree86/lib/X11/rgb.txt";
+#else
+#ifdef __FreeBSD__
+  static char *rgbfile = "/usr/X11R6/lib/X11/rgb.txt";
+#else
+   static char *rgbfile = "/usr/lib/X11/rgb.txt";
+#endif
+#endif
+#endif
+
+typedef struct { int r, g, b; } RGBdb;
+
+static RGBdb rgbdb[MAX_RGB];
+
+int
+main(int argc, char *argv[])
+{
+
+    fl_initialize(&argc, argv, "FormDemo", 0, 0);
+
+    create_form_cl();
+    strcpy(dbname, rgbfile);
+
+    if (load_browser(dbname))
+	fl_set_object_label(dbobj, dbname);
+    else
+	fl_set_object_label(dbobj, "None");
+
+//    fl_set_form_minsize(cl, cl->w , cl->h); // removed for fltk
+//    fl_set_form_maxsize(cl, 2*cl->w , 2*cl->h); // removed for fltk
+    cl->size_range(cl->w(),cl->h(),2*cl->w(),2*cl->h()); // added for fltk
+    // border changed from FL_TRANSIENT for fltk:
+    // This is so Esc & the close box will close the window.
+    // (on transient windows attempting to close it just calls the callback)
+    fl_show_form(cl, FL_PLACE_FREE, 1/*FL_TRANSIENT*/, "RGB Browser");
+
+
+    while (fl_do_forms())
+	;
+    return 0;
+}
+
+static void
+set_entry(int i)
+{
+    RGBdb *db = rgbdb + i;
+
+    fl_freeze_form(cl);
+// unclear why demo is doing this.  This messes up FL:
+//    fl_mapcolor(FL_FREE_COL4+i, db->r, db->g, db->b);
+    fl_mapcolor(FL_FREE_COL4, db->r, db->g, db->b);
+    fl_set_slider_value(rs, db->r);
+    fl_set_slider_value(gs, db->g);
+    fl_set_slider_value(bs, db->b);
+    fl_redraw_object(rescol);
+    fl_unfreeze_form(cl);
+}
+
+static void
+br_cb(Fl_Widget * ob, long)
+{
+    int r = fl_get_browser(ob);
+
+    if (r <= 0)
+	return;
+    set_entry(r - 1);
+}
+
+static int
+read_entry(FILE * fp, int *r, int *g, int *b, char *name)
+{
+    int  n;
+    char buf[512], *p;
+
+    if (!fgets(buf, sizeof(buf) - 1, fp))
+      return 0;
+
+    if(buf[0] == '!')
+      fgets(buf,sizeof(buf)-1,fp);
+
+    if(sscanf(buf, " %d %d %d %n", r, g, b, &n) < 3)
+	return 0;
+
+    p = buf + n;
+
+    /* squeeze out all spaces */
+    while (*p)
+    {
+	if (*p != ' ' && *p != '\n')
+	    *name++ = *p;
+	p++;
+    }
+    *name = 0;
+
+    return (feof(fp) || ferror(fp)) ? 0 : 1;
+}
+
+
+static int
+load_browser(char *fname)
+{
+    FILE *fp;
+    RGBdb *db = rgbdb, *dbs = db + MAX_RGB;
+    int r, g, b,  lr  = -1 , lg = -1, lb = -1;
+    char name[256], buf[256];
+#ifdef __EMX__
+    extern char *__XOS2RedirRoot(const char*);
+    if (!(fp = fopen(__XOS2RedirRoot(fname), "r")))
+#else
+    if (!(fp = fopen(fname, "r")))
+#endif
+    {
+	fl_show_alert("Load", fname, "Can't open", 0);
+	return 0;
+    }
+
+    /* read the items */
+
+    fl_freeze_form(cl);
+
+    for (; db < dbs && read_entry(fp, &r, &g, &b, name);)
+    {
+	db->r = r;
+	db->g = g;
+	db->b = b;
+
+	/* unique the entries on the fly */
+	if (lr != r || lg != g || lb != b)
+	{
+	    db++;
+	    lr = r;
+	    lg = g;
+	    lb = b;
+	    sprintf(buf, "(%3d %3d %3d) %s", r, g, b, name);
+	    fl_addto_browser(colbr, buf);
+	}
+    }
+    fclose(fp);
+
+    if (db < dbs)
+	db->r = 1000;		/* sentinel */
+    else
+    {
+	db--;
+	db->r = 1000;
+    }
+
+    fl_set_browser_topline(colbr, 1);
+    fl_select_browser_line(colbr, 1);
+    set_entry(0);
+    fl_unfreeze_form(cl);
+    return 1;
+}
+
+static int
+search_entry(int r, int g, int b)
+{
+    register RGBdb *db = rgbdb;
+    int i, j, diffr, diffg, diffb;
+    unsigned int diff, mindiff;
+
+    mindiff = ~0;
+    for (i = j = 0; db->r < 256; db++, i++)
+    {
+       diffr = r - db->r;
+       diffg = g - db->g;
+       diffb = b - db->b;
+
+#ifdef FL_LINEAR
+	diff = unsigned(3.0 * (FL_abs(r - db->r)) +
+			(5.9 * FL_abs(g - db->g)) +
+			(1.1 * (FL_abs(b - db->b)));
+#else
+        diff = unsigned(3.0 * (diffr *diffr) +
+			5.9 * (diffg *diffg) +
+			1.1 * (diffb *diffb));
+#endif
+
+	if (mindiff > diff)
+	{
+	    mindiff = diff;
+	    j = i;
+	}
+    }
+
+    return j;
+}
+
+static void
+search_rgb(Fl_Widget *, long)
+{
+    int r, g, b, i;
+    int top  = fl_get_browser_topline(colbr);
+
+    r = int(fl_get_slider_value(rs));
+    g = int(fl_get_slider_value(gs));
+    b = int(fl_get_slider_value(bs));
+
+    fl_freeze_form(cl);
+    fl_mapcolor(FL_FREE_COL4, r, g, b);
+    fl_redraw_object(rescol);
+    i = search_entry(r, g, b);
+    /* change topline only if necessary */
+    if(i < top || i > (top+15))
+       fl_set_browser_topline(colbr, i-8);
+    fl_select_browser_line(colbr, i + 1);
+    fl_unfreeze_form(cl);
+}
+
+/* change database */
+static void
+db_cb(Fl_Widget * ob, long)
+{
+    const char *p = fl_show_input("Enter New Database Name", dbname);
+    char buf[512];
+
+    if (!p || strcmp(p, dbname) == 0)
+	return;
+
+    strcpy(buf, p);
+    if (load_browser(buf))
+	strcpy(dbname, buf);
+    else
+	fl_set_object_label(ob, dbname);
+}
+
+static void
+done_cb(Fl_Widget *, long)
+{
+    exit(0);
+}
+
+static void
+create_form_cl(void)
+{
+    Fl_Widget *obj;
+
+    if (cl)
+	return;
+
+    cl = fl_bgn_form(FL_NO_BOX, 330, 385);
+    obj = fl_add_box(FL_UP_BOX, 0, 0, 330, 385, "");
+    fl_set_object_color(obj, FL_INDIANRED, FL_COL1);
+
+    obj = fl_add_box(FL_NO_BOX, 40, 10, 250, 30, "Color Browser");
+    fl_set_object_lcol(obj, FL_RED);
+    fl_set_object_lsize(obj, FL_HUGE_SIZE);
+    fl_set_object_lstyle(obj, FL_BOLD_STYLE + FL_SHADOW_STYLE);
+
+    dbobj = obj = fl_add_button(FL_NORMAL_BUTTON, 40, 50, 250, 25, "");
+    fl_set_object_boxtype(obj, FL_BORDER_BOX);
+    fl_set_object_color(obj, /*fl_get_visual_depth()==1 ? FL_WHITE:*/ FL_INDIANRED,
+                        FL_INDIANRED);
+    fl_set_object_callback(obj, db_cb, 0);
+    rs = obj = fl_add_valslider(FL_VERT_FILL_SLIDER, 225, 130, 30, 200, "");
+    fl_set_object_color(obj, FL_INDIANRED, FL_RED);
+    fl_set_slider_bounds(obj, 0, 255);
+    fl_set_slider_precision(obj, 0);
+    fl_set_object_callback(obj, search_rgb, 0);
+    fl_set_slider_return(obj, 0);
+
+    gs = obj = fl_add_valslider(FL_VERT_FILL_SLIDER, 255, 130, 30, 200, "");
+    fl_set_object_color(obj, FL_INDIANRED, FL_GREEN);
+    fl_set_slider_bounds(obj, 0, 255);
+    fl_set_slider_precision(obj, 0);
+    fl_set_object_callback(obj, search_rgb, 1);
+    fl_set_slider_return(obj, 0);
+
+    bs = obj = fl_add_valslider(FL_VERT_FILL_SLIDER, 285, 130, 30, 200, "");
+    fl_set_object_color(obj, FL_INDIANRED, FL_BLUE);
+    fl_set_slider_bounds(obj, 0, 255);
+    fl_set_slider_precision(obj, 0);
+    fl_set_object_callback(obj, search_rgb, 2);
+    fl_set_slider_return(obj, 0);
+
+
+    colbr = obj = fl_add_browser(FL_HOLD_BROWSER, 10, 90, 205, 240, "");
+    fl_set_browser_fontstyle(obj, FL_FIXED_STYLE); 
+    fl_set_object_callback(obj, br_cb, 0);
+
+
+    obj = fl_add_button(FL_NORMAL_BUTTON, 135, 345, 80, 30, "Done");
+    fl_set_object_callback(obj, done_cb, 0);
+
+    rescol = obj = fl_add_box(FL_FLAT_BOX, 225, 90, 90, 35, "");
+    fl_set_object_color(obj, FL_FREE_COL4, FL_FREE_COL4);
+    fl_set_object_boxtype(obj, FL_BORDER_BOX);
+
+
+    fl_end_form();
+    fl_scale_form(cl, 1.1, 1.0);
+}
diff --git a/test/color_chooser.cxx b/test/color_chooser.cxx
new file mode 100644
index 000000000..9cdcbd36a
--- /dev/null
+++ b/test/color_chooser.cxx
@@ -0,0 +1,125 @@
+/* 	Test forcing fltk to draw in different visuals:
+
+	This also tests fl_show_colormap and Fl_Color_Chooser
+
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include "list_visuals.C"
+
+int width = 75;
+int height = 75;
+uchar *image;
+
+void make_image() {
+  image = new uchar[3*width*height];
+  uchar *p = image;
+  for (int y = 0; y < height; y++) {
+    double Y = double(y)/(height-1);
+    for (int x = 0; x < width; x++) {
+      double X = double(x)/(width-1);
+      *p++ = uchar(255*((1-X)*(1-Y))); // red in upper-left
+      *p++ = uchar(255*((1-X)*Y));	// green in lower-left
+      *p++ = uchar(255*(X*Y));	// blue in lower-right
+    }
+  }
+}
+
+class Pens : public Fl_Box {
+  void draw();
+public:
+  Pens(int X, int Y, int W, int H, const char* L)
+    : Fl_Box(X,Y,W,H,L) {}
+};
+void Pens::draw() {
+  // use every color in the gray ramp:
+  for (int i = 0; i < 3*8; i++) {
+    fl_color((Fl_Color)(FL_GRAY_RAMP+i));
+    fl_line(x()+i, y(), x()+i, y()+h());
+  }
+}
+
+Fl_Color c = FL_GRAY;
+#define fullcolor_cell (FL_FREE_COLOR)
+
+void cb1(Fl_Widget *, void *v) {
+  c = fl_show_colormap(c);
+  Fl_Box* b = (Fl_Box*)v;
+  b->color(c);
+  b->parent()->redraw();
+}
+
+void cb2(Fl_Widget *, void *v) {
+  uchar r,g,b;
+  Fl::get_color(c,r,g,b);
+  if (!fl_color_chooser("New color:",r,g,b)) return;
+  c = fullcolor_cell;
+  Fl::set_color(fullcolor_cell,r,g,b);
+  Fl_Box* bx = (Fl_Box*)v;
+  bx->color(fullcolor_cell);
+  bx->parent()->redraw();
+}
+
+int main(int argc, char ** argv) {
+  Fl::set_color(fullcolor_cell,145,159,170);
+  Fl_Window window(400,400);
+  Fl_Box box(50,50,300,300);
+  box.box(FL_THIN_DOWN_BOX);
+  c = fullcolor_cell;
+  box.color(c);
+  Fl_Button b1(140,120,120,30,"fl_show_colormap");
+  b1.callback(cb1,&box);
+  Fl_Button b2(140,160,120,30,"fl_choose_color");
+  b2.callback(cb2,&box);
+  Fl_Box image_box(140,200,120,120,0);
+  make_image();
+  (new Fl_Image(image, width, height))->label(&image_box);
+  Fl_Box b(140,320,120,0,"Example of fl_draw_image()");
+  Pens p(80,200,3*8,120,"lines");
+  p.align(FL_ALIGN_TOP);
+  int i = 1;
+  if (!Fl::args(argc,argv,i) || i != argc-1) {
+    printf("usage: %s  visual-number\n"
+	   " - : default visual\n"
+	   " r : call Fl::visual(FL_RGB)\n"
+	   " c : call Fl::own_colormap()\n",argv[0]);
+#ifndef WIN32
+    printf(" # : use this visual with an empty colormap:\n");
+    list_visuals();
+#endif
+    puts(Fl::help);
+    exit(1);
+  }
+  if (argv[i][0] == 'r') {
+    if (!Fl::visual(FL_RGB)) printf("Fl::visual(FL_RGB) returned false.\n");
+  } else if (argv[i][0] == 'c') {
+    Fl::own_colormap();
+  } else if (argv[i][0] != '-') {
+#ifndef WIN32
+    int visid = atoi(argv[i]);
+    fl_open_display();
+    XVisualInfo templt; int num;
+    templt.visualid = visid;
+    fl_visual = XGetVisualInfo(fl_display, VisualIDMask, &templt, &num);
+    if (!fl_visual) Fl::fatal("No visual with id %d",visid);
+    fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen),
+				  fl_visual->visual, AllocNone);
+    fl_xpixel(FL_BLACK); // make sure black is allocated
+#else
+    Fl::fatal("Visual id's not supported on MSWindows");
+#endif
+  }
+  window.show(argc,argv);
+  return Fl::run();
+}
diff --git a/test/connect.cxx b/test/connect.cxx
new file mode 100644
index 000000000..26fd02d07
--- /dev/null
+++ b/test/connect.cxx
@@ -0,0 +1,47 @@
+/*	connect.C
+
+	Program to make a button to turn a ppp connection on/off.
+	You must chmod +s /usr/sbin/pppd, and put all the options
+	into /etc/ppp/options.
+
+*/
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+int running;	// actually the pid
+Fl_Toggle_Button *Button;
+
+void sigchld(int) {
+  running = 0;
+  Button->value(0);
+}
+
+void cb(Fl_Widget *o, void *) {
+  if (((Fl_Toggle_Button*)o)->value()) {
+    if (running) return;
+    running = fork();
+    if (!running) execl("/usr/sbin/pppd","pppd","-detach",0);
+    else signal(SIGCHLD, sigchld);
+  } else {
+    if (!running) return;
+    kill(running, SIGINT);
+    running = 0;
+  }
+}
+
+int main(int argc, char ** argv) {
+   Fl_Window window(100,50);
+   Fl_Toggle_Button button(0,0,100,50,"Connect");
+   Button = &button;
+   button.color(1,2);
+   button.callback(cb,0);
+   window.show(argc,argv);
+   return Fl::run();
+}
diff --git a/test/cube.cxx b/test/cube.cxx
new file mode 100644
index 000000000..ec8ed9892
--- /dev/null
+++ b/test/cube.cxx
@@ -0,0 +1,147 @@
+/*	demo08 rewritten to not use Forms compatability		*/
+
+// Modified to have 2 cubes to test multiple OpenGL contexts
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if !HAVE_GL
+class cube_box : public Fl_Box {
+public:	
+  double lasttime;
+  int wire;
+  double size;
+  double speed;
+  cube_box(int x,int y,int w,int h,const char *l=0)
+    :Fl_Box(FL_DOWN_BOX,x,y,w,h,l){
+      label("This demo does\nnot work without GL");
+  }
+};
+#else
+#include 
+#include 
+
+class cube_box : public Fl_Gl_Window {
+  void draw();
+public:
+  double lasttime;
+  int wire;
+  double size;
+  double speed;
+  cube_box(int x,int y,int w,int h,const char *l=0)
+    : Fl_Gl_Window(x,y,w,h,l) {lasttime = 0.0;}
+};
+
+/* The cube definition */
+float v0[3] = {0.0, 0.0, 0.0};
+float v1[3] = {1.0, 0.0, 0.0};
+float v2[3] = {1.0, 1.0, 0.0};
+float v3[3] = {0.0, 1.0, 0.0};
+float v4[3] = {0.0, 0.0, 1.0};
+float v5[3] = {1.0, 0.0, 1.0};
+float v6[3] = {1.0, 1.0, 1.0};
+float v7[3] = {0.0, 1.0, 1.0};
+
+#define v3f(x) glVertex3fv(x)
+
+void drawcube(int wire) {
+/* Draw a colored cube */
+  glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
+  glColor3ub(0,0,255);
+  v3f(v0); v3f(v1); v3f(v2); v3f(v3);
+  glEnd();
+  glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
+  glColor3ub(0,255,255); v3f(v4); v3f(v5); v3f(v6); v3f(v7);
+  glEnd();
+  glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
+  glColor3ub(255,0,255); v3f(v0); v3f(v1); v3f(v5); v3f(v4);
+  glEnd();
+  glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
+  glColor3ub(255,255,0); v3f(v2); v3f(v3); v3f(v7); v3f(v6);
+  glEnd();
+  glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
+  glColor3ub(0,255,0); v3f(v0); v3f(v4); v3f(v7); v3f(v3);
+  glEnd();
+  glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
+  glColor3ub(255,0,0); v3f(v1); v3f(v2); v3f(v6); v3f(v5);
+  glEnd();
+}
+
+void cube_box::draw() {
+  lasttime = lasttime+speed;
+  if (!valid()) {
+    glLoadIdentity();
+    glViewport(0,0,w(),h());
+    glEnable(GL_DEPTH_TEST);
+    glFrustum(-1,1,-1,1,2,10000);
+    glTranslatef(0,0,-10);
+  }
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  glPushMatrix();
+  glRotatef(float(lasttime*1.6),0,0,1);
+  glRotatef(float(lasttime*4.2),1,0,0);
+  glRotatef(float(lasttime*2.3),0,1,0);
+  glTranslatef(-1.0, 1.2f, -1.5);
+  glScalef(float(size),float(size),float(size));
+  drawcube(wire);
+  glPopMatrix();
+}
+
+#endif
+
+Fl_Window *form;
+Fl_Slider *speed, *size;
+Fl_Button *button, *wire, *flat;
+cube_box *cube, *cube2;
+
+void makeform(const char *name) {
+  form = new Fl_Window(510+390,390,name);
+  new Fl_Box(FL_DOWN_FRAME,20,20,350,350,"");
+  new Fl_Box(FL_DOWN_FRAME,510,20,350,350,"");
+  speed = new Fl_Slider(FL_VERT_SLIDER,390,90,40,220,"Speed");
+  size = new Fl_Slider(FL_VERT_SLIDER,450,90,40,220,"Size");
+  wire = new Fl_Radio_Light_Button(390,20,100,30,"Wire");
+  flat = new Fl_Radio_Light_Button(390,50,100,30,"Flat");
+  button = new Fl_Button(390,340,100,30,"Exit");
+  cube = new cube_box(23,23,344,344, 0);
+  cube2 = new cube_box(513,23,344,344, 0);
+  Fl_Box *b = new Fl_Box(FL_NO_BOX,cube->x(),size->y(),
+			 cube->w(),size->h(),0);
+  form->resizable(b);
+  b->hide();
+  form->end();
+}
+
+main(int argc, char **argv) {
+  makeform(argv[0]);
+  speed->bounds(4,0);
+  speed->value(cube->speed = cube2->speed = 1.0);
+  size->bounds(4,0.01);
+  size->value(cube->size = cube2->size = 1.0);
+  flat->value(1); cube->wire = 0; cube2->wire = 1;
+  form->label("cube");
+  form->show(argc,argv);
+  cube->show();
+  cube2->show();
+  for (;;) {
+    if (form->visible() && speed->value())
+      {if (!Fl::check()) break;}	// returns immediately
+    else
+      {if (!Fl::wait()) break;}	// waits until something happens
+    cube->wire = wire->value();
+    cube2->wire = !wire->value();
+    cube->size = cube2->size = size->value();
+    cube->speed = cube2->speed = speed->value();
+    cube->redraw();
+    cube2->redraw();
+    if (Fl::readqueue() == button) break;
+  }
+  return 0;
+}
+
diff --git a/test/cursor.cxx b/test/cursor.cxx
new file mode 100644
index 000000000..7eebe9da8
--- /dev/null
+++ b/test/cursor.cxx
@@ -0,0 +1,138 @@
+// cursor.C
+
+// Test the cursor setting code
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+Fl_Color fg = FL_BLACK;
+Fl_Color bg = FL_WHITE;
+Fl_Cursor cursor = FL_CURSOR_DEFAULT;
+
+Fl_Hor_Value_Slider *cursor_slider;
+
+void choice_cb(Fl_Widget *, void *v) {
+  cursor = (Fl_Cursor)(int)v;
+  cursor_slider->value(cursor);
+  fl_cursor(cursor,fg,bg);
+}
+
+Fl_Menu_Item choices[] = {
+  {"FL_CURSOR_DEFAULT",0,choice_cb,(void*)FL_CURSOR_DEFAULT},
+  {"FL_CURSOR_ARROW",0,choice_cb,(void*)FL_CURSOR_ARROW},
+  {"FL_CURSOR_CROSS",0,choice_cb,(void*)FL_CURSOR_CROSS},
+  {"FL_CURSOR_WAIT",0,choice_cb,(void*)FL_CURSOR_WAIT},
+  {"FL_CURSOR_INSERT",0,choice_cb,(void*)FL_CURSOR_INSERT},
+  {"FL_CURSOR_HAND",0,choice_cb,(void*)FL_CURSOR_HAND},
+  {"FL_CURSOR_HELP",0,choice_cb,(void*)FL_CURSOR_HELP},
+  {"FL_CURSOR_MOVE",0,choice_cb,(void*)FL_CURSOR_MOVE},
+  {"FL_CURSOR_NS",0,choice_cb,(void*)FL_CURSOR_NS},
+  {"FL_CURSOR_WE",0,choice_cb,(void*)FL_CURSOR_WE},
+  {"FL_CURSOR_NWSE",0,choice_cb,(void*)FL_CURSOR_NWSE},
+  {"FL_CURSOR_NESW",0,choice_cb,(void*)FL_CURSOR_NESW},
+  {"FL_CURSOR_NONE",0,choice_cb,(void*)FL_CURSOR_NONE},
+#if 0
+  {"FL_CURSOR_N",0,choice_cb,(void*)FL_CURSOR_N},
+  {"FL_CURSOR_NE",0,choice_cb,(void*)FL_CURSOR_NE},
+  {"FL_CURSOR_E",0,choice_cb,(void*)FL_CURSOR_E},
+  {"FL_CURSOR_SE",0,choice_cb,(void*)FL_CURSOR_SE},
+  {"FL_CURSOR_S",0,choice_cb,(void*)FL_CURSOR_S},
+  {"FL_CURSOR_SW",0,choice_cb,(void*)FL_CURSOR_SW},
+  {"FL_CURSOR_W",0,choice_cb,(void*)FL_CURSOR_W},
+  {"FL_CURSOR_NW",0,choice_cb,(void*)FL_CURSOR_NW},
+#endif
+  {0}
+};
+
+void setcursor(Fl_Widget *o, void *) {
+  Fl_Hor_Value_Slider *slider = (Fl_Hor_Value_Slider *)o;
+  cursor = Fl_Cursor((int)slider->value());
+  fl_cursor(cursor,fg,bg);
+}
+
+void setfg(Fl_Widget *o, void *) {
+  Fl_Hor_Value_Slider *slider = (Fl_Hor_Value_Slider *)o;
+  fg = Fl_Color((int)slider->value());
+  fl_cursor(cursor,fg,bg);
+}
+
+void setbg(Fl_Widget *o, void *) {
+  Fl_Hor_Value_Slider *slider = (Fl_Hor_Value_Slider *)o;
+  bg = Fl_Color((int)slider->value());
+  fl_cursor(cursor,fg,bg);
+}
+
+// draw the label without any ^C or \nnn conversions:
+class CharBox : public Fl_Box {
+  void draw() {
+    fl_font(FL_FREE_FONT,14);
+    fl_draw(label(), x()+w()/2, y()+h()/2);
+  }
+public:
+  CharBox(int X, int Y, int W, int H, const char* L) : Fl_Box(X,Y,W,H,L) {}
+};
+
+int main(int argc, char **argv) {
+  Fl_Window window(400,300);
+
+  Fl_Choice choice(80,100,200,25,"Cursor:");
+  choice.menu(choices);
+  choice.callback(choice_cb);
+  choice.when(FL_WHEN_RELEASE|FL_WHEN_NOT_CHANGED);
+
+  Fl_Hor_Value_Slider slider1(80,180,310,30,"Cursor:");
+  cursor_slider = &slider1;
+  slider1.align(FL_ALIGN_LEFT);
+  slider1.step(1);
+  slider1.precision(0);
+  slider1.bounds(0,100);
+  slider1.value(0);
+  slider1.callback(setcursor);
+  slider1.value(cursor);
+
+  Fl_Hor_Value_Slider slider2(80,220,310,30,"fgcolor:");
+  slider2.align(FL_ALIGN_LEFT);
+  slider2.step(1);
+  slider2.precision(0);
+  slider2.bounds(0,255);
+  slider2.value(0);
+  slider2.callback(setfg);
+  slider2.value(fg);
+
+  Fl_Hor_Value_Slider slider3(80,260,310,30,"bgcolor:");
+  slider3.align(FL_ALIGN_LEFT);
+  slider3.step(1);
+  slider3.precision(0);
+  slider3.bounds(0,255);
+  slider3.value(0);
+  slider3.callback(setbg);
+  slider3.value(bg);
+
+#if 0
+  // draw the manual's diagram of cursors...
+  window.size(400,800);
+  int y = 300;
+  Fl::set_font(FL_FREE_FONT, "cursor");
+  char buf[100]; char *p = buf;
+  for (Fl_Menu* m = choices; m->label(); m++) {
+    Fl_Box* b = new Fl_Box(35,y,150,25,m->label());
+    b->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
+    int n = (int)(m->argument());
+    if (n == FL_CURSOR_NONE) break;
+    if (n == FL_CURSOR_DEFAULT) n = FL_CURSOR_ARROW;
+    p[0] = (char)((n-1)*2);
+    p[1] = 0;
+    b = new CharBox(15,y,20,20,p); p+=2;
+    y += 25;
+  }
+#endif
+
+  window.resizable(window);
+  window.end();
+  window.show(argc,argv);
+  return Fl::run();
+}
diff --git a/test/curve.cxx b/test/curve.cxx
new file mode 100644
index 000000000..15d25217c
--- /dev/null
+++ b/test/curve.cxx
@@ -0,0 +1,88 @@
+// Test fl_curve
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+double args[9] = {
+  20,20, 50,200, 100,20, 200,200, 0};
+const char* name[9] = {
+  "X0", "Y0", "X1", "Y1", "X2", "Y2", "X3", "Y3", "rotate"};
+
+int points;
+
+class Drawing : public Fl_Widget {
+  void draw() {
+    fl_clip(x(),y(),w(),h());
+    fl_color(FL_DARK3);
+    fl_rectf(x(),y(),w(),h());
+    fl_push_matrix();
+    if (args[8]) {
+      fl_translate(x()+w()/2.0, y()+h()/2.0);
+      fl_rotate(args[8]);
+      fl_translate(-(x()+w()/2.0), -(y()+h()/2.0));
+    }
+    fl_translate(x(),y());
+    if (!points) {
+    fl_color(FL_WHITE);
+    fl_begin_complex_polygon();
+   fl_curve(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
+    fl_end_complex_polygon();
+    }
+    fl_color(FL_BLACK);
+    fl_begin_line();
+    fl_vertex(args[0],args[1]);
+    fl_vertex(args[2],args[3]);
+    fl_vertex(args[4],args[5]);
+    fl_vertex(args[6],args[7]);
+    fl_end_line();
+    fl_color(points ? FL_WHITE : FL_RED);
+    points ? fl_begin_points() : fl_begin_line();
+   fl_curve(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
+    points ? fl_end_points() : fl_end_line();
+    fl_pop_matrix();
+    fl_pop_clip();
+  }
+public:
+  Drawing(int X,int Y,int W,int H) : Fl_Widget(X,Y,W,H) {}
+};
+
+Drawing *d;
+
+void points_cb(Fl_Widget* o, void*) {
+  points = ((Fl_Toggle_Button*)o)->value();
+  d->redraw();
+}
+
+void slider_cb(Fl_Widget* o, void* v) {
+  Fl_Slider* s = (Fl_Slider*)o;
+  args[long(v)] = s->value();
+  d->redraw();
+}
+
+int main(int argc, char** argv) {
+  Fl_Double_Window window(300,555);
+  Drawing drawing(10,10,280,280);
+  d = &drawing;
+
+  int y = 300;
+  for (int n = 0; n<9; n++) {
+    Fl_Slider* s = new Fl_Hor_Value_Slider(50,y,240,25,name[n]); y += 25;
+    s->minimum(0); s->maximum(280);
+    if (n == 8) s->maximum(360);
+    s->step(1);
+    s->value(args[n]);
+    s->align(FL_ALIGN_LEFT);
+    s->callback(slider_cb, (void*)n);
+  }
+  Fl_Toggle_Button but(50,y,50,25,"points");
+  but.callback(points_cb);
+
+  window.end();
+  window.show(argc,argv);
+  return Fl::run();
+}
+
+
diff --git a/test/demo.cxx b/test/demo.cxx
new file mode 100644
index 000000000..75b5dc821
--- /dev/null
+++ b/test/demo.cxx
@@ -0,0 +1,255 @@
+/*	demo.C
+
+	The Forms demo program, rewritten in fltk.
+	The original code compiled fine, but this version does not use
+	
+
+*/
+
+#include 
+#include 
+#include 
+#if defined(WIN32) && !defined(CYGNUS)
+# include 
+//# define chdir _chdir
+#else
+# include 
+#endif
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* The form description */
+
+void doexit(Fl_Widget *, void *);
+void doback(Fl_Widget *, void *);
+void dobut(Fl_Widget *, long);
+
+Fl_Window *form;
+Fl_Button *but[9];
+
+void create_the_forms() {
+  Fl_Widget *obj;
+  form = new Fl_Window(370, 450);
+  obj = new Fl_Box(FL_FRAME_BOX,20,390,330,40,"Fltk Demonstration");
+  obj->color(FL_GRAY-4);
+  obj->labelsize(24);
+  obj->labelfont(FL_BOLD);
+  obj->labeltype(FL_ENGRAVED_LABEL);
+  obj = new Fl_Box(FL_FRAME_BOX,20,50,330,330,0);
+  obj->color(FL_GRAY-8);
+  obj = new Fl_Button(130,10,110,30,"Exit");
+  obj->callback(doexit);
+  obj = new Fl_Button(20,50,330,380); obj->type(FL_HIDDEN_BUTTON);
+  obj->callback(doback);
+  obj = but[0] = new Fl_Button(40,270,90,90);
+  obj = but[1] = new Fl_Button(140,270,90,90);
+  obj = but[2] = new Fl_Button(240,270,90,90);
+  obj = but[5] = new Fl_Button(240,170,90,90);
+  obj = but[4] = new Fl_Button(140,170,90,90);
+  obj = but[3] = new Fl_Button(40,170,90,90);
+  obj = but[6] = new Fl_Button(40,70,90,90);
+  obj = but[7] = new Fl_Button(140,70,90,90);
+  obj = but[8] = new Fl_Button(240,70,90,90);
+  for (int i=0; i<9; i++) {
+    but[i]->align(FL_ALIGN_WRAP);
+    but[i]->callback(dobut, i);
+  }
+  form->forms_end();
+}
+
+/* Maintaining and building up the menus. */
+
+typedef struct {
+  char name[64];
+  int numb;
+  char iname[9][64];
+  char icommand[9][64];
+} MENU;
+
+#define MAXMENU	32
+
+MENU menus[MAXMENU];
+int mennumb = 0;
+
+int find_menu(char nnn[])
+/* Returns the number of a given menu name. */
+{
+  int i;
+  for (i=0; ihide();
+  for (i=0; ishow();
+    but[bn]->label(menus[men].iname[i]);
+//     if (menus[men].icommand[i][0] == '@')
+//       but[bn]->color(FL_GRAY-8);
+//     else
+//       but[bn]->color(FL_GRAY);
+  }
+  strcpy(stack[stsize],nnn);
+  stsize++;
+}
+
+void pop_menu()
+/* Pops a menu */
+{
+  if (stsize<=1) return;
+  stsize -= 2;
+  push_menu(stack[stsize]);
+}
+
+/* The callback Routines */
+
+void dobut(Fl_Widget *, long arg)
+/* handles a button push */
+{
+  int men = find_menu(stack[stsize-1]);
+  int n = menus[men].numb;
+  int bn = but2numb( (int) arg, n-1);
+  if (menus[men].icommand[bn][0] == '@')
+    push_menu(menus[men].icommand[bn]);
+  else
+    system(menus[men].icommand[bn]);
+}
+
+void doback(Fl_Widget *, void *) {pop_menu();}
+
+void doexit(Fl_Widget *, void *) {exit(0);}
+
+int load_the_menu(const char fname[])
+/* Loads the menu file. Returns whether successful. */
+{
+  FILE *fin;
+  char line[256], mname[64],iname[64],cname[64];
+  int i,j;
+  fin = fopen(fname,"r");
+  if (fin == NULL)
+  {
+//    fl_show_message("ERROR","","Cannot read the menu description file.");
+    return 0;
+  }
+  for (;;) {
+    if (fgets(line,256,fin) == NULL) break;
+    j = 0; i = 0;
+    while (line[i] == ' ' || line[i] == '\t') i++;
+    if (line[i] == '\n') continue;
+    if (line[i] == '#') continue;
+    while (line[i] != ':' && line[i] != '\n') mname[j++] = line[i++];
+    mname[j] = '\0';
+    if (line[i] == ':') i++;
+    j = 0; 
+    while (line[i] != ':' && line[i] != '\n')
+    {
+      if (line[i] == '\\') {
+	i++;
+	if (line[i] == 'n') iname[j++] = '\n';
+	else iname[j++] = line[i];
+	i++;
+      } else
+        iname[j++] = line[i++];
+    }
+    iname[j] = '\0';
+    if (line[i] == ':') i++;
+    j = 0;
+    while (line[i] != ':' && line[i] != '\n') cname[j++] = line[i++];
+    cname[j] = '\0';
+    addto_menu(mname,iname,cname);
+  }
+  fclose(fin);
+  return 1;
+}
+
+int main(int argc, char **argv) {
+  create_the_forms();
+  char buf[256];
+  strcpy(buf, argv[0]);
+  strcat(buf, ".menu");
+  const char *fname = buf;
+  int i = 0;
+  if (!Fl::args(argc,argv,i) || i < argc-1)
+    Fl::fatal("Usage: %s  \n%s",Fl::help);
+  if (i < argc) fname = argv[i];
+  if (!load_the_menu(fname)) Fl::fatal("Can't open %s",fname);
+  strcpy(buf,fname);
+  const char *c = filename_name(buf);
+  if (c > buf) {buf[c-buf] = 0; chdir(buf);}
+  push_menu("@main");
+  form->show(argc,argv);
+  Fl::run();
+  return 0;
+}
diff --git a/test/demo.menu b/test/demo.menu
new file mode 100644
index 000000000..3d4c74b5e
--- /dev/null
+++ b/test/demo.menu
@@ -0,0 +1,80 @@
+# Menu description file for the generic demo program
+#
+# Each line consists of three fields, separated by :
+#
+# - menu name	: To which the item belongs (starts with @)
+# - item name	: Placed on button. (use \n for newline)
+# - command name: To be executed. Use a menu name to define a submenu.
+#
+# @main indicates the main menu.
+#
+
+@main:Widget\nTests:@x
+	@x:Fl_Browser:./browser&
+	@x:Fl_Input:./input&
+	@x:Fl_Output:./output&
+	@x:Fl_Button:./radio&
+	@x:Fl_Tabs:./tabs&
+	@x:Fl_Tile:./tile&
+	@x:Fl_Scroll:./scroll&
+	@x:Fl_Pack:./pack&
+	@x:Fl_Menu:./menubar&
+
+@main:Window\nTests:@w
+	@w:overlay:./overlay&
+	@w:subwindow:./subwindow&
+	@w:double\nbuffer:./doublebuffer&
+	@w:GL window:./cube&
+	@w:GL overlay:./gl_overlay&
+	@w:iconize:./iconize&
+	@w:fullscreen:./fullscreen&
+	@w:resizable:./resizebox&
+	@w:resize:./resize&
+
+@main:Drawing\nTests:@d
+	@d:Fl_Bitmap:./bitmap&
+	@d:Fl_Pixmap:./pixmap&
+	@d:Fl_Image:./image&
+	@d:pixmap\nbrowser:./pixmap_browser&
+	@d:cursor:./cursor&
+	@d:labels:./label&
+	@d:fl_arc:./arc&
+	@d:fl_curve:./curve&
+	@d:fonts:./fonts&
+
+@main:Events:@u
+	@u:navigation:./navigation&
+	@u:minimum update:./minimum&
+	@u:keyboard:./keyboard&
+	@u:fast & slow widgets:./fast_slow&
+	@u:inactive:./inactive&
+
+@main:Fluid\n(UI design tool):../fluid/fluid valuators.fl&
+
+@main:Cool\nDemos:@e
+	@e:X Color\nBrowser:./colbrowser&
+	@e:Mandelbrot:./mandelbrot&
+	@e:Fractals:./fractals&
+	@e:Puzzle:./glpuzzle&
+	@e:shiny\nOpenGL\nbuttons:./shiny&
+	@e:Checkers:./checkers&
+
+@main:Other\nTests:@o
+	@o:color choosers:./color_chooser r&
+	@o:file chooser:./file_chooser&
+	@o:styles:./style&
+	@o:XForms Emulation:./forms&
+
+@main:Tutorial\nfrom\nManual:@j
+	@j:hello:./hello&
+	@j:button:./button&
+	@j:ask\n(modified):./ask&
+	@j:shape:./shape&
+
+@main:Images\nfor\nManual:@i
+	@i:valuators:./valuators&
+	@i:symbols:./symbols&
+	@i:buttons:./buttons&
+	@i:clock:./clock&
+	@i:popups:./message&
+	@i:boxtypes:./boxtype&
diff --git a/test/doublebuffer.cxx b/test/doublebuffer.cxx
new file mode 100644
index 000000000..b15bc02c3
--- /dev/null
+++ b/test/doublebuffer.cxx
@@ -0,0 +1,99 @@
+// Double-buffering test.
+
+// This demo shows how double buffering helps, by drawing the
+// window in a particularily bad way.
+
+// The single-buffered window will blink as it updates.  The
+// double buffered one will not.  It will take just as long
+// (or longer) to update, but often it will appear to be faster.
+
+// This demo should work for both the GL and X versions of Fl,
+// even though the double buffering mechanism is totally different.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+// this purposely draws each line 10 times to be slow:
+void star(int w, int h, int n) {
+  fl_push_matrix();
+  fl_translate(w/2, h/2);
+  fl_scale(w/2, h/2);
+  for (int i = 0; i < n; i++) {
+    for (int j = i+1; j < n; j++)/* for (int k=0; k<10; k++)*/ {
+      fl_begin_line();
+      fl_vertex(cos(2*M_PI*i/n+.1), sin(2*M_PI*i/n+.1));
+      fl_vertex(cos(2*M_PI*j/n+.1), sin(2*M_PI*j/n+.1));
+      fl_end_line();
+    }
+  }
+  fl_pop_matrix();
+}
+
+int sides[2] = {20,20};
+
+void slider_cb(Fl_Widget* o, long v) {
+  sides[v] = int(((Fl_Slider*)o)->value());
+  o->parent()->redraw();
+}
+
+void bad_draw(int w,int h,int which) {
+//   for (int i=0; i<10; i++) {
+//     fl_color(7); fl_rectf(0,0,w,h); fl_color(0); star(w,h);
+//     fl_color(0); fl_rectf(0,0,w,h); fl_color(7); star(w,h);
+//   }
+  fl_color(FL_BLACK); fl_rectf(0,0,w,h);
+  fl_color(FL_WHITE); star(w,h,sides[which]);
+  //  for (int x=0; xvalue(o->value());
+if (!Fl::pushed()) slow->value(o->value());
+}
+
+Fl_Slider *fast;
+
+Fl_Slider *slow;
+
+int main(int argc, char **argv) {
+  Fl_Window *w;
+  { Fl_Window* o = new Fl_Window(318, 443);
+    w = o;
+    Fl_Group::current()->resizable(o);
+    { Fl_Slider* o = new Fl_Slider(90, 200, 30, 200, "move\nthis");
+      control = o;
+      o->callback((Fl_Callback*)cb_control);
+      o->when(FL_WHEN_CHANGED|FL_WHEN_RELEASE|FL_WHEN_NOT_CHANGED);
+    }
+    { Fl_Slider* o = new Fl_Slider(140, 200, 30, 200, "fast\nredraw");
+      fast = o;
+      o->set_output();
+    }
+    { Fl_Slider* o = new Fl_Slider(190, 200, 30, 200, "slow\nredraw");
+      slow = o;
+      o->set_output();
+    }
+    { Fl_Box* o = new Fl_Box(10, 10, 300, 180, "The left slider has changed( FL_WHEN_CHANGED | FL_WHEN_RELEASE | FL_WHEN_N\
+OT_CHANGED) so it produces a callback on both drag and release mouse events\
+.\nThe middle slider (representing a widget with low overhead) is changed o\
+n every mouse movement.\nThe right slider (representing a widget with high \
+overhead) is only updated when the mouse is released, by checking if Fl::pu\
+shed() is zero.");
+      o->box(FL_DOWN_BOX);
+      o->color(53);
+      o->labelfont(4);
+      o->labelsize(12);
+      o->align(148);
+    }
+    w->end();
+  }
+  w->show(argc, argv);
+  return Fl::run();
+}
diff --git a/test/fast_slow.H b/test/fast_slow.H
new file mode 100644
index 000000000..233a9e649
--- /dev/null
+++ b/test/fast_slow.H
@@ -0,0 +1,9 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include 
+#include 
+#include 
+#include 
+extern Fl_Slider *control;
+extern Fl_Slider *fast;
+extern Fl_Slider *slow;
diff --git a/test/fast_slow.fl b/test/fast_slow.fl
new file mode 100644
index 000000000..71ee657d1
--- /dev/null
+++ b/test/fast_slow.fl
@@ -0,0 +1,36 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 0.99 
+gridx 10 
+gridy 10 
+snap 3
+Function {} {open
+} {
+  Fl_Window {} {open
+    xywh {143 188 318 443} resizable visible
+  } {
+    Fl_Slider control {
+      label {move
+this}
+      callback {fast->value(o->value());
+if (!Fl::pushed()) slow->value(o->value());}
+      xywh {90 200 30 200}
+      code0 {o->when(FL_WHEN_CHANGED|FL_WHEN_RELEASE|FL_WHEN_NOT_CHANGED);}
+    }
+    Fl_Slider fast {
+      label {fast
+redraw}
+      xywh {140 200 30 200} deactivate
+    }
+    Fl_Slider slow {
+      label {slow
+redraw}
+      xywh {190 200 30 200} deactivate
+    }
+    Fl_Box {} {
+      label {The left slider has changed( FL_WHEN_CHANGED | FL_WHEN_RELEASE | FL_WHEN_NOT_CHANGED) so it produces a callback on both drag and release mouse events.
+The middle slider (representing a widget with low overhead) is changed on every mouse movement.
+The right slider (representing a widget with high overhead) is only updated when the mouse is released, by checking if Fl::pushed() is zero.} selected
+      xywh {10 10 300 180} box DOWN_BOX color {53 47} labelfont 4 labelsize 12 align 148
+    }
+  }
+} 
diff --git a/test/file_chooser.cxx b/test/file_chooser.cxx
new file mode 100644
index 000000000..e2b366ce2
--- /dev/null
+++ b/test/file_chooser.cxx
@@ -0,0 +1,36 @@
+/*	Test fl_file_chooser()	*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+Fl_Input *pattern, *current;
+
+void pickfile(Fl_Widget *) {
+  const char *p;
+  p = fl_file_chooser("Pick a file",pattern->value(),current->value());
+  if (p) current->value(p);
+}
+
+void thecb(const char *name) {
+  printf("Callback '%s'\n",name);
+}
+
+int main(int argc, char **argv) {
+  Fl_Window window(400,200);
+  pattern = new Fl_Input(100,50,280,30,"Pattern:");
+  pattern->static_value("*");
+  current = new Fl_Input(100,90,280,30,"Current:");
+  Fl_Button button(100,120,100,30,"&Choose file");
+  button.callback(pickfile);
+  window.end();
+  window.show(argc, argv);
+  fl_file_chooser_callback(thecb);
+  return Fl::run();
+}
diff --git a/test/fl_jpeg_image.cxx b/test/fl_jpeg_image.cxx
new file mode 100644
index 000000000..960c0515c
--- /dev/null
+++ b/test/fl_jpeg_image.cxx
@@ -0,0 +1,178 @@
+/* 	Test fl_draw_image.
+
+	Be sure to try every visual with the -v switch and try
+	-m (monochrome) on each of them.
+
+	This program requires either the libjpeg.a library or
+	an internal DD library to read images (this is chosen
+	by the presence of the "DD" #define).
+
+	To get the jpeg library:
+
+The "official" archive site for this software is ftp.uu.net (Internet
+address 192.48.96.9).  The most recent released version can always be found
+there in directory graphics/jpeg.  This particular version will be archived
+as graphics/jpeg/jpegsrc.v6a.tar.gz.
+
+	The makefile assummes you decompressed and build these
+	in a directory called "jpeg-6a" in the same location as the
+	"FL" directory.
+
+*/
+
+#include 
+#include 
+#include 
+#include 
+
+void readtheimage(const char *name); // below
+int width;
+int height;
+int depth;
+int linedelta;
+uchar *ibuffer;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+int mono;
+
+class image_window : public Fl_Window {
+  void draw();
+public:
+  image_window(int w,int h) : Fl_Window(w,h) {box(FL_NO_BOX);}
+};
+
+void image_window::draw() {
+  if (mono)
+    fl_draw_image_mono(ibuffer+1,0,0,width,height,depth,linedelta);
+  else
+    fl_draw_image(ibuffer,0,0,width,height,depth,linedelta);
+}
+
+////////////////////////////////////////////////////////////////
+
+#include 
+#include "list_visuals.C"
+
+////////////////////////////////////////////////////////////////
+
+int visid = -1;
+int arg(int argc, char **argv, int &i) {
+  if (argv[i][1] == 'm') {mono = 1; i++; return 1;}
+
+  if (argv[i][1] == 'v') {
+    if (i+1 >= argc) return 0;
+    visid = atoi(argv[i+1]);
+    i += 2;
+    return 2;
+  }
+
+  return 0;
+}
+
+int main(int argc, char ** argv) {
+
+  int i = 1;
+  if (!Fl::args(argc,argv,i,arg) || i != argc-1) {
+    fprintf(stderr,"usage: %s  image_file\n"
+" -v # : use visual\n"
+" -m : monochrome\n"
+"%s\n",
+	    argv[0],Fl::help);
+    exit(1);
+  }
+
+  readtheimage(argv[i]);
+  image_window *window = new image_window(width,height);
+
+  if (visid>=0) {
+    fl_open_display();
+    XVisualInfo templt; int num;
+    templt.visualid = visid;
+    fl_visual = XGetVisualInfo(fl_display, VisualIDMask, &templt, &num);
+    if (!fl_visual) {
+      fprintf(stderr, "No visual with id %d, use one of:\n",visid);
+      list_visuals();
+      exit(1);
+    }
+    fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen),
+				fl_visual->visual, AllocNone);
+    fl_xpixel(0); // make sure black is allocated
+  }
+
+  window->show(argc,argv);
+  return Fl::run();
+}
+
+////////////////////////////////////////////////////////////////
+#ifndef DD_LIBRARY
+// Read using jpeg library:
+
+extern "C" {
+#include "jpeglib.h"
+}
+
+void readtheimage(const char *name) {
+  struct jpeg_decompress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  FILE * infile = fopen(name, "rb");
+  if (!infile) {
+    fprintf(stderr, "can't open %s\n", name);
+    exit(1);
+  }
+  cinfo.err = jpeg_std_error(&jerr);
+  jpeg_create_decompress(&cinfo);
+  jpeg_stdio_src(&cinfo, infile);
+  jpeg_read_header(&cinfo, TRUE);
+  jpeg_start_decompress(&cinfo);
+  width = cinfo.output_width;
+  height = cinfo.output_height;
+  depth = cinfo.output_components;
+  ibuffer = new uchar[width*height*depth];
+  uchar *rp = ibuffer;
+  for (int i=0; i= ibuffer; p-=4) {
+    uchar r = p[3];
+    uchar g = p[2];
+    uchar b = p[1];
+    uchar a = p[0];
+    p[0] = r;
+    p[1] = g;
+    p[2] = b;
+    p[3] = a;
+  }
+  // make it bottom-to-top:
+  ibuffer = ibuffer + width*(height-1)*depth;
+  linedelta = -(width*depth);
+}
+#endif
+
diff --git a/test/fonts.cxx b/test/fonts.cxx
new file mode 100644
index 000000000..0b3639ae2
--- /dev/null
+++ b/test/fonts.cxx
@@ -0,0 +1,127 @@
+/* demo of Fl::set_fonts() */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+Fl_Window *form;
+
+Fl_Box *textobj;
+
+Fl_Hold_Browser *fontobj, *sizeobj;
+
+int *sizes[1000];
+int numsizes[1000];
+int pickedsize = 14;
+
+void font_cb(Fl_Widget *, long) {
+  int fn = fontobj->value();
+  if (!fn) return;
+  fn--;
+  textobj->labelfont(fn);
+  sizeobj->clear();
+  int n = numsizes[fn];
+  int *s = sizes[fn];
+  if (!n) {
+    // no sizes
+  } else if (s[0] == 0) {
+    // many sizes;
+    int j = 1;
+    for (int i = 1; i<64 || iadd(buf);
+    }
+    sizeobj->value(pickedsize);
+  } else {
+    // some sizes
+    int w = 0;
+    for (int i = 0; i < n; i++) {
+      if (s[i]<=pickedsize) w = i;
+      char buf[20];
+      sprintf(buf,"@b%d",s[i]);
+      sizeobj->add(buf);
+    }
+    sizeobj->value(w+1);
+  }
+  textobj->redraw();
+}
+
+void size_cb(Fl_Widget *, long) {
+  int i = sizeobj->value();
+  if (!i) return;
+  const char *c = sizeobj->text(i);
+  while (*c < '0' || *c > '9') c++;
+  pickedsize = atoi(c);
+  textobj->labelsize(pickedsize);
+  textobj->redraw();
+}
+
+char label[400];
+
+void create_the_forms() {
+  form = new Fl_Window(550,370);
+
+  strcpy(label, "Hello, world!\n");
+  int i = strlen(label);
+  uchar c;
+  for (c = ' '+1; c < 127; c++) {if (!(c&0x1f)) label[i++]='\n'; label[i++]=c;}
+  label[i++] = '\n';
+  for (c = 0xA1; c; c++) {if (!(c&0x1f)) label[i++]='\n'; label[i++]=c;}
+  label[i] = 0;
+
+  textobj = new Fl_Box(FL_FRAME_BOX,10,10,530,170,label);
+  textobj->align(FL_ALIGN_TOP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
+  textobj->color(9,47);
+  fontobj = new Fl_Hold_Browser(10, 190, 390, 170);
+  fontobj->box(FL_FRAME_BOX);
+  fontobj->color(53,3);
+  fontobj->callback(font_cb);
+  form->resizable(fontobj);
+  sizeobj = new Fl_Hold_Browser(410, 190, 130, 170);
+  sizeobj->box(FL_FRAME_BOX);
+  sizeobj->color(53,3);
+  sizeobj->callback(size_cb);
+  form->end();
+}
+
+#include 
+
+int main(int argc, char **argv) {
+  create_the_forms();
+  int i = fl_choice("Which fonts:","-*","iso8859","All");
+  int k = Fl::set_fonts(i ? (i>1 ? "*" : 0) : "-*");
+  for (i = 0; i < k; i++) {
+    int t; const char *name = Fl::get_font_name((Fl_Font)i,&t);
+    char buffer[128];
+#if 1
+    if (t) {
+      char *p = buffer;
+      if (t & FL_BOLD) {*p++ = '@'; *p++ = 'b';}
+      if (t & FL_ITALIC) {*p++ = '@'; *p++ = 'i';}
+      strcpy(p,name);
+      name = buffer;
+    }
+#else // this is neat, but really slow on some X servers:
+    sprintf(buffer, "@F%d@.%s", i, name);
+    name = buffer;
+#endif
+    fontobj->add(name);
+    int *s; int n = Fl::get_font_sizes((Fl_Font)i, s);
+    numsizes[i] = n;
+    if (n) {
+      sizes[i] = new int[n];
+      for (int j=0; jvalue(1);
+  font_cb(fontobj,0);
+  form->show(argc,argv);
+  return Fl::run();
+}
diff --git a/test/forms.cxx b/test/forms.cxx
new file mode 100644
index 000000000..1ca2c965d
--- /dev/null
+++ b/test/forms.cxx
@@ -0,0 +1,205 @@
+// This is an XForms program with very few changes.
+// Search for "fltk" to find all changes necessary to port to fltk.
+
+/* This demo show the different boxtypes. Note that some
+ * boxtypes are not appropriate for some objects
+ */
+
+#include  // changed for fltk
+
+static int border = 1; // changed from FL_TRANSIENT for fltk
+// (this is so the close box and Esc work to close the window)
+
+typedef struct { int val; char *name; } VN_struct;
+#define VN(a) {a,#a}
+
+// static VN_struct gmode[] =
+// {
+//   VN(StaticGray), VN(GrayScale), VN(StaticColor),
+//   VN(PseudoColor), VN(TrueColor), VN(DirectColor),
+// };
+
+static VN_struct btypes[]=
+{
+   {FL_NO_BOX,"no box"},
+   {FL_UP_BOX, "up box"},
+   {FL_DOWN_BOX,"down box"},
+   {FL_BORDER_BOX,"border box"},
+   {FL_SHADOW_BOX,"shadow box"},
+   {FL_FLAT_BOX,"flat box"},
+   {FL_FRAME_BOX,"frame box"},
+   {FL_EMBOSSED_BOX,"embossed box"},
+   {FL_ROUNDED_BOX,"rounded box"},
+   {FL_RFLAT_BOX,"rflat box"},
+   {FL_RSHADOW_BOX,"rshadow box"}, // renamed for fltk
+   {FL_OVAL_BOX,"oval box"},
+   {FL_ROUNDED3D_UPBOX,"rounded3d upbox"},
+   {FL_ROUNDED3D_DOWNBOX,"rounded3d downbox"},
+   {FL_OVAL3D_UPBOX,"oval3d upbox"},
+   {FL_OVAL3D_DOWNBOX,"oval3d downbox"},
+   /* sentinel */
+   {-1}
+};
+
+#include "srs.xbm"
+
+/*************** Callback **********************/
+
+FL_FORM *form;
+Fl_Widget *tobj[18], *exitob, *btypeob, *modeob;
+
+void 
+boxtype_cb (Fl_Widget * ob, long)
+{
+  int i, req_bt = fl_get_choice(ob) - 1;
+  static int lastbt = -1;
+
+  if(lastbt != req_bt)
+  {
+     fl_freeze_form (form);
+     fl_redraw_form (form);
+     for (i = 0; i < 18; i++)
+        fl_set_object_boxtype (tobj[i], (Fl_Boxtype)btypes[req_bt].val);
+     fl_unfreeze_form (form);
+     lastbt = req_bt;
+     fl_redraw_form(form); // added for fltk
+  }
+}
+
+void 
+mode_cb (Fl_Widget *, long)
+{
+//   static int lval = -1;
+//   int val = fl_get_choice (ob) -1;
+//   int  db = 0;
+
+//   if (val == lval || val < 0)
+//     return;
+
+//   fl_hide_form (form);
+//   if (!fl_mode_capable (gmode[val].val, 0))
+//   {
+//       fl_set_choice(ob, lval);
+//       val = lval;
+//   }
+
+//   fl_set_graphics_mode (gmode[val].val, db);
+//   fl_show_form (form, FL_PLACE_GEOMETRY, border, "Box types");
+
+//   lval = val;
+}
+
+/*************** Creation Routines *********************/
+
+void 
+create_form_form (void)
+{
+  Fl_Widget *obj;
+
+  form = fl_bgn_form(FL_NO_BOX, 720, 520);
+  obj = fl_add_box(FL_UP_BOX, 0, 0, 720, 520, "");
+  fl_set_object_color(obj, FL_BLUE, FL_COL1);
+  obj = fl_add_box(FL_DOWN_BOX, 10, 90, 700, 420, "");
+  fl_set_object_color(obj, FL_COL1, FL_COL1);
+  obj = fl_add_box(FL_DOWN_BOX, 10, 10, 700, 70, "");
+  fl_set_object_color(obj, FL_SLATEBLUE, FL_COL1);
+  tobj[0] = obj = fl_add_box(FL_UP_BOX, 30, 110, 110, 110, "Box");
+  tobj[1] = obj = fl_add_text(FL_NORMAL_TEXT, 30, 240, 110, 30, "Text");
+  tobj[2] = obj = fl_add_bitmap(FL_NORMAL_BITMAP, 40, 280, 90, 80, "Bitmap");
+  fl_set_object_lcol(obj, FL_BLUE);
+  tobj[3] = obj = fl_add_chart(FL_BAR_CHART, 160, 110, 160, 110, "Chart");
+  tobj[4] = obj = fl_add_clock(FL_ANALOG_CLOCK, 40, 390, 90, 90, "Clock");
+//fl_set_object_dblbuffer(tobj[4],1); // removed for fltk
+  tobj[5]=obj=fl_add_button(FL_NORMAL_BUTTON, 340, 110, 120, 30, "Button");
+  tobj[6]=obj=fl_add_lightbutton(FL_PUSH_BUTTON,340,150,120,30,"Lightbutton");
+  tobj[7]=obj=fl_add_roundbutton(FL_PUSH_BUTTON,340,190,120,30,"Roundbutton");
+  tobj[8]=obj=fl_add_slider(FL_VERT_SLIDER, 160, 250, 40, 230, "Slider");
+  tobj[9]=obj=fl_add_valslider(FL_VERT_SLIDER, 220, 250, 40, 230, "Valslider");
+  tobj[10]=obj=fl_add_dial (FL_LINE_DIAL, 280, 250, 100, 100, "Dial");
+  tobj[11]=obj=fl_add_positioner(FL_NORMAL_POSITIONER,280,380,150,100, "Positioner");
+  tobj[12]=obj=fl_add_counter (FL_NORMAL_COUNTER,480,110,210,30, "Counter");
+  tobj[13]=obj=fl_add_input (FL_NORMAL_INPUT, 520,170,170,30, "Input");
+  tobj[14]=obj=fl_add_menu (FL_PUSH_MENU, 400, 240, 100, 30, "Menu");
+  tobj[15]=obj=fl_add_choice (FL_NORMAL_CHOICE, 580, 250, 110, 30, "Choice");
+  tobj[16]=obj=fl_add_timer (FL_VALUE_TIMER, 580, 210, 110, 30, "Timer");
+//fl_set_object_dblbuffer(tobj[16], 1); // removed for fltk
+  tobj[17]=obj=fl_add_browser (FL_NORMAL_BROWSER,450,300,240, 180, "Browser");
+  exitob=obj= fl_add_button (FL_NORMAL_BUTTON, 590, 30, 100, 30, "Exit");
+  btypeob=obj= fl_add_choice (FL_NORMAL_CHOICE,110,30, 130, 30, "Boxtype");
+  fl_set_object_callback (obj, boxtype_cb, 0);
+  modeob = obj=fl_add_choice(FL_NORMAL_CHOICE,370,30,130,30,"Graphics mode");
+  fl_set_object_callback (obj, mode_cb, 0);
+  fl_end_form ();
+}
+/*---------------------------------------*/
+
+void 
+create_the_forms (void)
+{
+  create_form_form ();
+}
+
+/*************** Main Routine ***********************/
+
+char *browserlines[] = {
+   " ", "@C1@c@l@bObjects Demo",   " ",
+   "This demo shows you all",      "objects that currently",
+   "exist in the Forms Library.",  " ",
+   "You can change the boxtype",   "of the different objects",
+   "using the buttons at the",     "top of the form. Note that",
+   "some combinations might not",  "look too good. Also realize",
+   "that for all object classes",  "many different types are",
+   "available with different",     "behaviour.", " ",
+   "With this demo you can also",  "see the effect of the drawing",
+   "mode on the appearance of the","objects.",
+   0
+};
+
+
+int
+main (int argc, char *argv[])
+{
+  FL_COLOR c = FL_BLACK;
+  char **p;
+  VN_struct *vn;
+
+  fl_initialize(&argc, argv, "FormDemo", 0, 0);
+  create_the_forms ();
+  fl_set_bitmap_data (tobj[2], sorceress_width, sorceress_height, sorceress_bits);
+  fl_add_chart_value (tobj[3], 15, "item 1", c++);
+  fl_add_chart_value (tobj[3], 5, "item 2", c++);
+  fl_add_chart_value (tobj[3], -10, "item 3", c++);
+  fl_add_chart_value (tobj[3], 25, "item 4", c++);
+  fl_set_menu (tobj[14], "item 1|item 2|item 3|item 4|item 5");
+  fl_addto_choice (tobj[15], "item 1");
+  fl_addto_choice (tobj[15], "item 2");
+  fl_addto_choice (tobj[15], "item 3");
+  fl_addto_choice (tobj[15], "item 4");
+  fl_addto_choice (tobj[15], "item 5");
+  fl_set_timer (tobj[16], 1000.0);
+
+  for ( p = browserlines; *p; p++)
+     fl_add_browser_line (tobj[17], *p);
+
+  for ( vn = btypes; vn->val >= 0; vn++)
+    fl_addto_choice(btypeob, vn->name);
+
+//   {
+//     int i;
+//     VN_struct *g = gmode, *gs = g + sizeof (gmode) / sizeof (gmode[0]);
+//     for (i = 1; g < gs; g++, i++)
+//     {
+//       fl_addto_choice (modeob, g->name);
+//       if(!fl_mode_capable(g->val, 0))
+//         fl_set_choice_item_mode(modeob, i, FL_PUP_GRAY);
+//     }
+//   }
+//   fl_set_choice (modeob, fl_vmode+1);
+
+  fl_show_form (form, FL_PLACE_MOUSE, border, "Box types");
+
+  while (fl_do_forms () != exitob)
+     ;
+
+  return 0;
+}
diff --git a/test/fractals.cxx b/test/fractals.cxx
new file mode 100644
index 000000000..5eb783e51
--- /dev/null
+++ b/test/fractals.cxx
@@ -0,0 +1,779 @@
+/* Fractal drawing program
+   This is a GLUT demo program, with modifications to
+   demonstrate how to add fltk controls to a glut program.   The glut
+   code is unchanged except for the end (search for fltk to find changes).
+*/
+
+#include 
+#if !HAVE_GL
+#include 
+#include 
+int main(int, char**) {
+  fl_alert("This demo does not work without GL");
+  return 1;
+}
+#else
+/*
+ * To compile: cc -o fractals fractals.c -lGL -lGLU -lX11 -lglut -lXmu -lm
+ *
+ * Usage: fractals
+ *
+ * Homework 6, Part 2: fractal mountains and fractal trees 
+ * (Pretty Late)
+ *
+ * Draws fractal mountains and trees -- and an island of mountains in water 
+ * (I tried having trees on the island but it didn't work too well.)
+ *
+ * Two viewer modes: polar and flying (both restrained to y>0 for up vector).
+ * Keyboard 0->9 and +/- control speed when flying.
+ *
+ * Only keyboard commands are 0-9 and +/- for speed in flying mode.
+ *
+ * Fog would make the island look much better, but I couldn't get it to work
+ * correctly.  Would line up on -z axis not from eye.
+ *
+ * Philip Winston - 3/4/95
+ * pwinston@hmc.edu
+ * http://www.cs.hmc.edu/people/pwinston
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include            /* ULONG_MAX is defined here */
+#include             /* FLT_MAX is atleast defined here */
+
+#include   /* for random seed */
+
+#include "fracviewer.c" // changed from .h for fltk
+
+#if defined(WIN32) || defined(__EMX__)
+#define drand48() (((float) rand())/((float) RAND_MAX))
+#define srand48(x) (srand((x)))
+#endif
+
+typedef enum { NOTALLOWED, MOUNTAIN, TREE, ISLAND, BIGMTN, STEM, LEAF, 
+               MOUNTAIN_MAT, WATER_MAT, LEAF_MAT, TREE_MAT, STEMANDLEAVES,
+               AXES } DisplayLists;
+
+#define MAXLEVEL 8
+
+int Rebuild = 1,        /* Rebuild display list in next display? */
+    Fract   = TREE,     /* What fractal are we building */
+    Level   = 4;        /* levels of recursion for fractals */     
+
+int DrawAxes = 0;       
+
+/***************************************************************/
+/************************* VECTOR JUNK *************************/
+/***************************************************************/
+
+  /* print vertex to stderr */
+void printvert(float v[3])
+{
+  fprintf(stderr, "(%f, %f, %f)\n", v[0], v[1], v[2]);
+}
+
+#if 0	// removed for FL, it is in fracviewer.c
+  /* normalizes v */
+void normalize(GLfloat v[3])
+{
+  GLfloat d = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+
+  if (d == 0)
+    fprintf(stderr, "Zero length vector in normalize\n");
+  else
+    v[0] /= d; v[1] /= d; v[2] /= d;
+}
+
+  /* calculates a normalized crossproduct to v1, v2 */
+void ncrossprod(float v1[3], float v2[3], float cp[3])
+{
+  cp[0] = v1[1]*v2[2] - v1[2]*v2[1];
+  cp[1] = v1[2]*v2[0] - v1[0]*v2[2];
+  cp[2] = v1[0]*v2[1] - v1[1]*v2[0];
+  normalize(cp);
+}
+#endif
+
+  /* calculates normal to the triangle designated by v1, v2, v3 */
+void triagnormal(float v1[3], float v2[3], float v3[3], float norm[3])
+{
+  float vec1[3], vec2[3];
+
+  vec1[0] = v3[0] - v1[0];  vec2[0] = v2[0] - v1[0];
+  vec1[1] = v3[1] - v1[1];  vec2[1] = v2[1] - v1[1];
+  vec1[2] = v3[2] - v1[2];  vec2[2] = v2[2] - v1[2];
+
+  ncrossprod(vec2, vec1, norm);
+}
+
+float xzlength(float v1[3], float v2[3])
+{
+  return sqrt((v1[0] - v2[0])*(v1[0] - v2[0]) +
+              (v1[2] - v2[2])*(v1[2] - v2[2]));
+}
+
+float xzslope(float v1[3], float v2[3])
+{
+  return ((v1[0] != v2[0]) ? ((v1[2] - v2[2]) / (v1[0] - v2[0]))
+	                   : FLT_MAX);
+}
+
+
+/***************************************************************/
+/************************ MOUNTAIN STUFF ***********************/
+/***************************************************************/
+
+GLfloat DispFactor[MAXLEVEL];  /* Array of what to multiply random number
+				  by for a given level to get midpoint
+				  displacement  */
+GLfloat DispBias[MAXLEVEL];  /* Array of what to add to random number
+				before multiplying it by DispFactor */
+
+#define NUMRANDS 191
+float RandTable[NUMRANDS];  /* hash table of random numbers so we can
+			       raise the same midpoints by the same amount */ 
+
+         /* The following are for permitting an edge of a moutain to be   */
+         /* pegged so it won't be displaced up or down.  This makes it    */
+         /* easier to setup scenes and makes a single moutain look better */
+
+GLfloat Verts[3][3],    /* Vertices of outside edges of mountain */
+        Slopes[3];      /* Slopes between these outside edges */
+int     Pegged[3];      /* Is this edge pegged or not */           
+
+ /*
+  * Comes up with a new table of random numbers [0,1)
+  */
+void InitRandTable(unsigned int seed)
+{
+  int i;
+
+  srand48((long) seed);
+  for (i = 0; i < NUMRANDS; i++)
+    RandTable[i] = drand48() - 0.5;
+}
+
+  /* calculate midpoint and displace it if required */
+void Midpoint(GLfloat mid[3], GLfloat v1[3], GLfloat v2[3],
+	      int edge, int level)
+{
+  unsigned hash;
+
+  mid[0] = (v1[0] + v2[0]) / 2;
+  mid[1] = (v1[1] + v2[1]) / 2;
+  mid[2] = (v1[2] + v2[2]) / 2;
+  if (!Pegged[edge] || (fabs(xzslope(Verts[edge], mid) 
+                        - Slopes[edge]) > 0.00001)) {
+    srand48((int)((v1[0]+v2[0])*23344));
+    hash = unsigned(drand48() * 7334334);
+    srand48((int)((v2[2]+v1[2])*43433));
+    hash = (unsigned)(drand48() * 634344 + hash) % NUMRANDS;
+    mid[1] += ((RandTable[hash] + DispBias[level]) * DispFactor[level]);
+  }
+}
+
+  /*
+   * Recursive moutain drawing routine -- from lecture with addition of 
+   * allowing an edge to be pegged.  This function requires the above
+   * globals to be set, as well as the Level global for fractal level 
+   */
+static float cutoff = -1;
+
+void FMR(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int level)
+{
+  if (level == Level) {
+    GLfloat norm[3];
+    if (v1[1] <= cutoff && v2[1]<=cutoff && v3[1]<=cutoff) return;
+    triagnormal(v1, v2, v3, norm);
+    glNormal3fv(norm);
+    glVertex3fv(v1);
+    glVertex3fv(v2);
+    glVertex3fv(v3);
+
+  } else {
+    GLfloat m1[3], m2[3], m3[3];
+
+    Midpoint(m1, v1, v2, 0, level);
+    Midpoint(m2, v2, v3, 1, level);
+    Midpoint(m3, v3, v1, 2, level);
+
+    FMR(v1, m1, m3, level + 1);
+    FMR(m1, v2, m2, level + 1);
+    FMR(m3, m2, v3, level + 1);
+    FMR(m1, m2, m3, level + 1);
+  }
+}
+
+ /*
+  * sets up lookup tables and calls recursive mountain function
+  */
+void FractalMountain(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3],
+                     int pegged[3])
+{
+  GLfloat lengths[MAXLEVEL];
+  GLfloat fraction[8] = { 0.3, 0.3, 0.4, 0.2, 0.3, 0.2, 0.4, 0.4  };
+  GLfloat bias[8]     = { 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1  };
+  int i;
+  float avglen = (xzlength(v1, v2) + 
+                  xzlength(v2, v3) +
+		  xzlength(v3, v1) / 3);
+
+  for (i = 0; i < 3; i++) {
+    Verts[0][i] = v1[i];      /* set mountain vertex globals */
+    Verts[1][i] = v2[i];
+    Verts[2][i] = v3[i];
+    Pegged[i] = pegged[i];
+  }
+
+  Slopes[0] = xzslope(Verts[0], Verts[1]);   /* set edge slope globals */
+  Slopes[1] = xzslope(Verts[1], Verts[2]);
+  Slopes[2] = xzslope(Verts[2], Verts[0]);
+
+  lengths[0] = avglen;          
+  for (i = 1; i < Level; i++) {   
+    lengths[i] = lengths[i-1]/2;     /* compute edge length for each level */
+  }
+
+  for (i = 0; i < Level; i++) {     /* DispFactor and DispBias arrays */      
+    DispFactor[i] = (lengths[i] * ((i <= 7) ? fraction[i] : fraction[7]));
+    DispBias[i]   = ((i <= 7) ? bias[i] : bias[7]);
+  } 
+
+  glBegin(GL_TRIANGLES);
+    FMR(v1, v2, v3, 0);    /* issues no GL but vertex calls */
+  glEnd();
+}
+
+ /*
+  * draw a mountain and build the display list
+  */
+void CreateMountain(void)
+{
+  GLfloat v1[3] = { 0, 0, -1 }, v2[3] = { -1, 0, 1 }, v3[3] = { 1, 0, 1 };
+  int pegged[3] = { 1, 1, 1 };
+
+  glNewList(MOUNTAIN, GL_COMPILE);
+  glPushAttrib(GL_LIGHTING_BIT);
+    glCallList(MOUNTAIN_MAT);
+    FractalMountain(v1, v2, v3, pegged);
+  glPopAttrib();
+  glEndList();
+}
+
+  /*
+   * new random numbers to make a different moutain
+   */
+void NewMountain(void)
+{
+  InitRandTable(time(NULL));
+}
+
+/***************************************************************/
+/***************************** TREE ****************************/
+/***************************************************************/
+
+long TreeSeed;   /* for srand48 - remember so we can build "same tree"
+                     at a different level */
+
+ /*
+  * recursive tree drawing thing, fleshed out from class notes pseudocode 
+  */
+void FractalTree(int level)
+{
+  long savedseed;  /* need to save seeds while building tree too */
+
+  if (level == Level) {
+      glPushMatrix();
+        glRotatef(drand48()*180, 0, 1, 0);
+        glCallList(STEMANDLEAVES);
+      glPopMatrix();
+  } else {
+    glCallList(STEM);
+    glPushMatrix();
+    glRotatef(drand48()*180, 0, 1, 0);
+    glTranslatef(0, 1, 0);
+    glScalef(0.7, 0.7, 0.7);
+
+      savedseed = (long)((ulong)drand48()*ULONG_MAX);
+      glPushMatrix();    
+        glRotatef(110 + drand48()*40, 0, 1, 0);
+        glRotatef(30 + drand48()*20, 0, 0, 1);
+        FractalTree(level + 1);
+      glPopMatrix();
+
+      srand48(savedseed);
+      savedseed = (long)((ulong)drand48()*ULONG_MAX);
+      glPushMatrix();
+        glRotatef(-130 + drand48()*40, 0, 1, 0);
+        glRotatef(30 + drand48()*20, 0, 0, 1);
+        FractalTree(level + 1);
+      glPopMatrix();
+
+      srand48(savedseed);
+      glPushMatrix();
+        glRotatef(-20 + drand48()*40, 0, 1, 0);
+        glRotatef(30 + drand48()*20, 0, 0, 1);
+        FractalTree(level + 1);
+      glPopMatrix();
+
+    glPopMatrix();
+  }
+}
+
+  /*
+   * Create display lists for a leaf, a set of leaves, and a stem
+   */
+void CreateTreeLists(void)
+{
+  GLUquadricObj *cylquad = gluNewQuadric();
+  int i;
+
+  glNewList(STEM, GL_COMPILE);
+  glPushMatrix();
+    glRotatef(-90, 1, 0, 0);
+    gluCylinder(cylquad, 0.1, 0.08, 1, 10, 2 );
+  glPopMatrix();
+  glEndList();
+
+  glNewList(LEAF, GL_COMPILE);  /* I think this was jeff allen's leaf idea */
+    glBegin(GL_TRIANGLES);
+      glNormal3f(-0.1, 0, 0.25);  /* not normalized */
+      glVertex3f(0, 0, 0);
+      glVertex3f(0.25, 0.25, 0.1);
+      glVertex3f(0, 0.5, 0);
+
+      glNormal3f(0.1, 0, 0.25);
+      glVertex3f(0, 0, 0);
+      glVertex3f(0, 0.5, 0);
+      glVertex3f(-0.25, 0.25, 0.1);
+    glEnd();
+  glEndList();
+
+  glNewList(STEMANDLEAVES, GL_COMPILE);
+  glPushMatrix();
+  glPushAttrib(GL_LIGHTING_BIT);
+    glCallList(STEM);
+    glCallList(LEAF_MAT);
+    for(i = 0; i < 3; i++) {
+      glTranslatef(0, 0.333, 0);
+      glRotatef(90, 0, 1, 0);
+      glPushMatrix();
+        glRotatef(0, 0, 1, 0);
+        glRotatef(50, 1, 0, 0);
+        glCallList(LEAF);
+      glPopMatrix();
+      glPushMatrix();
+        glRotatef(180, 0, 1, 0);
+        glRotatef(60, 1, 0, 0);
+        glCallList(LEAF);
+      glPopMatrix();
+    }
+  glPopAttrib();
+  glPopMatrix();
+  glEndList();
+}
+
+ /*
+  * draw and build display list for tree
+  */
+void CreateTree(void)
+{
+  srand48(TreeSeed);
+
+  glNewList(TREE, GL_COMPILE);
+    glPushMatrix();
+    glPushAttrib(GL_LIGHTING_BIT);
+    glCallList(TREE_MAT);
+    glTranslatef(0, -1, 0);
+    FractalTree(0);
+    glPopAttrib();
+    glPopMatrix();
+  glEndList();  
+}
+
+ /*
+  * new seed for a new tree (groan)
+  */
+void NewTree(void)
+{
+  TreeSeed = time(NULL);
+}
+
+/***************************************************************/
+/*********************** FRACTAL PLANET ************************/
+/***************************************************************/
+
+void CreateIsland(void)
+{
+  cutoff = .06;
+  CreateMountain();
+  cutoff = -1;
+  glNewList(ISLAND, GL_COMPILE);
+  glPushAttrib(GL_LIGHTING_BIT);
+  glMatrixMode(GL_MODELVIEW);
+  glPushMatrix();
+    glCallList(WATER_MAT);
+
+    glBegin(GL_QUADS);
+      glNormal3f(0, 1, 0);
+      glVertex3f(10, 0.01, 10);
+      glVertex3f(10, 0.01, -10);
+      glVertex3f(-10, 0.01, -10);
+      glVertex3f(-10, 0.01, 10);
+    glEnd();
+
+    glPushMatrix();
+    glTranslatef(0, -0.1, 0);
+    glCallList(MOUNTAIN);
+    glPopMatrix();
+
+    glPushMatrix();
+    glRotatef(135, 0, 1, 0);
+    glTranslatef(0.2, -0.15, -0.4);
+    glCallList(MOUNTAIN);
+    glPopMatrix();
+
+    glPushMatrix();
+    glRotatef(-60, 0, 1, 0);
+    glTranslatef(0.7, -0.07, 0.5);
+    glCallList(MOUNTAIN);
+    glPopMatrix();
+
+    glPushMatrix();
+    glRotatef(-175, 0, 1, 0);
+    glTranslatef(-0.7, -0.05, -0.5);
+    glCallList(MOUNTAIN);
+    glPopMatrix();
+
+    glPushMatrix();
+    glRotatef(165, 0, 1, 0);
+    glTranslatef(-0.9, -0.12, 0.0);
+    glCallList(MOUNTAIN);
+    glPopMatrix();
+
+  glPopMatrix();
+  glPopAttrib();
+  glEndList();  
+}
+
+
+void NewFractals(void)
+{
+  NewMountain();
+  NewTree();
+}
+
+void Create(int fract)
+{
+  switch(fract) {
+    case MOUNTAIN:
+      CreateMountain();
+      break;
+    case TREE:
+      CreateTree();
+      break;
+    case ISLAND:
+      CreateIsland();
+      break;
+  }
+}
+
+
+
+/***************************************************************/
+/**************************** OPENGL ***************************/
+/***************************************************************/
+
+
+void SetupMaterials(void)
+{
+  GLfloat mtn_ambuse[] =   { 0.426, 0.256, 0.108, 1.0 };
+  GLfloat mtn_specular[] = { 0.394, 0.272, 0.167, 1.0 };
+  GLfloat mtn_shininess[] = { 10 };
+
+  GLfloat water_ambuse[] =   { 0.0, 0.1, 0.5, 1.0 };
+  GLfloat water_specular[] = { 0.0, 0.1, 0.5, 1.0 };
+  GLfloat water_shininess[] = { 10 };
+
+  GLfloat tree_ambuse[] =   { 0.4, 0.25, 0.1, 1.0 };
+  GLfloat tree_specular[] = { 0.0, 0.0, 0.0, 1.0 };
+  GLfloat tree_shininess[] = { 0 };
+
+  GLfloat leaf_ambuse[] =   { 0.0, 0.8, 0.0, 1.0 };
+  GLfloat leaf_specular[] = { 0.0, 0.8, 0.0, 1.0 };
+  GLfloat leaf_shininess[] = { 10 };
+
+  glNewList(MOUNTAIN_MAT, GL_COMPILE);
+    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mtn_ambuse);
+    glMaterialfv(GL_FRONT, GL_SPECULAR, mtn_specular);
+    glMaterialfv(GL_FRONT, GL_SHININESS, mtn_shininess);
+  glEndList();
+
+  glNewList(WATER_MAT, GL_COMPILE);
+    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, water_ambuse);
+    glMaterialfv(GL_FRONT, GL_SPECULAR, water_specular);
+    glMaterialfv(GL_FRONT, GL_SHININESS, water_shininess);
+  glEndList();
+
+  glNewList(TREE_MAT, GL_COMPILE);
+    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, tree_ambuse);
+    glMaterialfv(GL_FRONT, GL_SPECULAR, tree_specular);
+    glMaterialfv(GL_FRONT, GL_SHININESS, tree_shininess);
+  glEndList();
+
+  glNewList(LEAF_MAT, GL_COMPILE);
+    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, leaf_ambuse);
+    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, leaf_specular);
+    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, leaf_shininess);
+  glEndList();
+}
+
+void myGLInit(void)
+{
+  GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
+  GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
+  GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
+  GLfloat light_position[] = { 0.0, 0.3, 0.3, 0.0 };
+
+  GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
+
+  glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
+  glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
+  glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
+  glLightfv(GL_LIGHT0, GL_POSITION, light_position);
+    
+  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
+
+  glEnable(GL_LIGHTING);
+  glEnable(GL_LIGHT0);
+
+  glDepthFunc(GL_LEQUAL);
+  glEnable(GL_DEPTH_TEST);
+
+  glEnable(GL_NORMALIZE);
+#if 0
+  glEnable(GL_CULL_FACE);
+  glCullFace(GL_BACK);
+#endif
+
+  glShadeModel(GL_SMOOTH);
+#if 0
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+#endif
+
+  SetupMaterials();
+  CreateTreeLists();
+
+  glFlush();
+} 
+
+/***************************************************************/
+/************************ GLUT STUFF ***************************/
+/***************************************************************/
+
+void reshape(int w, int h)
+{
+  glViewport(0,0,w,h);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective(60.0, (GLdouble)w/h, 0.01, 100);
+  glPushMatrix();
+  glMatrixMode(GL_MODELVIEW);
+  glFlush();
+}
+
+void display(void)
+{ 
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  glFlush();
+
+  glMatrixMode(GL_PROJECTION);
+  glPopMatrix();
+  glPushMatrix();  /* clear of last viewing xform, leaving perspective */
+
+  agvViewTransform();
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+
+  if (Rebuild) {
+    Create(Fract);
+    Rebuild = 0;
+  }
+
+  glCallList(Fract);
+
+  if (DrawAxes)
+    glCallList(AXES);
+
+  glutSwapBuffers();
+  glFlush();
+}
+
+void visible(int v)
+{
+  if (v == GLUT_VISIBLE)
+    agvSetAllowIdle(1);
+  else {
+    glutIdleFunc(NULL);
+    agvSetAllowIdle(0);
+  }
+}
+
+void menuuse(int v)
+{
+  if (v == GLUT_MENU_NOT_IN_USE)
+    agvSetAllowIdle(1);
+  else {
+    glutIdleFunc(NULL);
+    agvSetAllowIdle(0);
+  }
+}
+
+/***************************************************************/
+/******************* MENU SETUP & HANDLING *********************/
+/***************************************************************/
+
+typedef enum { MENU_QUIT, MENU_RAND, MENU_MOVE, MENU_AXES } MenuChoices;
+
+void setlevel(int value)
+{
+  Level = value;
+  Rebuild = 1;
+  glutPostRedisplay();
+}
+
+void choosefract(int value)
+{
+  Fract = value;
+  Rebuild = 1;
+  glutPostRedisplay();
+}
+
+void handlemenu(int value)
+{
+  switch (value) {
+    case MENU_QUIT:
+      exit(0);
+      break;
+    case MENU_RAND:
+      NewFractals();
+      Rebuild = 1;
+      glutPostRedisplay();
+      break;
+    case MENU_AXES:
+      DrawAxes = !DrawAxes;
+      glutPostRedisplay();
+      break;
+    }
+}
+
+void MenuInit(void)
+{
+  int submenu3, submenu2, submenu1;
+
+  submenu1 = glutCreateMenu(setlevel);
+  glutAddMenuEntry("0", 0);  glutAddMenuEntry("1", 1);
+  glutAddMenuEntry("2", 2);  glutAddMenuEntry("3", 3);
+  glutAddMenuEntry("4", 4);  glutAddMenuEntry("5", 5);
+  glutAddMenuEntry("6", 6);  glutAddMenuEntry("7", 7);
+  glutAddMenuEntry("8", 8);
+
+  submenu2 = glutCreateMenu(choosefract);
+  glutAddMenuEntry("Moutain", MOUNTAIN);
+  glutAddMenuEntry("Tree", TREE);
+  glutAddMenuEntry("Island", ISLAND);
+
+  submenu3 = glutCreateMenu(agvSwitchMoveMode);
+  glutAddMenuEntry("Flying", FLYING);
+  glutAddMenuEntry("Polar", POLAR);
+
+  glutCreateMenu(handlemenu);
+  glutAddSubMenu("Level", submenu1);
+  glutAddSubMenu("Fractal", submenu2);
+  glutAddSubMenu("Movement", submenu3);
+  glutAddMenuEntry("New Fractal",      MENU_RAND);
+  glutAddMenuEntry("Toggle Axes", MENU_AXES);
+  glutAddMenuEntry("Quit",             MENU_QUIT);
+  glutAttachMenu(GLUT_RIGHT_BUTTON);
+}
+
+
+/***************************************************************/
+/**************************** MAIN *****************************/
+/***************************************************************/
+
+// fltk-style callbacks to Glut menu callback translators:
+void setlevel(Fl_Widget*, void *value) {setlevel(long(value));}
+
+void choosefract(Fl_Widget*, void *value) {choosefract(long(value));}
+
+void handlemenu(Fl_Widget*, void *value) {handlemenu(long(value));}
+
+#include 
+#include 
+#include 
+
+int main(int argc, char** argv)
+{
+//  glutInit(&argc, argv); // this line removed for fltk
+
+  // create fltk window:
+  Fl_Window window(512+20, 512+100);
+  window.resizable(window);
+
+  // create a bunch of buttons:
+  Fl_Group *g = new Fl_Group(110,50,400-110,30,"Level:");
+  g->align(FL_ALIGN_LEFT);
+  g->begin();
+  Fl_Button *b;
+  b = new Fl_Button(110,50,30,30,"0"); b->callback(setlevel,(void*)0);
+  b = new Fl_Button(140,50,30,30,"1"); b->callback(setlevel,(void*)1);
+  b = new Fl_Button(170,50,30,30,"2"); b->callback(setlevel,(void*)2);
+  b = new Fl_Button(200,50,30,30,"3"); b->callback(setlevel,(void*)3);
+  b = new Fl_Button(230,50,30,30,"4"); b->callback(setlevel,(void*)4);
+  b = new Fl_Button(260,50,30,30,"5"); b->callback(setlevel,(void*)5);
+  b = new Fl_Button(290,50,30,30,"6"); b->callback(setlevel,(void*)6);
+  b = new Fl_Button(320,50,30,30,"7"); b->callback(setlevel,(void*)7);
+  b = new Fl_Button(350,50,30,30,"8"); b->callback(setlevel,(void*)8);
+  g->end();
+
+  b = new Fl_Button(400,50,100,30,"New Fractal"); b->callback(handlemenu,(void*)MENU_RAND);
+  
+  b = new Fl_Button( 10,10,100,30,"Mountain"); b->callback(choosefract,(void*)MOUNTAIN);
+  b = new Fl_Button(110,10,100,30,"Tree"); b->callback(choosefract,(void*)TREE);
+  b = new Fl_Button(210,10,100,30,"Island"); b->callback(choosefract,(void*)ISLAND);
+  b = new Fl_Button(400,10,100,30,"Quit"); b->callback(handlemenu,(void*)MENU_QUIT);
+
+
+  window.show(argc,argv); // glut will die unless parent window visible
+  window.begin(); // this will cause Glut window to be a child
+  glutInitWindowSize(512, 512);
+  glutInitWindowPosition(10,90); // place it inside parent window
+  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE);
+  glutCreateWindow("Fractal Planet?");
+  window.end();
+  window.resizable(glut_window);
+
+  agvInit(1); /* 1 cause we don't have our own idle */
+
+  glutReshapeFunc(reshape);
+  glutDisplayFunc(display);
+  glutVisibilityFunc(visible);
+  glutMenuStateFunc(menuuse);
+
+  NewFractals();
+  agvMakeAxesList(AXES);
+  myGLInit(); 
+  MenuInit();
+
+  glutMainLoop(); // must use this rather than Fl::run if glutIdleFunc is used
+  return 0;
+}
+#endif
diff --git a/test/fracviewer.c b/test/fracviewer.c
new file mode 100644
index 000000000..9d926c175
--- /dev/null
+++ b/test/fracviewer.c
@@ -0,0 +1,496 @@
+/*
+ * fractviewer.c [from agviewer.c  (version 1.0)]
+ *
+ * AGV: a glut viewer. Routines for viewing a 3d scene w/ glut
+ *
+ * See agv_example.c and agviewer.h comments within for more info.
+ *
+ * I welcome any feedback or improved versions!
+ *
+ * Philip Winston - 4/11/95
+ * pwinston@hmc.edu
+ * http://www.cs.hmc.edu/people/pwinston
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "fracviewer.h"
+
+/* Some  files do not define M_PI... */
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
+
+/***************************************************************/
+/************************** SETTINGS ***************************/
+/***************************************************************/
+
+   /* Initial polar movement settings */
+#define INIT_POLAR_AZ  0.0
+#define INIT_POLAR_EL 30.0
+#define INIT_DIST      4.0
+#define INIT_AZ_SPIN   0.5
+#define INIT_EL_SPIN   0.0
+
+  /* Initial flying movement settings */
+#define INIT_EX        0.0
+#define INIT_EY       -2.0
+#define INIT_EZ       -2.0
+#define INIT_MOVE     0.01
+#define MINMOVE      0.001    
+
+  /* Start in this mode */
+#define INIT_MODE   POLAR   
+
+  /* Controls:  */
+
+  /* map 0-9 to an EyeMove value when number key is hit in FLYING mode */
+#define SPEEDFUNCTION(x) ((x)*(x)*0.001)  
+
+  /* Multiply EyeMove by (1+-MOVEFRACTION) when +/- hit in FLYING mode */
+#define MOVEFRACTION 0.25   
+
+  /* What to multiply number of pixels mouse moved by to get rotation amount */
+#define EL_SENS   0.5
+#define AZ_SENS   0.5
+
+  /* What to multiply number of pixels mouse moved by for movement amounts */
+#define DIST_SENS 0.01
+#define E_SENS    0.01
+
+  /* Minimum spin to allow in polar (lower forced to zero) */
+#define MIN_AZSPIN 0.1
+#define MIN_ELSPIN 0.1
+
+  /* Factors used in computing dAz and dEl (which determine AzSpin, ElSpin) */
+#define SLOW_DAZ 0.90
+#define SLOW_DEL 0.90
+#define PREV_DAZ 0.80
+#define PREV_DEL 0.80
+#define CUR_DAZ  0.20
+#define CUR_DEL  0.20
+
+/***************************************************************/
+/************************** GLOBALS ****************************/
+/***************************************************************/
+
+int     MoveMode = INIT_MODE;  /* FLYING or POLAR mode? */
+
+GLfloat Ex = INIT_EX,             /* flying parameters */
+        Ey = INIT_EY,
+        Ez = INIT_EZ,
+        EyeMove = INIT_MOVE,     
+
+        EyeDist = INIT_DIST,      /* polar params */
+        AzSpin  = INIT_AZ_SPIN,
+        ElSpin  = INIT_EL_SPIN,
+
+        EyeAz = INIT_POLAR_AZ,    /* used by both */
+        EyeEl = INIT_POLAR_EL;
+
+int agvMoving;    /* Currently moving?  */
+
+int downx, downy,   /* for tracking mouse position */
+    lastx, lasty,
+    downb = -1;     /* and button status */
+						
+GLfloat downDist, downEl, downAz, /* for saving state of things */
+        downEx, downEy, downEz,   /* when button is pressed */
+        downEyeMove;                
+
+GLfloat dAz, dEl, lastAz, lastEl;  /* to calculate spinning w/ polar motion */
+int     AdjustingAzEl = 0;
+
+int AllowIdle, RedisplayWindow; 
+   /* If AllowIdle is 1 it means AGV will install its own idle which
+    * will update the viewpoint as needed and send glutPostRedisplay() to the
+    * window RedisplayWindow which was set in agvInit().  AllowIdle of 0
+    * means AGV won't install an idle funciton, and something like
+    * "if (agvMoving) agvMove()" should exist at the end of the running
+    * idle function.
+    */
+
+#define MAX(x,y) (((x) > (y)) ? (x) : (y))
+#define TORAD(x) ((M_PI/180.0)*(x))
+#define TODEG(x) ((180.0/M_PI)*(x))
+
+/***************************************************************/
+/************************ PROTOTYPES ***************************/
+/***************************************************************/
+
+  /*
+   * these are functions meant for internal use only
+   * the other prototypes are in agviewer.h
+   */
+
+void PolarLookFrom(GLfloat dist, GLfloat elevation, GLfloat azimuth);
+void FlyLookFrom(GLfloat x, GLfloat y, GLfloat z,
+                        GLfloat az, GLfloat el);
+int  ConstrainEl(void);
+void MoveOn(int v);
+void SetMove(float newmove);
+static void normalize(GLfloat v[3]);
+static void ncrossprod(float v1[3], float v2[3], float cp[3]);
+
+
+/***************************************************************/
+/************************ agvInit ******************************/
+/***************************************************************/
+
+void agvInit(int window)
+{
+  glutMouseFunc(agvHandleButton);
+  glutMotionFunc(agvHandleMotion);
+  glutKeyboardFunc(agvHandleKeys);
+  RedisplayWindow = glutGetWindow();
+  agvSetAllowIdle(window);
+}
+
+/***************************************************************/
+/************************ VIEWPOINT STUFF **********************/
+/***************************************************************/
+
+  /*
+   * viewing transformation modified from page 90 of red book
+   */
+void PolarLookFrom(GLfloat dist, GLfloat elevation, GLfloat azimuth)
+{
+  glTranslatef(0, 0, -dist);
+  glRotatef(elevation, 1, 0, 0);
+  glRotatef(azimuth, 0, 1, 0);
+
+}
+
+  /*
+   * I took the idea of tracking eye position in absolute
+   * coords and direction looking in Polar form from denis
+   */
+void FlyLookFrom(GLfloat x, GLfloat y, GLfloat z, GLfloat az, GLfloat el)
+{
+  float lookat[3], perp[3], up[3];
+
+  lookat[0] = sin(TORAD(az))*cos(TORAD(el));
+  lookat[1] = sin(TORAD(el));
+  lookat[2] = -cos(TORAD(az))*cos(TORAD(el));
+  normalize(lookat);
+  perp[0] = lookat[2];
+  perp[1] = 0;
+  perp[2] = -lookat[0];
+  normalize(perp);
+  ncrossprod(lookat, perp, up);
+  gluLookAt(x, y, z,
+            x+lookat[0], y+lookat[1], z+lookat[2],
+            up[0], up[1], up[2]);
+}
+
+  /*
+   * Call viewing transformation based on movement mode
+   */
+void agvViewTransform(void)
+{ 
+  switch (MoveMode) {
+    case FLYING:
+      FlyLookFrom(Ex, Ey, Ez, EyeAz, EyeEl);
+      break;
+    case POLAR:
+      PolarLookFrom(EyeDist, EyeEl, EyeAz);
+      break;
+    }
+}
+
+  /*
+   * keep them vertical; I think this makes a lot of things easier, 
+   * but maybe it wouldn't be too hard to adapt things to let you go
+   * upside down
+   */
+int ConstrainEl(void)
+{
+  if (EyeEl <= -90) {
+    EyeEl = -89.99;
+    return 1;
+  } else if (EyeEl >= 90) {
+    EyeEl = 89.99;
+    return 1;
+  }
+  return 0;
+}
+
+ /*
+  * Idle Function - moves eyeposition
+  */
+void agvMove(void)
+{
+
+  switch (MoveMode)  {
+    case FLYING:
+      Ex += EyeMove*sin(TORAD(EyeAz))*cos(TORAD(EyeEl));
+      Ey += EyeMove*sin(TORAD(EyeEl));
+      Ez -= EyeMove*cos(TORAD(EyeAz))*cos(TORAD(EyeEl));
+      break;
+
+    case POLAR:
+      EyeEl += ElSpin;
+      EyeAz += AzSpin;
+      if (ConstrainEl()) {  /* weird spin thing to make things look     */
+        ElSpin = -ElSpin;      /* look better when you are kept from going */
+                               /* upside down while spinning - Isn't great */
+        if (fabs(ElSpin) > fabs(AzSpin))
+          AzSpin = fabs(ElSpin) * ((AzSpin > 0) ? 1 : -1);
+      }
+      break;
+    }
+
+  if (AdjustingAzEl) {
+    dAz *= SLOW_DAZ;
+    dEl *= SLOW_DEL;
+  }
+
+  if (AllowIdle) {
+    glutSetWindow(RedisplayWindow);
+    glutPostRedisplay();
+  }
+}
+
+
+  /*
+   * Don't install agvMove as idle unless we will be updating the view
+   * and we've been given a RedisplayWindow
+   */
+void MoveOn(int v)
+{
+  if (v && ((MoveMode == FLYING && EyeMove != 0) ||
+             (MoveMode == POLAR &&
+             (AzSpin != 0 || ElSpin != 0 || AdjustingAzEl)))) {
+    agvMoving = 1;
+    if (AllowIdle)
+      glutIdleFunc(agvMove);
+  } else {
+    agvMoving = 0;
+    if (AllowIdle)
+      glutIdleFunc(NULL);
+  }
+}
+
+  /*
+   * set new redisplay window.  If <= 0 it means we are not to install
+   * an idle function and will rely on whoever does install one to 
+   * put statement like "if (agvMoving) agvMove();" at end of it
+   */
+void agvSetAllowIdle(int allowidle)
+{
+  if ((AllowIdle = allowidle))
+    MoveOn(1);
+}
+
+
+  /*
+   * when moving to flying we stay in the same spot, moving to polar we
+   * reset since we have to be looking at the origin (though a pivot from
+   * current position to look at origin might be cooler)
+   */
+void agvSwitchMoveMode(int move)
+{
+  switch (move) {
+    case FLYING:
+      if (MoveMode == FLYING) return;
+      Ex    = -EyeDist*sin(TORAD(EyeAz))*cos(TORAD(EyeEl));
+      Ey    =  EyeDist*sin(TORAD(EyeEl));
+      Ez    =  EyeDist*(cos(TORAD(EyeAz))*cos(TORAD(EyeEl)));
+      EyeAz =  EyeAz;
+      EyeEl = -EyeEl;
+      EyeMove = INIT_MOVE;
+      break;
+    case POLAR:
+      EyeDist = INIT_DIST;
+      EyeAz   = INIT_POLAR_AZ;
+      EyeEl   = INIT_POLAR_EL;
+      AzSpin  = INIT_AZ_SPIN;
+      ElSpin  = INIT_EL_SPIN;
+      break;
+    }
+  MoveMode = move;
+  MoveOn(1);
+  glutPostRedisplay();
+}
+
+/***************************************************************/
+/*******************    MOUSE HANDLING   ***********************/
+/***************************************************************/
+
+void agvHandleButton(int button, int state, int x, int y)
+{
+ if (state == GLUT_DOWN && downb == -1) {  
+    lastx = downx = x;
+    lasty = downy = y;
+    downb = button;    
+
+    switch (button) {
+      case GLUT_LEFT_BUTTON:
+        lastEl = downEl = EyeEl;
+        lastAz = downAz = EyeAz;
+        AzSpin = ElSpin = dAz = dEl = 0;
+        AdjustingAzEl = 1;
+	MoveOn(1);
+        break;
+
+      case GLUT_MIDDLE_BUTTON:
+        downDist = EyeDist;
+	downEx = Ex;
+	downEy = Ey;
+	downEz = Ez;
+	downEyeMove = EyeMove;
+	EyeMove = 0;
+    }
+
+  } else if (state == GLUT_UP && button == downb) {
+
+    downb = -1;
+
+    switch (button) {
+      case GLUT_LEFT_BUTTON:
+        if (MoveMode != FLYING) {
+	  AzSpin =  -dAz;
+	  if (AzSpin < MIN_AZSPIN && AzSpin > -MIN_AZSPIN)
+	    AzSpin = 0;	
+	  ElSpin = -dEl;
+	  if (ElSpin < MIN_ELSPIN && ElSpin > -MIN_ELSPIN)
+	    ElSpin = 0; 
+	}
+        AdjustingAzEl = 0;
+        MoveOn(1);
+	break;
+
+      case GLUT_MIDDLE_BUTTON:
+	EyeMove = downEyeMove;
+      }
+  }
+}
+
+ /*
+  * change EyeEl and EyeAz and position when mouse is moved w/ button down
+  */
+void agvHandleMotion(int x, int y)
+{
+  int deltax = x - downx, deltay = y - downy;
+
+  switch (downb) {
+    case GLUT_LEFT_BUTTON:
+      EyeEl  = downEl + EL_SENS * ((MoveMode == FLYING) ? -deltay : deltay);
+      ConstrainEl();
+      EyeAz  = downAz + AZ_SENS * deltax;
+      dAz    = PREV_DAZ*dAz + CUR_DAZ*(lastAz - EyeAz);
+      dEl    = PREV_DEL*dEl + CUR_DEL*(lastEl - EyeEl);
+      lastAz = EyeAz;
+      lastEl = EyeEl;
+      break;
+    case GLUT_MIDDLE_BUTTON:
+        EyeDist = downDist + DIST_SENS*deltay;
+        Ex = downEx - E_SENS*deltay*sin(TORAD(EyeAz))*cos(TORAD(EyeEl));
+        Ey = downEy - E_SENS*deltay*sin(TORAD(EyeEl));
+        Ez = downEz + E_SENS*deltay*cos(TORAD(EyeAz))*cos(TORAD(EyeEl));
+      break;
+  }
+  glutPostRedisplay();
+}
+
+/***************************************************************/
+/********************* KEYBOARD HANDLING ***********************/
+/***************************************************************/
+
+  /*
+   * set EyeMove (current speed) for FLYING mode
+   */
+void SetMove(float newmove)
+{
+  if (newmove > MINMOVE) {
+    EyeMove = newmove;
+    MoveOn(1);
+  } else {
+    EyeMove = 0;
+    MoveOn(0);
+  }
+}
+
+  /*
+   * 0->9 set speed, +/- adjust current speed  -- in FLYING mode
+   */
+void agvHandleKeys(unsigned char key, int, int) {
+  if (MoveMode != FLYING)
+    return;
+
+  if (key >= '0' && key <= '9')
+    SetMove(SPEEDFUNCTION((key-'0')));
+  else
+    switch(key) {
+      case '+':  
+        if (EyeMove == 0)
+          SetMove(MINMOVE);
+         else
+	  SetMove(EyeMove *= (1 + MOVEFRACTION));
+        break;
+      case '-':
+	SetMove(EyeMove *= (1 - MOVEFRACTION));
+        break;
+    }
+}
+
+/***************************************************************/
+/*********************** VECTOR STUFF **************************/
+/***************************************************************/
+
+  /* normalizes v */
+static void normalize(GLfloat v[3])
+{
+  GLfloat d = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+
+  if (d == 0)
+    fprintf(stderr, "Zero length vector in normalize\n");
+  else
+    v[0] /= d; v[1] /= d; v[2] /= d;
+}
+
+  /* calculates a normalized crossproduct to v1, v2 */
+static void ncrossprod(float v1[3], float v2[3], float cp[3])
+{
+  cp[0] = v1[1]*v2[2] - v1[2]*v2[1];
+  cp[1] = v1[2]*v2[0] - v1[0]*v2[2];
+  cp[2] = v1[0]*v2[1] - v1[1]*v2[0];
+  normalize(cp);
+}
+
+/***************************************************************/
+/**************************** AXES *****************************/
+/***************************************************************/
+
+
+  /* draw axes -- was helpful to debug/design things */
+void agvMakeAxesList(int displaylistnum)
+{
+  int i,j;
+  GLfloat axes_ambuse[] =   { 0.5, 0.0, 0.0, 1.0 };
+  glNewList(displaylistnum, GL_COMPILE);
+  glPushAttrib(GL_LIGHTING_BIT);
+  glMatrixMode(GL_MODELVIEW);
+    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, axes_ambuse);
+    glBegin(GL_LINES);
+      glVertex3f(15, 0, 0); glVertex3f(-15, 0, 0);
+      glVertex3f(0, 15, 0); glVertex3f(0, -15, 0);
+      glVertex3f(0, 0, 15); glVertex3f(0, 0, -15);
+    glEnd();
+    for (i = 0; i < 3; i++) {
+      glPushMatrix();
+        glTranslatef(-10*(i==0), -10*(i==1), -10*(i==2));
+        for (j = 0; j < 21; j++) {
+//          glutSolidCube(0.1);
+          glTranslatef(i==0, i==1, i==2);
+	}
+      glPopMatrix();
+    }
+  glPopAttrib();
+  glEndList();  
+}
+
+
diff --git a/test/fracviewer.h b/test/fracviewer.h
new file mode 100644
index 000000000..d217e9aa6
--- /dev/null
+++ b/test/fracviewer.h
@@ -0,0 +1,104 @@
+/*
+ * fracviewer.h [from agviewer.h  (version 1.0)]
+ *
+ * AGV: a glut viewer. Routines for viewing a 3d scene w/ glut
+ *
+ * The two view movement modes are POLAR and FLYING.  Both move the eye, NOT
+ * THE OBJECT.  You can never be upside down or twisted (roll) in either mode.
+ *
+ * A nice addition would be an examiner type trackball mode where you are
+ * moving the object and so could see it from any angle.  Also less restricted
+ * flying and polar modes (fly upside down, do rolls, etc.).
+ *
+ * Controls for Polar are just left and middle buttons -- for flying it's
+ * those plus 0-9 number keys and +/- for speed adjustment.
+ *
+ * See agv_example.c and agviewer.c for more info.  Probably want to make
+ * a copy of these and then edit for each program.  This isn't meant to be
+ * a library, just something to graft onto your own programs.
+ *
+ * I welcome any feedback or improved versions.
+ *
+ * Philip Winston - 4/11/95
+ * pwinston@hmc.edu
+ * http://www.cs.hmc.edu/people/pwinston
+ */
+
+
+ /*
+  * Call agvInit() with glut's current window set to the window in 
+  * which you want to run the viewer. Right after creating it is fine.  It
+  * will remember that window for possible later use (see below) and
+  * registers mouse, motion, and keyboard handlers for that window (see below).
+  *
+  * allowidle is 1 or 0 depnding on whether you will let AGV install
+  * and uninstall an idle function.  0 means you will not let it (because
+  * you will be having your own idle function). In this case it is your
+  * responsibility to put a statement like:
+  *
+  *     if (agvMoving)
+  *       agvMove();
+  *
+  * at the end of your idle function, to let AGV update the viewpoint if it
+  * is moving. 
+  *
+  * If allowidle is 1 it means AGV will install its own idle which
+  * will update the viewpoint as needed and send glutPostRedisplay() to the
+  * window which was current when agvInit() was called.
+  *
+  * agvSetIdleAllow changes this value so you can let AGV install its idle
+  * when your idle isn't installed. 
+  *
+  */
+void agvInit(int allowidle);
+void agvSetAllowIdle(int allowidle);
+
+
+ /*
+  * Set which movement mode you are in.
+  */
+typedef enum { FLYING, POLAR } MovementType;
+void agvSwitchMoveMode(int move);
+
+ /*
+  * agvViewTransform basically does the appropriate gluLookAt() for the 
+  * current position.  So call it in your display on the projection matrix
+  */
+void agvViewTransform(void);
+
+ /*
+  * agvMoving will be set by AGV according to whether it needs you to call
+  * agvMove() at the end of your idle function.  You only need these if 
+  * you aren't allowing AGV to do its own idle.
+  * (Don't change the value of agvMoving)
+  */
+extern int agvMoving;
+void agvMove(void);
+
+ /*
+  * These are the routines AGV registers to deal with mouse and keyboard input.
+  * Keyboard input only matters in flying mode, and then only to set speed.
+  * Mouse input only uses left two buttons in both modes.
+  * These are all registered with agvInit(), but you could register
+  * something else which called these, or reregister these as needed 
+  */
+void agvHandleButton(int button, int state, int x, int y);
+void agvHandleMotion(int x, int y);
+void agvHandleKeys(unsigned char key, int x, int y);
+
+ /*
+  * Just an extra routine which makes an x-y-z axes (about 10x10x10)
+  * which is nice for aligning things and debugging.  Pass it an available
+  * displaylist number.
+  */
+void agvMakeAxesList(int displaylist);
+
+
+
+
+
+
+
+
+
+
diff --git a/test/fromdos.c b/test/fromdos.c
new file mode 100644
index 000000000..54dff5a9f
--- /dev/null
+++ b/test/fromdos.c
@@ -0,0 +1,65 @@
+/* fromdos.c : strip the stupid ^M characters without mistakes! */
+
+/* this can do in-place conversion or be used as a pipe... */
+
+#include 
+#include 
+#include 
+#include 
+
+int main(int argc, char** argv) {
+  int f,c;
+  if (argc <= 1) {
+    if (isatty(0)) {
+      fprintf(stderr,"usage : %s \nStrips ^M characters.\nCan do in-place conversion of many files or can be used in a pipe\n",argv[0]);
+      return 1;
+    }
+    for (;;) {
+      c = getchar();
+      while (c == '\r') {
+	c = getchar();
+	if (c != '\n') putchar(c);
+      }
+      if (c < 0) break;
+      putchar(c);
+    }
+    return 0;
+  }
+  for (f = 1; f < argc; f++) {
+    char* fname = argv[f];
+    char tempname[1024];
+    FILE* in = fopen(fname,"rb");
+    FILE* out;
+    int mod = 0;
+    if (!in) {
+      fprintf(stderr,"%s : %s\n", fname, strerror(errno));
+      return 1;
+    }
+    strcpy(tempname, fname);
+    strcat(tempname, ".temp");
+    out = fopen(tempname, "wb");
+    if (!out) {
+      fprintf(stderr,"%s : %s\n", fname, strerror(errno));
+      return 1;
+    }
+    for (;;) {
+      c = getc(in);
+      while (c == '\r') {
+	c = getc(in);
+	if (c == '\n') mod=1; else putc(c,out);
+      }
+      if (c < 0) break;
+      putc(c,out);
+    }
+    fclose(in);
+    fclose(out);
+    if (!mod) {
+      fprintf(stderr,"%s : no change\n", fname);
+      unlink(tempname);
+    } else if (rename(tempname, fname)) {
+      fprintf(stderr,"Can't mv %s %s : %s\n",tempname,fname,strerror(errno));
+      return 1;
+    }
+  }
+  return 0;
+}
diff --git a/test/fullscreen.cxx b/test/fullscreen.cxx
new file mode 100644
index 000000000..08317d315
--- /dev/null
+++ b/test/fullscreen.cxx
@@ -0,0 +1,219 @@
+/*	fullscreen.C
+
+	This demo shows how to do many of the window manipulations that
+	are popular on SGI programs, even though X does not really like
+	them.  You can toggle the border on/off, change the visual to
+	switch between single/double buffer, and make the window take
+	over the screen.
+
+	Normally the program makes a single window with a child GL window.
+	This simulates a program where the 3D display is surrounded by
+	control knobs.  Running the program with an argument will
+	make it make a seperate GL window from the controls window.  This
+	simulates a (older?) style program where the graphics display is
+	a different window than the controls.
+
+	This program reports how many times it redraws the window to
+	stdout, so you can see how much time it is wasting.  It appears
+	to be impossible to prevent X from sending redundant resize
+	events, so there are extra redraws.  But the way I have the
+	code arranged here seems to be keeping that to a minimu.
+
+	Apparently unavoidable bugs:
+
+	Turning the border on causes an unnecessary redraw.
+
+	Turning off full screen when the border is on causes an unnecessary
+	resize and redraw when the program turns the border on.
+
+	If it is a seperate window, turning double buffering on and off
+	will cause the window to raise, deiconize, and possibly move.  You
+	can avoid this by making the Fl_Gl_Window a child of a normal
+	window.
+
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if HAVE_GL
+#include 
+#include 
+
+class shape_window : public Fl_Gl_Window {
+  void draw();
+public:
+  int sides;
+  shape_window(int x,int y,int w,int h,const char *l=0);
+};
+
+shape_window::shape_window(int x,int y,int w,int h,const char *l) :
+Fl_Gl_Window(x,y,w,h,l) {
+  sides = 3;
+}
+
+void shape_window::draw() {
+  printf("drawing size %d %d\n",w(),h());
+  if (!valid()) {
+    valid(1);
+//  printf("init\n");
+    glLoadIdentity();
+    glViewport(0,0,w(),h());
+  }
+  glClear(GL_COLOR_BUFFER_BIT);
+  glColor3f(.5,.6,.7);
+  glBegin(GL_POLYGON);
+  for (int i=0; i
+
+class shape_window : public Fl_Window {
+  void draw();
+public:
+  int sides;
+  shape_window(int x,int y,int w,int h,const char *l=0);
+};
+
+shape_window::shape_window(int x,int y,int w,int h,const char *l) :
+Fl_Window(x,y,w,h,l) {
+  sides = 3;
+}
+
+void shape_window::draw() {
+  fl_color(0);
+  fl_rectf(0,0,w(),h());
+  fl_font(0,20);
+  fl_color(7);
+  fl_draw("This requires GL",0,0,w(),h(),FL_ALIGN_CENTER);
+}
+
+#endif
+
+void sides_cb(Fl_Widget *o, void *p) {
+  shape_window *sw = (shape_window *)p;
+  sw->sides = int(((Fl_Slider *)o)->value());
+  sw->redraw();
+}
+
+#if HAVE_GL
+void double_cb(Fl_Widget *o, void *p) {
+  shape_window *sw = (shape_window *)p;
+  int d = ((Fl_Button *)o)->value();
+  sw->mode(d ? Fl_Mode(FL_DOUBLE|FL_RGB) : FL_RGB);
+}
+#else
+void double_cb(Fl_Widget *, void *) {}
+#endif
+
+void border_cb(Fl_Widget *o, void *p) {
+  Fl_Window *w = (Fl_Window *)p;
+  int d = ((Fl_Button *)o)->value();
+  w->border(d);
+}
+
+int px,py,pw,ph;
+Fl_Button *border_button;
+void fullscreen_cb(Fl_Widget *o, void *p) {
+  Fl_Window *w = (Fl_Window *)p;
+  int d = ((Fl_Button *)o)->value();
+  if (d) {
+    px = w->x();
+    py = w->y();
+    pw = w->w();
+    ph = w->h();
+    w->fullscreen();
+  } else {
+    w->fullscreen_off(px,py,pw,ph);
+  }
+}
+
+#include 
+
+void exit_cb(Fl_Widget *, void *) {
+  exit(0);
+}
+
+#define NUMB 5
+
+int twowindow = 0;
+int initfull = 0;
+int arg(int, char **argv, int &i) {
+  if (argv[i][1] == '2') {twowindow = 1; i++; return 1;}
+  if (argv[i][1] == 'f') {initfull = 1; i++; return 1;}
+  return 0;
+}
+
+int main(int argc, char **argv) {
+
+  int i=0;
+  if (Fl::args(argc,argv,i,arg) < argc)
+    Fl::fatal("Options are:\n -2 = 2 windows\n -f = startup fullscreen\n%s",Fl::help);
+
+  Fl_Single_Window window(300,300+30*NUMB); window.end();
+
+  shape_window sw(10,10,window.w()-20,window.h()-30*NUMB-20);
+#if HAVE_GL
+  sw.mode(FL_RGB);
+#endif
+
+  Fl_Window *w;
+  if (twowindow) {	// make it's own window
+    sw.resizable(&sw);
+    w = &sw;
+    window.set_modal();	// makes controls stay on top when fullscreen pushed
+    argc--;
+    sw.show();
+  } else {		// otherwise make a subwindow
+    window.add(sw);
+    window.resizable(&sw);
+    w = &window;
+  }
+
+  window.begin();
+
+  int y = window.h()-30*NUMB-5;
+  Fl_Hor_Slider slider(50,y,window.w()-60,30,"Sides:");
+  slider.align(FL_ALIGN_LEFT);
+  slider.callback(sides_cb,&sw);
+  slider.value(sw.sides);
+  slider.step(1);
+  slider.bounds(3,40);
+  y+=30;
+
+  Fl_Toggle_Light_Button b1(50,y,window.w()-60,30,"Double Buffered");
+  b1.callback(double_cb,&sw);
+  y+=30;
+
+  Fl_Toggle_Light_Button b2(50,y,window.w()-60,30,"Border");
+  b2.callback(border_cb,w);
+  b2.set();
+  border_button = &b2;
+  y+=30;
+
+  Fl_Toggle_Light_Button b3(50,y,window.w()-60,30,"FullScreen");
+  b3.callback(fullscreen_cb,w);
+  y+=30;
+
+  Fl_Button eb(50,y,window.w()-60,30,"Exit");
+  eb.callback(exit_cb);
+  y+=30;
+
+  if (initfull) {b3.set(); b3.do_callback();}
+
+  window.end();
+  window.show(argc,argv);
+
+  return Fl::run();
+}
diff --git a/test/gl_overlay.cxx b/test/gl_overlay.cxx
new file mode 100644
index 000000000..db7c0e3d8
--- /dev/null
+++ b/test/gl_overlay.cxx
@@ -0,0 +1,128 @@
+/*	The simple GL demo, modified to draw the GL overlay as well */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if !HAVE_GL
+#include 
+class shape_window : public Fl_Box {
+public:	
+  int sides;
+  shape_window(int x,int y,int w,int h,const char *l=0)
+    :Fl_Box(FL_DOWN_BOX,x,y,w,h,l){
+      label("This demo does\nnot work without GL");
+  }
+};
+#else
+#include 
+#include 
+
+class shape_window : public Fl_Gl_Window {
+  void draw();
+  void draw_overlay();
+public:
+  int sides;
+  int overlay_sides;
+  shape_window(int x,int y,int w,int h,const char *l=0);
+};
+
+shape_window::shape_window(int x,int y,int w,int h,const char *l) :
+Fl_Gl_Window(x,y,w,h,l) {
+  sides = overlay_sides = 3;
+}
+
+void shape_window::draw() {
+// the valid() property may be used to avoid reinitializing your
+// GL transformation for each redraw:
+  if (!valid()) {
+    valid(1);
+    glLoadIdentity();
+    glViewport(0,0,w(),h());
+  }
+// draw an amazing but slow graphic:
+  glClear(GL_COLOR_BUFFER_BIT);
+  //  for (int j=1; j<=1000; j++) {
+    glBegin(GL_POLYGON);
+    for (int i=0; isides = int(((Fl_Slider *)o)->value());
+  sw->redraw();
+}
+
+#if HAVE_GL
+void overlay_sides_cb(Fl_Widget *o, void *p) {
+  shape_window *sw = (shape_window *)p;
+  sw->overlay_sides = int(((Fl_Slider *)o)->value());
+  sw->redraw_overlay();
+}
+#endif
+#include 
+int main(int argc, char **argv) {
+
+  Fl_Window window(300, 370);
+
+  shape_window sw(10, 75, window.w()-20, window.h()-90);
+//sw.mode(FL_RGB);
+  window.resizable(&sw);
+
+  Fl_Hor_Slider slider(60, 5, window.w()-70, 30, "Sides:");
+  slider.align(FL_ALIGN_LEFT);
+  slider.callback(sides_cb,&sw);
+  slider.value(sw.sides);
+  slider.step(1);
+  slider.bounds(3,40);
+
+  Fl_Hor_Slider oslider(60, 40, window.w()-70, 30, "Overlay:");
+  oslider.align(FL_ALIGN_LEFT);
+#if HAVE_GL
+  oslider.callback(overlay_sides_cb,&sw);
+  oslider.value(sw.overlay_sides);
+#endif
+  oslider.step(1);
+  oslider.bounds(3,40);
+
+  window.end();
+  window.show(argc,argv);
+#if HAVE_GL
+  printf("Can do overlay = %d\n", sw.can_do_overlay());
+  sw.show();
+  sw.redraw_overlay();
+#else
+  sw.show();
+#endif
+
+  return Fl::run();
+}
diff --git a/test/glpuzzle.cxx b/test/glpuzzle.cxx
new file mode 100644
index 000000000..78d515c35
--- /dev/null
+++ b/test/glpuzzle.cxx
@@ -0,0 +1,1455 @@
+// This is a GLUT demo program to demonstrate fltk's GLUT emulation.
+// Search for "fltk" to find all the changes
+
+// this block added for fltk's distribtion so it will compile w/o OpenGL:
+#include 
+#if !HAVE_GL
+#include 
+#include 
+int main(int, char**) {
+  fl_alert("This demo does not work without GL");
+  return 1;
+}
+#else
+// end of added block
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 	// changed for fltk
+#include "trackball.c"	// changed from trackball.h for fltk
+
+#define WIDTH 4
+#define HEIGHT 5
+#define PIECES 10
+#define OFFSETX -2
+#define OFFSETY -2.5
+#define OFFSETZ -0.5
+
+typedef char Config[HEIGHT][WIDTH];
+
+struct puzzle {
+  struct puzzle *backptr;
+  struct puzzle *solnptr;
+  Config pieces;
+  struct puzzle *next;
+  unsigned hashvalue;
+};
+
+#define HASHSIZE 10691
+
+struct puzzlelist {
+  struct puzzle *puzzle;
+  struct puzzlelist *next;
+};
+
+static char convert[PIECES + 1] =
+{0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4};
+
+static unsigned char colors[PIECES + 1][3] =
+{
+  {0, 0, 0},
+  {255, 255, 127},
+  {255, 255, 127},
+  {255, 255, 127},
+  {255, 255, 127},
+  {255, 127, 255},
+  {255, 127, 255},
+  {255, 127, 255},
+  {255, 127, 255},
+  {255, 127, 127},
+  {255, 255, 255},
+};
+
+void changeState(void);
+
+static struct puzzle *hashtable[HASHSIZE];
+static struct puzzle *startPuzzle;
+static struct puzzlelist *puzzles;
+static struct puzzlelist *lastentry;
+
+int curX, curY, visible;
+
+#define MOVE_SPEED 0.2
+static unsigned char movingPiece;
+static float move_x, move_y;
+static float curquat[4];
+static int doubleBuffer = 1;
+static int depth = 1;
+
+static char xsize[PIECES + 1] =
+{0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2};
+static char ysize[PIECES + 1] =
+{0, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2};
+static float zsize[PIECES + 1] =
+{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.6};
+
+static Config startConfig =
+{
+  {8, 10, 10, 7},
+  {8, 10, 10, 7},
+  {6, 9, 9, 5},
+  {6, 4, 3, 5},
+  {2, 0, 0, 1}
+};
+
+static Config thePuzzle =
+{
+  {8, 10, 10, 7},
+  {8, 10, 10, 7},
+  {6, 9, 9, 5},
+  {6, 4, 3, 5},
+  {2, 0, 0, 1}
+};
+
+static int xadds[4] =
+{-1, 0, 1, 0};
+static int yadds[4] =
+{0, -1, 0, 1};
+
+static long W = 400, H = 300;
+static GLint viewport[4];
+
+#define srandom srand
+#define random() (rand() >> 2)
+
+unsigned
+hash(Config config)
+{
+  int i, j, value;
+
+  value = 0;
+  for (i = 0; i < HEIGHT; i++) {
+    for (j = 0; j < WIDTH; j++) {
+      value = value + convert[config[i][j]];
+      value *= 6;
+    }
+  }
+  return (value);
+}
+
+int
+solution(Config config)
+{
+  if (config[4][1] == 10 && config[4][2] == 10)
+    return (1);
+  return (0);
+}
+
+float boxcoords[][3] =
+{
+  {0.2, 0.2, 0.9},
+  {0.8, 0.2, 0.9},
+  {0.8, 0.8, 0.9},
+  {0.2, 0.8, 0.9},
+  {0.2, 0.1, 0.8},
+  {0.8, 0.1, 0.8},
+  {0.9, 0.2, 0.8},
+  {0.9, 0.8, 0.8},
+  {0.8, 0.9, 0.8},
+  {0.2, 0.9, 0.8},
+  {0.1, 0.8, 0.8},
+  {0.1, 0.2, 0.8},
+  {0.2, 0.1, 0.2},
+  {0.8, 0.1, 0.2},
+  {0.9, 0.2, 0.2},
+  {0.9, 0.8, 0.2},
+  {0.8, 0.9, 0.2},
+  {0.2, 0.9, 0.2},
+  {0.1, 0.8, 0.2},
+  {0.1, 0.2, 0.2},
+  {0.2, 0.2, 0.1},
+  {0.8, 0.2, 0.1},
+  {0.8, 0.8, 0.1},
+  {0.2, 0.8, 0.1},
+};
+
+float boxnormals[][3] =
+{
+  {0, 0, 1},            /* 0 */
+  {0, 1, 0},
+  {1, 0, 0},
+  {0, 0, -1},
+  {0, -1, 0},
+  {-1, 0, 0},
+  {0.7071, 0.7071, 0.0000},  /* 6 */
+  {0.7071, -0.7071, 0.0000},
+  {-0.7071, 0.7071, 0.0000},
+  {-0.7071, -0.7071, 0.0000},
+  {0.7071, 0.0000, 0.7071},  /* 10 */
+  {0.7071, 0.0000, -0.7071},
+  {-0.7071, 0.0000, 0.7071},
+  {-0.7071, 0.0000, -0.7071},
+  {0.0000, 0.7071, 0.7071},  /* 14 */
+  {0.0000, 0.7071, -0.7071},
+  {0.0000, -0.7071, 0.7071},
+  {0.0000, -0.7071, -0.7071},
+  {0.5774, 0.5774, 0.5774},  /* 18 */
+  {0.5774, 0.5774, -0.5774},
+  {0.5774, -0.5774, 0.5774},
+  {0.5774, -0.5774, -0.5774},
+  {-0.5774, 0.5774, 0.5774},
+  {-0.5774, 0.5774, -0.5774},
+  {-0.5774, -0.5774, 0.5774},
+  {-0.5774, -0.5774, -0.5774},
+};
+
+int boxfaces[][4] =
+{
+  {0, 1, 2, 3},         /* 0 */
+  {9, 8, 16, 17},
+  {6, 14, 15, 7},
+  {20, 23, 22, 21},
+  {12, 13, 5, 4},
+  {19, 11, 10, 18},
+  {7, 15, 16, 8},       /* 6 */
+  {13, 14, 6, 5},
+  {18, 10, 9, 17},
+  {19, 12, 4, 11},
+  {1, 6, 7, 2},         /* 10 */
+  {14, 21, 22, 15},
+  {11, 0, 3, 10},
+  {20, 19, 18, 23},
+  {3, 2, 8, 9},         /* 14 */
+  {17, 16, 22, 23},
+  {4, 5, 1, 0},
+  {20, 21, 13, 12},
+  {2, 7, 8, -1},        /* 18 */
+  {16, 15, 22, -1},
+  {5, 6, 1, -1},
+  {13, 21, 14, -1},
+  {10, 3, 9, -1},
+  {18, 17, 23, -1},
+  {11, 4, 0, -1},
+  {20, 12, 19, -1},
+};
+
+#define NBOXFACES (sizeof(boxfaces)/sizeof(boxfaces[0]))
+
+/* Draw a box.  Bevel as desired. */
+void
+drawBox(int piece, float xoff, float yoff)
+{
+  int xlen, ylen;
+  int i, k;
+  float x, y, z;
+  float zlen;
+  float *v;
+
+  xlen = xsize[piece];
+  ylen = ysize[piece];
+  zlen = zsize[piece];
+
+  glColor3ubv(colors[piece]);
+  glBegin(GL_QUADS);
+  for (i = 0; i < 18; i++) {
+    glNormal3fv(boxnormals[i]);
+    for (k = 0; k < 4; k++) {
+      if (boxfaces[i][k] == -1)
+        continue;
+      v = boxcoords[boxfaces[i][k]];
+      x = v[0] + OFFSETX;
+      if (v[0] > 0.5)
+        x += xlen - 1;
+      y = v[1] + OFFSETY;
+      if (v[1] > 0.5)
+        y += ylen - 1;
+      z = v[2] + OFFSETZ;
+      if (v[2] > 0.5)
+        z += zlen - 1;
+      glVertex3f(xoff + x, yoff + y, z);
+    }
+  }
+  glEnd();
+  glBegin(GL_TRIANGLES);
+  for (i = 18; i < int(NBOXFACES); i++) {
+    glNormal3fv(boxnormals[i]);
+    for (k = 0; k < 3; k++) {
+      if (boxfaces[i][k] == -1)
+        continue;
+      v = boxcoords[boxfaces[i][k]];
+      x = v[0] + OFFSETX;
+      if (v[0] > 0.5)
+        x += xlen - 1;
+      y = v[1] + OFFSETY;
+      if (v[1] > 0.5)
+        y += ylen - 1;
+      z = v[2] + OFFSETZ;
+      if (v[2] > 0.5)
+        z += zlen - 1;
+      glVertex3f(xoff + x, yoff + y, z);
+    }
+  }
+  glEnd();
+}
+
+float containercoords[][3] =
+{
+  {-0.1, -0.1, 1.0},
+  {-0.1, -0.1, -0.1},
+  {4.1, -0.1, -0.1},
+  {4.1, -0.1, 1.0},
+  {1.0, -0.1, 0.6},     /* 4 */
+  {3.0, -0.1, 0.6},
+  {1.0, -0.1, 0.0},
+  {3.0, -0.1, 0.0},
+  {1.0, 0.0, 0.0},      /* 8 */
+  {3.0, 0.0, 0.0},
+  {3.0, 0.0, 0.6},
+  {1.0, 0.0, 0.6},
+  {0.0, 0.0, 1.0},      /* 12 */
+  {4.0, 0.0, 1.0},
+  {4.0, 0.0, 0.0},
+  {0.0, 0.0, 0.0},
+  {0.0, 5.0, 0.0},      /* 16 */
+  {0.0, 5.0, 1.0},
+  {4.0, 5.0, 1.0},
+  {4.0, 5.0, 0.0},
+  {-0.1, 5.1, -0.1},    /* 20 */
+  {4.1, 5.1, -0.1},
+  {4.1, 5.1, 1.0},
+  {-0.1, 5.1, 1.0},
+};
+
+float containernormals[][3] =
+{
+  {0, -1, 0},
+  {0, -1, 0},
+  {0, -1, 0},
+  {0, -1, 0},
+  {0, -1, 0},
+  {0, 1, 0},
+  {0, 1, 0},
+  {0, 1, 0},
+  {1, 0, 0},
+  {1, 0, 0},
+  {1, 0, 0},
+  {-1, 0, 0},
+  {-1, 0, 0},
+  {-1, 0, 0},
+  {0, 1, 0},
+  {0, 0, -1},
+  {0, 0, -1},
+  {0, 0, 1},
+  {0, 0, 1},
+  {0, 0, 1},
+  {0, 0, 1},
+  {0, 0, 1},
+  {0, 0, 1},
+  {0, 0, 1},
+};
+
+int containerfaces[][4] =
+{
+  {1, 6, 4, 0},
+  {0, 4, 5, 3},
+  {1, 2, 7, 6},
+  {7, 2, 3, 5},
+  {16, 19, 18, 17},
+
+  {23, 22, 21, 20},
+  {12, 11, 8, 15},
+  {10, 13, 14, 9},
+
+  {15, 16, 17, 12},
+  {2, 21, 22, 3},
+  {6, 8, 11, 4},
+
+  {1, 0, 23, 20},
+  {14, 13, 18, 19},
+  {9, 7, 5, 10},
+
+  {12, 13, 10, 11},
+
+  {1, 20, 21, 2},
+  {4, 11, 10, 5},
+
+  {15, 8, 19, 16},
+  {19, 8, 9, 14},
+  {8, 6, 7, 9},
+  {0, 3, 13, 12},
+  {13, 3, 22, 18},
+  {18, 22, 23, 17},
+  {17, 23, 0, 12},
+};
+
+#define NCONTFACES (sizeof(containerfaces)/sizeof(containerfaces[0]))
+
+/* Draw the container */
+void
+drawContainer(void)
+{
+  int i, k;
+  float *v;
+
+  /* Y is reversed here because the model has it reversed */
+
+  /* Arbitrary bright wood-like color */
+  glColor3ub(209, 103, 23);
+  glBegin(GL_QUADS);
+  for (i = 0; i < int(NCONTFACES); i++) {
+    v = containernormals[i];
+    glNormal3f(v[0], -v[1], v[2]);
+    for (k = 3; k >= 0; k--) {
+      v = containercoords[containerfaces[i][k]];
+      glVertex3f(v[0] + OFFSETX, -(v[1] + OFFSETY), v[2] + OFFSETZ);
+    }
+  }
+  glEnd();
+}
+
+void
+drawAll(void)
+{
+  int i, j;
+  int piece;
+  char done[PIECES + 1];
+  float m[4][4];
+
+  build_rotmatrix(m, curquat);
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  glTranslatef(0, 0, -10);
+  glMultMatrixf(&(m[0][0]));
+  glRotatef(180, 0, 0, 1);
+
+  if (depth) {
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  } else {
+    glClear(GL_COLOR_BUFFER_BIT);
+  }
+  for (i = 1; i <= PIECES; i++) {
+    done[i] = 0;
+  }
+  glLoadName(0);
+  drawContainer();
+  for (i = 0; i < HEIGHT; i++) {
+    for (j = 0; j < WIDTH; j++) {
+      piece = thePuzzle[i][j];
+      if (piece == 0)
+        continue;
+      if (done[piece])
+        continue;
+      done[piece] = 1;
+      glLoadName(piece);
+      if (piece == movingPiece) {
+        drawBox(piece, move_x, move_y);
+      } else {
+        drawBox(piece, j, i);
+      }
+    }
+  }
+}
+
+void
+redraw(void)
+{
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective(45, 1.0, 0.1, 100.0);
+
+  drawAll();
+
+  if (doubleBuffer)
+    glutSwapBuffers();
+  else
+    glFinish();
+}
+
+void
+solidifyChain(struct puzzle *puzzle)
+{
+  int i;
+  char buf[256];
+
+  i = 0;
+  while (puzzle->backptr) {
+    i++;
+    puzzle->backptr->solnptr = puzzle;
+    puzzle = puzzle->backptr;
+  }
+  sprintf(buf, "%d moves to complete!", i);
+  glutSetWindowTitle(buf);
+}
+
+int
+addConfig(Config config, struct puzzle *back)
+{
+  unsigned hashvalue;
+  struct puzzle *newpiece;
+  struct puzzlelist *newlistentry;
+
+  hashvalue = hash(config);
+
+  newpiece = hashtable[hashvalue % HASHSIZE];
+  while (newpiece != NULL) {
+    if (newpiece->hashvalue == hashvalue) {
+      int i, j;
+
+      for (i = 0; i < WIDTH; i++) {
+        for (j = 0; j < HEIGHT; j++) {
+          if (convert[config[j][i]] !=
+            convert[newpiece->pieces[j][i]])
+            goto nomatch;
+        }
+      }
+      return 0;
+    }
+  nomatch:
+    newpiece = newpiece->next;
+  }
+
+  newpiece = (struct puzzle *) malloc(sizeof(struct puzzle));
+  newpiece->next = hashtable[hashvalue % HASHSIZE];
+  newpiece->hashvalue = hashvalue;
+  memcpy(newpiece->pieces, config, HEIGHT * WIDTH);
+  newpiece->backptr = back;
+  newpiece->solnptr = NULL;
+  hashtable[hashvalue % HASHSIZE] = newpiece;
+
+  newlistentry = (struct puzzlelist *) malloc(sizeof(struct puzzlelist));
+  newlistentry->puzzle = newpiece;
+  newlistentry->next = NULL;
+
+  if (lastentry) {
+    lastentry->next = newlistentry;
+  } else {
+    puzzles = newlistentry;
+  }
+  lastentry = newlistentry;
+
+  if (back == NULL) {
+    startPuzzle = newpiece;
+  }
+  if (solution(config)) {
+    solidifyChain(newpiece);
+    return 1;
+  }
+  return 0;
+}
+
+/* Checks if a space can move */
+int
+canmove0(Config pieces, int x, int y, int dir, Config newpieces)
+{
+  char piece;
+  int xadd, yadd;
+  int l, m;
+
+  xadd = xadds[dir];
+  yadd = yadds[dir];
+
+  if (x + xadd < 0 || x + xadd >= WIDTH ||
+    y + yadd < 0 || y + yadd >= HEIGHT)
+    return 0;
+  piece = pieces[y + yadd][x + xadd];
+  if (piece == 0)
+    return 0;
+  memcpy(newpieces, pieces, HEIGHT * WIDTH);
+  for (l = 0; l < WIDTH; l++) {
+    for (m = 0; m < HEIGHT; m++) {
+      if (newpieces[m][l] == piece)
+        newpieces[m][l] = 0;
+    }
+  }
+  xadd = -xadd;
+  yadd = -yadd;
+  for (l = 0; l < WIDTH; l++) {
+    for (m = 0; m < HEIGHT; m++) {
+      if (pieces[m][l] == piece) {
+        int newx, newy;
+
+        newx = l + xadd;
+        newy = m + yadd;
+        if (newx < 0 || newx >= WIDTH ||
+          newy < 0 || newy >= HEIGHT)
+          return 0;
+        if (newpieces[newy][newx] != 0)
+          return 0;
+        newpieces[newy][newx] = piece;
+      }
+    }
+  }
+  return 1;
+}
+
+/* Checks if a piece can move */
+int
+canmove(Config pieces, int x, int y, int dir, Config newpieces)
+{
+  int xadd, yadd;
+
+  xadd = xadds[dir];
+  yadd = yadds[dir];
+
+  if (x + xadd < 0 || x + xadd >= WIDTH ||
+    y + yadd < 0 || y + yadd >= HEIGHT)
+    return 0;
+  if (pieces[y + yadd][x + xadd] == pieces[y][x]) {
+    return canmove(pieces, x + xadd, y + yadd, dir, newpieces);
+  }
+  if (pieces[y + yadd][x + xadd] != 0)
+    return 0;
+  return canmove0(pieces, x + xadd, y + yadd, (dir + 2) % 4, newpieces);
+}
+
+int
+generateNewConfigs(struct puzzle *puzzle)
+{
+  int i, j, k;
+  Config pieces;
+  Config newpieces;
+
+  memcpy(pieces, puzzle->pieces, HEIGHT * WIDTH);
+  for (i = 0; i < WIDTH; i++) {
+    for (j = 0; j < HEIGHT; j++) {
+      if (pieces[j][i] == 0) {
+        for (k = 0; k < 4; k++) {
+          if (canmove0(pieces, i, j, k, newpieces)) {
+            if (addConfig(newpieces, puzzle))
+              return 1;
+          }
+        }
+      }
+    }
+  }
+  return 0;
+}
+
+void
+freeSolutions(void)
+{
+  struct puzzlelist *nextpuz;
+  struct puzzle *puzzle, *next;
+  int i;
+
+  while (puzzles) {
+    nextpuz = puzzles->next;
+    free((char *) puzzles);
+    puzzles = nextpuz;
+  }
+  lastentry = NULL;
+  for (i = 0; i < HASHSIZE; i++) {
+    puzzle = hashtable[i];
+    hashtable[i] = NULL;
+    while (puzzle) {
+      next = puzzle->next;
+      free((char *) puzzle);
+      puzzle = next;
+    }
+  }
+  startPuzzle = NULL;
+}
+
+int
+continueSolving(void)
+{
+  struct puzzle *nextpuz;
+  int i, j;
+  int movedPiece;
+  int movedir;
+  int fromx, fromy;
+  int tox, toy;
+
+  if (startPuzzle == NULL)
+    return 0;
+  if (startPuzzle->solnptr == NULL) {
+    freeSolutions();
+    return 0;
+  }
+  nextpuz = startPuzzle->solnptr;
+  movedPiece = 0;
+  movedir = 0;
+  for (i = 0; i < HEIGHT; i++) {
+    for (j = 0; j < WIDTH; j++) {
+      if (startPuzzle->pieces[i][j] != nextpuz->pieces[i][j]) {
+        if (startPuzzle->pieces[i][j]) {
+          movedPiece = startPuzzle->pieces[i][j];
+          fromx = j;
+          fromy = i;
+          if (i < HEIGHT - 1 && nextpuz->pieces[i + 1][j] == movedPiece) {
+            movedir = 3;
+          } else {
+            movedir = 2;
+          }
+          goto found_piece;
+        } else {
+          movedPiece = nextpuz->pieces[i][j];
+          if (i < HEIGHT - 1 &&
+            startPuzzle->pieces[i + 1][j] == movedPiece) {
+            fromx = j;
+            fromy = i + 1;
+            movedir = 1;
+          } else {
+            fromx = j + 1;
+            fromy = i;
+            movedir = 0;
+          }
+          goto found_piece;
+        }
+      }
+    }
+  }
+  glutSetWindowTitle("What!  No change?");
+  freeSolutions();
+  return 0;
+
+found_piece:
+  if (!movingPiece) {
+    movingPiece = movedPiece;
+    move_x = fromx;
+    move_y = fromy;
+  }
+  move_x += xadds[movedir] * MOVE_SPEED;
+  move_y += yadds[movedir] * MOVE_SPEED;
+
+  tox = fromx + xadds[movedir];
+  toy = fromy + yadds[movedir];
+
+  if (move_x > tox - MOVE_SPEED / 2 && move_x < tox + MOVE_SPEED / 2 &&
+    move_y > toy - MOVE_SPEED / 2 && move_y < toy + MOVE_SPEED / 2) {
+    startPuzzle = nextpuz;
+    movingPiece = 0;
+  }
+  memcpy(thePuzzle, startPuzzle->pieces, HEIGHT * WIDTH);
+  changeState();
+  return 1;
+}
+
+int
+solvePuzzle(void)
+{
+  struct puzzlelist *nextpuz;
+  char buf[256];
+  int i;
+
+  if (solution(thePuzzle)) {
+    glutSetWindowTitle("Puzzle already solved!");
+    return 0;
+  }
+  addConfig(thePuzzle, NULL);
+  i = 0;
+
+  while (puzzles) {
+    i++;
+    if (generateNewConfigs(puzzles->puzzle))
+      break;
+    nextpuz = puzzles->next;
+    free((char *) puzzles);
+    puzzles = nextpuz;
+  }
+  if (puzzles == NULL) {
+    freeSolutions();
+    sprintf(buf, "I can't solve it! (%d positions examined)", i);
+    glutSetWindowTitle(buf);
+    return 1;
+  }
+  return 1;
+}
+
+int
+selectPiece(int mousex, int mousey)
+{
+  long hits;
+  GLuint selectBuf[1024];
+  GLuint closest;
+  GLuint dist;
+
+  glSelectBuffer(1024, selectBuf);
+  (void) glRenderMode(GL_SELECT);
+  glInitNames();
+
+  /* Because LoadName() won't work with no names on the stack */
+  glPushName(0);
+
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPickMatrix(mousex, H - mousey, 4, 4, viewport);
+  gluPerspective(45, 1.0, 0.1, 100.0);
+
+  drawAll();
+
+  hits = glRenderMode(GL_RENDER);
+  if (hits <= 0) {
+    return 0;
+  }
+  closest = 0;
+  dist = 4294967295;
+  while (hits) {
+    if (selectBuf[(hits - 1) * 4 + 1] < dist) {
+      dist = selectBuf[(hits - 1) * 4 + 1];
+      closest = selectBuf[(hits - 1) * 4 + 3];
+    }
+    hits--;
+  }
+  return closest;
+}
+
+void
+nukePiece(int piece)
+{
+  int i, j;
+
+  for (i = 0; i < HEIGHT; i++) {
+    for (j = 0; j < WIDTH; j++) {
+      if (thePuzzle[i][j] == piece) {
+        thePuzzle[i][j] = 0;
+      }
+    }
+  }
+}
+
+void
+multMatrices(const GLfloat a[16], const GLfloat b[16], GLfloat r[16])
+{
+  int i, j;
+
+  for (i = 0; i < 4; i++) {
+    for (j = 0; j < 4; j++) {
+      r[i * 4 + j] =
+        a[i * 4 + 0] * b[0 * 4 + j] +
+        a[i * 4 + 1] * b[1 * 4 + j] +
+        a[i * 4 + 2] * b[2 * 4 + j] +
+        a[i * 4 + 3] * b[3 * 4 + j];
+    }
+  }
+}
+
+void
+makeIdentity(GLfloat m[16])
+{
+  m[0 + 4 * 0] = 1;
+  m[0 + 4 * 1] = 0;
+  m[0 + 4 * 2] = 0;
+  m[0 + 4 * 3] = 0;
+  m[1 + 4 * 0] = 0;
+  m[1 + 4 * 1] = 1;
+  m[1 + 4 * 2] = 0;
+  m[1 + 4 * 3] = 0;
+  m[2 + 4 * 0] = 0;
+  m[2 + 4 * 1] = 0;
+  m[2 + 4 * 2] = 1;
+  m[2 + 4 * 3] = 0;
+  m[3 + 4 * 0] = 0;
+  m[3 + 4 * 1] = 0;
+  m[3 + 4 * 2] = 0;
+  m[3 + 4 * 3] = 1;
+}
+
+/*
+   ** inverse = invert(src)
+ */
+int
+invertMatrix(const GLfloat src[16], GLfloat inverse[16])
+{
+  int i, j, k, swap;
+  double t;
+  GLfloat temp[4][4];
+
+  for (i = 0; i < 4; i++) {
+    for (j = 0; j < 4; j++) {
+      temp[i][j] = src[i * 4 + j];
+    }
+  }
+  makeIdentity(inverse);
+
+  for (i = 0; i < 4; i++) {
+    /* 
+       ** Look for largest element in column */
+    swap = i;
+    for (j = i + 1; j < 4; j++) {
+      if (fabs(temp[j][i]) > fabs(temp[i][i])) {
+        swap = j;
+      }
+    }
+
+    if (swap != i) {
+      /* 
+         ** Swap rows. */
+      for (k = 0; k < 4; k++) {
+        t = temp[i][k];
+        temp[i][k] = temp[swap][k];
+        temp[swap][k] = t;
+
+        t = inverse[i * 4 + k];
+        inverse[i * 4 + k] = inverse[swap * 4 + k];
+        inverse[swap * 4 + k] = t;
+      }
+    }
+    if (temp[i][i] == 0) {
+      /* 
+         ** No non-zero pivot.  The matrix is singular, which
+         shouldn't ** happen.  This means the user gave us a
+         bad matrix. */
+      return 0;
+    }
+    t = temp[i][i];
+    for (k = 0; k < 4; k++) {
+      temp[i][k] /= t;
+      inverse[i * 4 + k] /= t;
+    }
+    for (j = 0; j < 4; j++) {
+      if (j != i) {
+        t = temp[j][i];
+        for (k = 0; k < 4; k++) {
+          temp[j][k] -= temp[i][k] * t;
+          inverse[j * 4 + k] -= inverse[i * 4 + k] * t;
+        }
+      }
+    }
+  }
+  return 1;
+}
+
+/*
+   ** This is a screwball function.  What it does is the following:
+   ** Given screen x and y coordinates, compute the corresponding object space 
+   **   x and y coordinates given that the object space z is 0.9 + OFFSETZ.
+   ** Since the tops of (most) pieces are at z = 0.9 + OFFSETZ, we use that 
+   **   number.
+ */
+int
+computeCoords(int piece, int mousex, int mousey,
+  GLfloat * selx, GLfloat * sely)
+{
+  GLfloat modelMatrix[16];
+  GLfloat projMatrix[16];
+  GLfloat finalMatrix[16];
+  GLfloat in[4];
+  GLfloat a, b, c, d;
+  GLfloat top, bot;
+  GLfloat z;
+  GLfloat w;
+  GLfloat height;
+
+  if (piece == 0)
+    return 0;
+  height = zsize[piece] - 0.1 + OFFSETZ;
+
+  glGetFloatv(GL_PROJECTION_MATRIX, projMatrix);
+  glGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix);
+  multMatrices(modelMatrix, projMatrix, finalMatrix);
+  if (!invertMatrix(finalMatrix, finalMatrix))
+    return 0;
+
+  in[0] = (2.0 * (mousex - viewport[0]) / viewport[2]) - 1;
+  in[1] = (2.0 * ((H - mousey) - viewport[1]) / viewport[3]) - 1;
+
+  a = in[0] * finalMatrix[0 * 4 + 2] +
+    in[1] * finalMatrix[1 * 4 + 2] +
+    finalMatrix[3 * 4 + 2];
+  b = finalMatrix[2 * 4 + 2];
+  c = in[0] * finalMatrix[0 * 4 + 3] +
+    in[1] * finalMatrix[1 * 4 + 3] +
+    finalMatrix[3 * 4 + 3];
+  d = finalMatrix[2 * 4 + 3];
+
+  /* 
+     ** Ok, now we need to solve for z: **   (a + b z) / (c + d 
+
+     z) = height. ** ("height" is the height in object space we 
+
+     want to solve z for) ** ** ==>  a + b z = height c +
+     height d z **      bz - height d z = height c - a ** z =
+     (height c - a) / (b - height d) */
+  top = height * c - a;
+  bot = b - height * d;
+  if (bot == 0.0)
+    return 0;
+
+  z = top / bot;
+
+  /* 
+     ** Ok, no problem. ** Now we solve for x and y.  We know
+     that w = c + d z, so we compute it. */
+  w = c + d * z;
+
+  /* 
+     ** Now for x and y: */
+  *selx = (in[0] * finalMatrix[0 * 4 + 0] +
+    in[1] * finalMatrix[1 * 4 + 0] +
+    z * finalMatrix[2 * 4 + 0] +
+    finalMatrix[3 * 4 + 0]) / w - OFFSETX;
+  *sely = (in[0] * finalMatrix[0 * 4 + 1] +
+    in[1] * finalMatrix[1 * 4 + 1] +
+    z * finalMatrix[2 * 4 + 1] +
+    finalMatrix[3 * 4 + 1]) / w - OFFSETY;
+  return 1;
+}
+
+static int selected;
+static int selectx, selecty;
+static float selstartx, selstarty;
+
+void
+grabPiece(int piece, float selx, float sely)
+{
+  int hit;
+
+  selectx = int(selx);
+  selecty = int(sely);
+  if (selectx < 0 || selecty < 0 || selectx >= WIDTH || selecty >= HEIGHT) {
+    return;
+  }
+  hit = thePuzzle[selecty][selectx];
+  if (hit != piece)
+    return;
+  if (hit) {
+    movingPiece = hit;
+    while (selectx > 0 && thePuzzle[selecty][selectx - 1] == movingPiece) {
+      selectx--;
+    }
+    while (selecty > 0 && thePuzzle[selecty - 1][selectx] == movingPiece) {
+      selecty--;
+    }
+    move_x = selectx;
+    move_y = selecty;
+    selected = 1;
+    selstartx = selx;
+    selstarty = sely;
+  } else {
+    selected = 0;
+  }
+  changeState();
+}
+
+void
+moveSelection(float selx, float sely)
+{
+  float deltax, deltay;
+  int dir;
+  Config newpieces;
+
+  if (!selected)
+    return;
+  deltax = selx - selstartx;
+  deltay = sely - selstarty;
+
+  if (fabs(deltax) > fabs(deltay)) {
+    deltay = 0;
+    if (deltax > 0) {
+      if (deltax > 1)
+        deltax = 1;
+      dir = 2;
+    } else {
+      if (deltax < -1)
+        deltax = -1;
+      dir = 0;
+    }
+  } else {
+    deltax = 0;
+    if (deltay > 0) {
+      if (deltay > 1)
+        deltay = 1;
+      dir = 3;
+    } else {
+      if (deltay < -1)
+        deltay = -1;
+      dir = 1;
+    }
+  }
+  if (canmove(thePuzzle, selectx, selecty, dir, newpieces)) {
+    move_x = deltax + selectx;
+    move_y = deltay + selecty;
+    if (deltax > 0.5) {
+      memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
+      selectx++;
+      selstartx++;
+    } else if (deltax < -0.5) {
+      memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
+      selectx--;
+      selstartx--;
+    } else if (deltay > 0.5) {
+      memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
+      selecty++;
+      selstarty++;
+    } else if (deltay < -0.5) {
+      memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
+      selecty--;
+      selstarty--;
+    }
+  } else {
+    if (deltay > 0 && thePuzzle[selecty][selectx] == 10 &&
+      selectx == 1 && selecty == 3) {
+      /* Allow visual movement of solution piece outside of the 
+
+         box */
+      move_x = selectx;
+      move_y = sely - selstarty + selecty;
+    } else {
+      move_x = selectx;
+      move_y = selecty;
+    }
+  }
+}
+
+void
+dropSelection(void)
+{
+  if (!selected)
+    return;
+  movingPiece = 0;
+  selected = 0;
+  changeState();
+}
+
+static int left_mouse, middle_mouse;
+static int mousex, mousey;
+static int solving;
+static int spinning;
+static float lastquat[4];
+static int sel_piece;
+
+static void
+Reshape(int width, int height)
+{
+
+  W = width;
+  H = height;
+  glViewport(0, 0, W, H);
+  glGetIntegerv(GL_VIEWPORT, viewport);
+}
+
+void
+toggleSolve(void)
+{
+    if (solving) {
+      freeSolutions();
+      solving = 0;
+      glutChangeToMenuEntry(1, "Solving", 1);
+      glutSetWindowTitle("glpuzzle");
+      movingPiece = 0;
+    } else {
+      glutChangeToMenuEntry(1, "Stop solving", 1);
+      glutSetWindowTitle("Solving...");
+      if (solvePuzzle()) {
+        solving = 1;
+      }
+    }
+    changeState();
+    glutPostRedisplay();
+}
+
+void reset(void)
+{
+    if (solving) {
+      freeSolutions();
+      solving = 0;
+      glutChangeToMenuEntry(1, "Solving", 1);
+      glutSetWindowTitle("glpuzzle");
+      movingPiece = 0;
+      changeState();
+    }
+    memcpy(thePuzzle, startConfig, HEIGHT * WIDTH);
+    glutPostRedisplay();
+}
+
+void
+keyboard(unsigned char c, int x, int y)
+{
+  int piece;
+
+  switch (c) {
+  case 27:
+    exit(0);
+    break;
+  case 'D':
+  case 'd':
+    if (solving) {
+      freeSolutions();
+      solving = 0;
+      glutChangeToMenuEntry(1, "Solving", 1);
+      glutSetWindowTitle("glpuzzle");
+      movingPiece = 0;
+      changeState();
+    }
+    piece = selectPiece(x, y);
+    if (piece) {
+      nukePiece(piece);
+    }
+    glutPostRedisplay();
+    break;
+  case 'R':
+  case 'r':
+    reset();
+    break;
+  case 'S':
+  case 's':
+    toggleSolve();
+    break;
+  case 'b':
+  case 'B':
+    depth = 1 - depth;
+    if (depth) {
+      glEnable(GL_DEPTH_TEST);
+    } else {
+      glDisable(GL_DEPTH_TEST);
+    }
+    glutPostRedisplay();
+    break;
+  default:
+    break;
+  }
+}
+
+void
+motion(int x, int y)
+{
+  float selx, sely;
+
+  if (middle_mouse && !left_mouse) {
+    if (mousex != x || mousey != y) {
+      trackball(lastquat,
+        (2.0*mousex - W) / W,
+        (H - 2.0*mousey) / H,
+        (2.0*x - W) / W,
+        (H - 2.0*y) / H);
+      spinning = 1;
+    } else {
+      spinning = 0;
+    }
+    changeState();
+  } else {
+    computeCoords(sel_piece, x, y, &selx, &sely);
+    moveSelection(selx, sely);
+  }
+  mousex = x;
+  mousey = y;
+  glutPostRedisplay();
+}
+
+void
+mouse(int b, int s, int x, int y)
+{
+  float selx, sely;
+
+  mousex = x;
+  mousey = y;
+  curX = x;
+  curY = y;
+  if (s == GLUT_DOWN) {
+    switch (b) {
+    case GLUT_LEFT_BUTTON:
+      if (solving) {
+        freeSolutions();
+        solving = 0;
+      glutChangeToMenuEntry(1, "Solving", 1);
+        glutSetWindowTitle("glpuzzle");
+        movingPiece = 0;
+      }
+      left_mouse = GL_TRUE;
+      sel_piece = selectPiece(mousex, mousey);
+      if (computeCoords(sel_piece, mousex, mousey, &selx, &sely)) {
+        grabPiece(sel_piece, selx, sely);
+      }
+      glutPostRedisplay();
+      break;
+    case GLUT_MIDDLE_BUTTON:
+      middle_mouse = GL_TRUE;
+      glutPostRedisplay();
+      break;
+    }
+  } else {
+    switch (b) {
+    case GLUT_LEFT_BUTTON:
+      left_mouse = GL_FALSE;
+      dropSelection();
+      glutPostRedisplay();
+      break;
+    case GLUT_MIDDLE_BUTTON:
+      middle_mouse = GL_FALSE;
+      glutPostRedisplay();
+      break;
+    }
+  }
+  motion(x, y);
+}
+
+void
+animate(void)
+{
+  if (spinning) {
+    add_quats(lastquat, curquat, curquat);
+  }
+  glutPostRedisplay();
+  if (solving) {
+    if (!continueSolving()) {
+      solving = 0;
+      glutChangeToMenuEntry(1, "Solving", 1);
+      glutSetWindowTitle("glpuzzle");
+    }
+  }
+  if (!solving && !spinning && !visible) {
+    glutIdleFunc(NULL);
+  }
+}
+
+void
+changeState(void)
+{
+  if (visible) {
+    if (!solving && !spinning) {
+      glutIdleFunc(NULL);
+    } else {
+      glutIdleFunc(animate);
+    }
+  } else {
+    glutIdleFunc(NULL);
+  }
+}
+
+void
+init(void)
+{
+  static float lmodel_ambient[] =
+  {0.0, 0.0, 0.0, 0.0};
+  static float lmodel_twoside[] =
+  {GL_FALSE};
+  static float lmodel_local[] =
+  {GL_FALSE};
+  static float light0_ambient[] =
+  {0.1, 0.1, 0.1, 1.0};
+  static float light0_diffuse[] =
+  {1.0, 1.0, 1.0, 0.0};
+  static float light0_position[] =
+  {0.8660254, 0.5, 1, 0};
+  static float light0_specular[] =
+  {0.0, 0.0, 0.0, 0.0};
+  static float bevel_mat_ambient[] =
+  {0.0, 0.0, 0.0, 1.0};
+  static float bevel_mat_shininess[] =
+  {40.0};
+  static float bevel_mat_specular[] =
+  {0.0, 0.0, 0.0, 0.0};
+  static float bevel_mat_diffuse[] =
+  {1.0, 0.0, 0.0, 0.0};
+
+  glEnable(GL_CULL_FACE);
+  glCullFace(GL_BACK);
+  glEnable(GL_DEPTH_TEST);
+  glClearDepth(1.0);
+
+  glClearColor(0.5, 0.5, 0.5, 0.0);
+  glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
+  glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
+  glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
+  glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
+  glEnable(GL_LIGHT0);
+
+  glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_local);
+  glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
+  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
+  glEnable(GL_LIGHTING);
+
+  glMaterialfv(GL_FRONT, GL_AMBIENT, bevel_mat_ambient);
+  glMaterialfv(GL_FRONT, GL_SHININESS, bevel_mat_shininess);
+  glMaterialfv(GL_FRONT, GL_SPECULAR, bevel_mat_specular);
+  glMaterialfv(GL_FRONT, GL_DIFFUSE, bevel_mat_diffuse);
+
+  glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+  glEnable(GL_COLOR_MATERIAL);
+  glShadeModel(GL_FLAT);
+
+  trackball(curquat, 0.0, 0.0, 0.0, 0.0);
+  srandom(time(NULL));
+}
+
+static void
+Usage(void)
+{
+  printf("Usage: puzzle [-s]\n");
+  printf("   -s:  Run in single buffered mode\n");
+  exit(-1);
+}
+
+void
+visibility(int v)
+{
+  if (v == GLUT_VISIBLE) {
+    visible = 1;
+  } else {
+    visible = 0;
+  }
+  changeState();
+}
+
+void
+menu(int choice)
+{
+   switch(choice) {
+   case 1:
+      toggleSolve();
+      break;
+   case 2:
+      reset();
+      break;
+   case 3:
+      exit(0);
+      break;
+   }
+}
+
+int
+main(int argc, char **argv)
+{
+  long i;
+
+  glutInit(&argc, argv);
+  for (i = 1; i < argc; i++) {
+    if (argv[i][0] == '-') {
+      switch (argv[i][1]) {
+      case 's':
+        doubleBuffer = 0;
+        break;
+      default:
+        Usage();
+      }
+    } else {
+      Usage();
+    }
+  }
+
+  glutInitWindowSize(W, H);
+  if (doubleBuffer) {
+    glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE);
+  } else {
+    glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_SINGLE | GLUT_MULTISAMPLE);
+  }
+
+  glutCreateWindow("glpuzzle");
+  visible = 1; // added for fltk, bug in original program?
+
+  init();
+
+  glGetIntegerv(GL_VIEWPORT, viewport);
+
+  printf("\n");
+  printf("r   Reset puzzle\n");
+  printf("s   Solve puzzle (may take a few seconds to compute)\n");
+  printf("d   Destroy a piece - makes the puzzle easier\n");
+  printf("b   Toggles the depth buffer on and off\n");
+  printf("\n");
+  printf("Left mouse moves pieces\n");
+  printf("Middle mouse spins the puzzle\n");
+  printf("Right mouse has menu\n");
+
+  glutReshapeFunc(Reshape);
+  glutDisplayFunc(redraw);
+  glutKeyboardFunc(keyboard);
+  glutMotionFunc(motion);
+  glutMouseFunc(mouse);
+  glutVisibilityFunc(visibility);
+  glutCreateMenu(menu);
+  glutAddMenuEntry("Solve", 1);
+  glutAddMenuEntry("Reset", 2);
+  glutAddMenuEntry("Quit", 3);
+  glutAttachMenu(GLUT_RIGHT_BUTTON);
+  glutMainLoop();
+  return 0;             /* ANSI C requires main to return int. */
+}
+
+#endif // added for fltk's distribution
+
diff --git a/test/hello.cxx b/test/hello.cxx
new file mode 100644
index 000000000..eb6adb082
--- /dev/null
+++ b/test/hello.cxx
@@ -0,0 +1,16 @@
+/* 	Example program from the documentation	*/
+
+#include 
+#include 
+#include 
+
+int main(int argc, char **argv) {
+  Fl_Window *window = new Fl_Window(300,180);
+  Fl_Box *box = new Fl_Box(FL_UP_BOX,20,40,260,100,"Hello, World!");
+  box->labelfont(FL_BOLD+FL_ITALIC);
+  box->labelsize(36);
+  box->labeltype(FL_SHADOW_LABEL);
+  window->end();
+  window->show(argc, argv);
+  return Fl::run();
+}
diff --git a/test/iconize.cxx b/test/iconize.cxx
new file mode 100644
index 000000000..5511ac66a
--- /dev/null
+++ b/test/iconize.cxx
@@ -0,0 +1,54 @@
+// Fl_Window::iconize() test
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+void iconize_cb(Fl_Widget *, void *v) {
+  Fl_Window *w = (Fl_Window *)v;
+  w->iconize();
+}
+
+void show_cb(Fl_Widget *, void *v) {
+  Fl_Window *w = (Fl_Window *)v;
+  w->show();
+}
+
+void hide_cb(Fl_Widget *, void *v) {
+  Fl_Window *w = (Fl_Window *)v;
+  w->hide();
+}
+
+void window_cb(Fl_Widget*, void*) {
+  exit(0);
+}
+
+int main(int argc, char **argv) {
+
+  Fl_Window mainw(200,200);
+  mainw.end();
+  mainw.show(argc,argv);
+
+  Fl_Window control(120,120);
+
+  Fl_Button hide_button(0,0,120,30,"hide()");
+  hide_button.callback(hide_cb, &mainw);
+
+  Fl_Button iconize_button(0,30,120,30,"iconize()");
+  iconize_button.callback(iconize_cb, &mainw);
+
+  Fl_Button show_button(0,60,120,30,"show()");
+  show_button.callback(show_cb, &mainw);
+
+  Fl_Button show_button2(0,90,120,30,"show this");
+  show_button2.callback(show_cb, &control);
+
+  //  Fl_Box box(FL_NO_BOX,0,60,120,30,"Also try running\nwith -i switch");
+
+  control.end();
+  control.show();
+  control.callback(window_cb);
+  return Fl::run();
+}
diff --git a/test/image.cxx b/test/image.cxx
new file mode 100644
index 000000000..3a2e79c44
--- /dev/null
+++ b/test/image.cxx
@@ -0,0 +1,108 @@
+// Test of class Fl_Image
+//
+// Notice that Fl_Image is for a static, multiple-reuse image, such
+// as an icon or postage stamp.  Use fl_draw_image to go directly
+// from an buffered image that changes often.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int width = 75;
+int height = 75;
+uchar *image;
+
+void make_image() {
+  image = new uchar[3*width*height];
+  uchar *p = image;
+  for (int y = 0; y < height; y++) {
+    double Y = double(y)/(height-1);
+    for (int x = 0; x < width; x++) {
+      double X = double(x)/(width-1);
+      *p++ = uchar(255*((1-X)*(1-Y))); // red in upper-left
+      *p++ = uchar(255*((1-X)*Y));	// green in lower-left
+      *p++ = uchar(255*(X*Y));	// blue in lower-right
+    }
+  }
+}
+
+#include 
+
+Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb;
+Fl_Button *b;
+Fl_Window *w;
+
+void button_cb(Fl_Widget *,void *) {
+    int i = 0;
+    if (leftb->value()) i |= FL_ALIGN_LEFT;
+    if (rightb->value()) i |= FL_ALIGN_RIGHT;
+    if (topb->value()) i |= FL_ALIGN_TOP;
+    if (bottomb->value()) i |= FL_ALIGN_BOTTOM;
+    if (insideb->value()) i |= FL_ALIGN_INSIDE;
+    b->align(i);
+    w->redraw();
+}
+
+#include 
+#include "list_visuals.C"
+
+int visid = -1;
+int arg(int argc, char **argv, int &i) {
+  if (argv[i][1] == 'v') {
+    if (i+1 >= argc) return 0;
+    visid = atoi(argv[i+1]);
+    i += 2;
+    return 2;
+  }
+  return 0;
+}
+
+int main(int argc, char **argv) {
+
+#ifndef WIN32
+  int i = 1;
+  if (Fl::args(argc,argv,i,arg) < argc) {
+    fprintf(stderr," -v # : use visual\n%s\n",Fl::help);
+    exit(1);
+  }
+
+  if (visid >= 0) {
+    fl_open_display();
+    XVisualInfo templt; int num;
+    templt.visualid = visid;
+    fl_visual = XGetVisualInfo(fl_display, VisualIDMask, &templt, &num);
+    if (!fl_visual) {
+      fprintf(stderr, "No visual with id %d, use one of:\n",visid);
+      list_visuals();
+      exit(1);
+    }
+    fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen),
+				fl_visual->visual, AllocNone);
+    fl_xpixel(FL_BLACK); // make sure black is allocated in overlay visuals
+  } else {
+    Fl::visual(FL_RGB);
+  }
+#endif
+
+  Fl_Window window(400,400); ::w = &window;
+  Fl_Button b(140,160,120,120,0); ::b = &b;
+  make_image();
+  (new Fl_Image(image, width, height))->label(&b);
+  leftb = new Fl_Toggle_Button(50,75,50,25,"left");
+  leftb->callback(button_cb);
+  rightb = new Fl_Toggle_Button(100,75,50,25,"right");
+  rightb->callback(button_cb);
+  topb = new Fl_Toggle_Button(150,75,50,25,"top");
+  topb->callback(button_cb);
+  bottomb = new Fl_Toggle_Button(200,75,50,25,"bottom");
+  bottomb->callback(button_cb);
+  insideb = new Fl_Toggle_Button(250,75,50,25,"inside");
+  insideb->callback(button_cb);
+  window.resizable(window);
+  window.end();
+  window.show(argc, argv);
+  return Fl::run();
+}
diff --git a/test/inactive.C b/test/inactive.C
new file mode 100644
index 000000000..f78782124
--- /dev/null
+++ b/test/inactive.C
@@ -0,0 +1,99 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "inactive.H"
+
+Fl_Group *the_group;
+
+Fl_Menu_Item menu_menu[] = {
+ {"item", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"item", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"item", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"item", 0,  0, 0, 0, 0, 3, 14, 0},
+ {"item", 0,  0, 0, 0, 0, 3, 14, 0},
+ {0}
+};
+
+static void cb_active(Fl_Button*, void*) {
+  the_group->activate();
+}
+
+static void cb_inactive(Fl_Button*, void*) {
+  the_group->deactivate();
+}
+
+int main(int argc, char **argv) {
+  Fl_Window *w;
+  { Fl_Window* o = w = new Fl_Window(420, 295);
+    { Fl_Group* o = the_group = new Fl_Group(25, 25, 375, 235, "activate()/deactivate() called on this Fl_Group");
+      o->box(FL_ENGRAVED_FRAME);
+      o->align(17);
+      new Fl_Button(50, 50, 105, 25, "button");
+      { Fl_Group* o = new Fl_Group(50, 100, 105, 85, "Child group");
+        o->box(FL_DOWN_FRAME);
+        { Fl_Check_Button* o = new Fl_Check_Button(50, 100, 105, 25, "red");
+          o->type(102);
+          o->down_box(FL_DIAMOND_DOWN_BOX);
+          o->labelcolor(1);
+        }
+        { Fl_Check_Button* o = new Fl_Check_Button(50, 120, 105, 25, "green");
+          o->type(102);
+          o->down_box(FL_DIAMOND_DOWN_BOX);
+          o->selection_color(2);
+          o->labelcolor(2);
+        }
+        { Fl_Check_Button* o = new Fl_Check_Button(50, 140, 105, 25, "blue");
+          o->type(102);
+          o->down_box(FL_DIAMOND_DOWN_BOX);
+          o->selection_color(4);
+          o->labelcolor(4);
+        }
+        { Fl_Check_Button* o = new Fl_Check_Button(50, 160, 105, 25, "white");
+          o->type(102);
+          o->down_box(FL_DIAMOND_DOWN_BOX);
+          o->selection_color(7);
+          o->labelcolor(7);
+        }
+        o->end();
+      }
+      { Fl_Slider* o = new Fl_Slider(165, 50, 24, 150, "Fl_Slider");
+        o->value(0.5);
+      }
+      { Fl_Input* o = new Fl_Input(195, 50, 195, 30);
+        o->static_value("Fl_Input");
+      }
+      { Fl_Menu_Button* o = new Fl_Menu_Button(235, 105, 110, 30, "menu");
+        o->menu(menu_menu);
+      }
+      { Fl_Box* o = new Fl_Box(240, 205, 145, 50, "Fl_Box");
+        o->box(FL_EMBOSSED_FRAME);
+        o->labeltype(FL_SHADOW_LABEL);
+        o->labelfont(3);
+        o->labelsize(38);
+      }
+      { Fl_Value_Output* o = new Fl_Value_Output(255, 165, 130, 30, "value:");
+        o->maximum(10000);
+        o->step(1);
+        o->textfont(5);
+        o->textsize(24);
+        o->textcolor(4);
+      }
+      { Fl_Scrollbar* o = new Fl_Scrollbar(40, 220, 180, 20, "scrollbar");
+        o->type(1);
+        o->maximum(100);
+      }
+      o->end();
+    }
+    { Fl_Button* o = new Fl_Button(25, 265, 185, 25, "active");
+      o->type(102);
+      o->value(1);
+      o->callback((Fl_Callback*)cb_active);
+    }
+    { Fl_Button* o = new Fl_Button(220, 265, 180, 25, "inactive");
+      o->type(102);
+      o->callback((Fl_Callback*)cb_inactive);
+    }
+    o->end();
+  }
+  w->show(argc, argv);
+  return Fl::run();
+}
diff --git a/test/inactive.H b/test/inactive.H
new file mode 100644
index 000000000..c811f6c2f
--- /dev/null
+++ b/test/inactive.H
@@ -0,0 +1,15 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+extern Fl_Group *the_group;
+extern Fl_Menu_Item menu_menu[];
diff --git a/test/inactive.fl b/test/inactive.fl
new file mode 100644
index 000000000..0335158a8
--- /dev/null
+++ b/test/inactive.fl
@@ -0,0 +1,99 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 0.99 
+header_name {.H} 
+code_name {.C} 
+gridx 5 
+gridy 5 
+snap 3
+Function {} {open
+} {
+  Fl_Window {} {open
+    xywh {470 454 420 295} visible
+  } {
+    Fl_Group the_group {
+      label {activate()/deactivate() called on this Fl_Group} open
+      xywh {25 25 375 235} box ENGRAVED_FRAME align 17
+    } {
+      Fl_Button {} {
+        label button
+        xywh {50 50 105 25}
+      }
+      Fl_Group {} {
+        label {Child group} open
+        xywh {50 100 105 85} box DOWN_FRAME
+      } {
+        Fl_Check_Button {} {
+          label red
+          xywh {50 100 105 25} type Radio down_box DIAMOND_DOWN_BOX labelcolor 1
+        }
+        Fl_Check_Button {} {
+          label green
+          xywh {50 120 105 25} type Radio down_box DIAMOND_DOWN_BOX selection_color 2 labelcolor 2
+        }
+        Fl_Check_Button {} {
+          label blue
+          xywh {50 140 105 25} type Radio down_box DIAMOND_DOWN_BOX selection_color 4 labelcolor 4
+        }
+        Fl_Check_Button {} {
+          label white
+          xywh {50 160 105 25} type Radio down_box DIAMOND_DOWN_BOX selection_color 7 labelcolor 7
+        }
+      }
+      Fl_Slider {} {
+        label Fl_Slider
+        xywh {165 50 24 150} value 0.5
+      }
+      Fl_Input {} {
+        xywh {195 50 195 30}
+        code0 {o->static_value("Fl_Input");}
+      }
+      Fl_Menu_Button {} {
+        label menu open
+        xywh {235 105 110 30}
+      } {
+        menuitem {} {
+          label item
+          xywh {0 0 100 20}
+        }
+        menuitem {} {
+          label item
+          xywh {10 10 100 20}
+        }
+        menuitem {} {
+          label item
+          xywh {20 20 100 20}
+        }
+        menuitem {} {
+          label item
+          xywh {30 30 100 20}
+        }
+        menuitem {} {
+          label item
+          xywh {40 40 100 20}
+        }
+      }
+      Fl_Box {} {
+        label Fl_Box
+        xywh {240 205 145 50} box EMBOSSED_FRAME labeltype SHADOW_LABEL labelfont 3 labelsize 38
+      }
+      Fl_Value_Output {} {
+        label {value:}
+        xywh {255 165 130 30} maximum 10000 step 1 textfont 5 textsize 24 textcolor 4
+      }
+      Fl_Scrollbar {} {
+        label scrollbar selected
+        xywh {40 220 180 20} type Horizontal maximum 100
+      }
+    }
+    Fl_Button {} {
+      label active
+      callback {the_group->activate();}
+      xywh {25 265 185 25} type Radio value 1
+    }
+    Fl_Button {} {
+      label inactive
+      callback {the_group->deactivate();}
+      xywh {220 265 180 25} type Radio
+    }
+  }
+} 
diff --git a/test/input.cxx b/test/input.cxx
new file mode 100644
index 000000000..a29d82b58
--- /dev/null
+++ b/test/input.cxx
@@ -0,0 +1,92 @@
+/* 	Test input fields	*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+void cb(Fl_Widget *ob) {
+  printf("Callback for %s\n",ob->label());
+}
+
+int when = 0;
+Fl_Input *input[5];
+
+void toggle_cb(Fl_Widget *o, long v) {
+  if (((Fl_Toggle_Button*)o)->value()) when |= v; else when &= ~v;
+  for (int i=0; i<5; i++) input[i]->when(when);
+}
+
+void test(Fl_Input *i) {
+  if (i->changed()) {i->clear_changed(); printf("%s\n",i->label());}
+}
+
+void button_cb(Fl_Widget *,void *) {
+  for (int i=0; i<5; i++) test(input[i]);
+}
+
+void color_cb(Fl_Widget* button, void* v) {
+  Fl_Color c;
+  switch ((int)v) {
+  case 0: c = FL_WHITE; break;
+  case 1: c = FL_SELECTION_COLOR; break;
+  default: c = FL_BLACK; break;
+  }
+  uchar r,g,b; Fl::get_color(c, r,g,b);
+  if (fl_color_chooser(0,r,g,b)) {
+    Fl::set_color(c,r,g,b); Fl::redraw();
+    button->labelcolor(contrast(FL_BLACK,c));
+    button->redraw();
+  }
+}
+
+int main(int argc, char **argv) {
+  Fl_Window *window = new Fl_Window(400,400);
+
+  int y = 10;
+  input[0] = new Fl_Input(70,y,300,30,"Normal:"); y += 35;
+  // input[0]->cursor_color(FL_SELECTION_COLOR);
+  //  input[0]->maximum_size(20);
+  // input[0]->static_value("this is a testgarbage");
+  input[1] = new Fl_Float_Input(70,y,300,30,"Float:"); y += 35;
+  input[2] = new Fl_Int_Input(70,y,300,30,"Int:"); y += 35;
+  input[3] = new Fl_Secret_Input(70,y,300,30,"Secret:"); y += 35;
+  input[4] = new Fl_Multiline_Input(70,y,300,100,"Multiline:"); y += 105;
+
+  for (int i = 0; i < 4; i++) {
+    input[i]->when(0); input[i]->callback(cb);
+  }
+  int y1 = y;
+
+  Fl_Button *b;
+  b = new Fl_Toggle_Button(10,y,200,25,"FL_WHEN_&CHANGED");
+  b->callback(toggle_cb, FL_WHEN_CHANGED); y += 25;
+  b = new Fl_Toggle_Button(10,y,200,25,"FL_WHEN_&RELEASE");
+  b->callback(toggle_cb, FL_WHEN_RELEASE); y += 25;
+  b = new Fl_Toggle_Button(10,y,200,25,"FL_WHEN_&ENTER_KEY");
+  b->callback(toggle_cb, FL_WHEN_ENTER_KEY); y += 25;
+  b = new Fl_Toggle_Button(10,y,200,25,"FL_WHEN_&NOT_CHANGED");
+  b->callback(toggle_cb, FL_WHEN_NOT_CHANGED); y += 25;
+  y += 5;
+  b = new Fl_Button(10,y,200,25,"&print changed()");
+  b->callback(button_cb);
+
+  b = new Fl_Button(220,y1,100,25,"color"); y1 += 25;
+  b->color(input[0]->color()); b->callback(color_cb, (void*)0);
+  b = new Fl_Button(220,y1,100,25,"selection_color"); y1 += 25;
+  b->color(input[0]->selection_color()); b->callback(color_cb, (void*)1);
+  b = new Fl_Button(220,y1,100,25,"textcolor"); y1 += 25;
+  b->color(input[0]->textcolor()); b->callback(color_cb, (void*)2);
+  b->labelcolor(contrast(FL_BLACK,b->color()));
+
+  window->end();
+  window->show(argc,argv);
+  return Fl::run();
+}
diff --git a/test/jpeg_image.cxx b/test/jpeg_image.cxx
new file mode 100644
index 000000000..c788250fb
--- /dev/null
+++ b/test/jpeg_image.cxx
@@ -0,0 +1,179 @@
+/* 	Test fl_draw_image.
+
+	Be sure to try every visual with the -v switch and try
+	-m (monochrome) on each of them.
+
+	This program requires either the libjpeg.a library or
+	an internal DD library to read images (this is chosen
+	by the presence of the "DD" #define).
+
+	To get the jpeg library:
+
+The "official" archive site for this software is ftp.uu.net (Internet
+address 192.48.96.9).  The most recent released version can always be found
+there in directory graphics/jpeg.  This particular version will be archived
+as graphics/jpeg/jpegsrc.v6a.tar.gz.
+
+	The makefile assummes you decompressed and build these
+	in a directory called "jpeg-6a" in the same location as the
+	"FL" directory.
+
+*/
+
+#include 
+#include 
+#include 
+#include 
+
+void readtheimage(const char *name); // below
+int width;
+int height;
+int depth;
+int linedelta;
+uchar *ibuffer;
+
+////////////////////////////////////////////////////////////////
+
+#include 
+int mono;
+
+class image_window : public Fl_Window {
+  void draw();
+public:
+  image_window(int w,int h) : Fl_Window(w,h) {box(FL_NO_BOX);}
+};
+
+void image_window::draw() {
+  if (mono)
+    fl_draw_image_mono(ibuffer+1,0,0,width,height,depth,linedelta);
+  else
+    fl_draw_image(ibuffer,0,0,width,height,depth,linedelta);
+}
+
+////////////////////////////////////////////////////////////////
+
+#include 
+#include "list_visuals.C"
+
+////////////////////////////////////////////////////////////////
+
+int visid = -1;
+int arg(int argc, char **argv, int &i) {
+  if (argv[i][1] == 'm') {mono = 1; i++; return 1;}
+
+  if (argv[i][1] == 'v') {
+    if (i+1 >= argc) return 0;
+    visid = atoi(argv[i+1]);
+    i += 2;
+    return 2;
+  }
+
+  return 0;
+}
+
+int main(int argc, char ** argv) {
+
+  int i = 1;
+  if (!Fl::args(argc,argv,i,arg) || i != argc-1) {
+    fprintf(stderr,"usage: %s  image_file\n"
+" -v # : use visual\n"
+" -m : monochrome\n"
+"%s\n",
+	    argv[0],Fl::help);
+    exit(1);
+  }
+
+  readtheimage(argv[i]);
+  image_window *window = new image_window(width,height);
+
+  if (visid>=0) {
+    fl_open_display();
+    XVisualInfo templt; int num;
+    templt.visualid = visid;
+    fl_visual = XGetVisualInfo(fl_display, VisualIDMask, &templt, &num);
+    if (!fl_visual) {
+      fprintf(stderr, "No visual with id %d, use one of:\n",visid);
+      list_visuals();
+      exit(1);
+    }
+    fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen),
+				fl_visual->visual, AllocNone);
+    fl_xpixel(FL_BLACK); // make sure black is allocated
+  }
+
+  window->show(argc,argv);
+  return Fl::run();
+}
+
+////////////////////////////////////////////////////////////////
+#ifndef DD_LIBRARY
+// Read using jpeg library:
+
+extern "C" {
+#include "jpeglib.h"
+}
+
+void readtheimage(const char *name) {
+  struct jpeg_decompress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  FILE * infile = fopen(name, "rb");
+  if (!infile) {
+    fprintf(stderr, "can't open %s\n", name);
+    exit(1);
+  }
+  cinfo.err = jpeg_std_error(&jerr);
+  jpeg_create_decompress(&cinfo);
+  jpeg_stdio_src(&cinfo, infile);
+  jpeg_read_header(&cinfo, TRUE);
+  jpeg_start_decompress(&cinfo);
+  width = cinfo.output_width;
+  height = cinfo.output_height;
+  depth = cinfo.output_components;
+  ibuffer = new uchar[width*height*depth];
+  uchar *rp = ibuffer;
+  //  for (int i=0; i= ibuffer; p-=4) {
+    uchar r = p[3];
+    uchar g = p[2];
+    uchar b = p[1];
+    uchar a = p[0];
+    p[0] = r;
+    p[1] = g;
+    p[2] = b;
+    p[3] = a;
+  }
+  // make it bottom-to-top:
+  ibuffer = ibuffer + width*(height-1)*depth;
+  linedelta = -(width*depth);
+}
+#endif
+
diff --git a/test/keyboard.cxx b/test/keyboard.cxx
new file mode 100644
index 000000000..6f6fd58a3
--- /dev/null
+++ b/test/keyboard.cxx
@@ -0,0 +1,102 @@
+// Continuously display FLTK's event state.
+
+// Known bugs:
+
+// X insists on reporting the state *before* the shift key was
+// pressed, rather than after, on shift key events.  I fixed this for
+// the mouse buttons, but it did not seem worth it for shift.
+
+// X servers do not agree about any shift flags after except shift, ctrl,
+// lock, and alt.  They may also not agree about the symbols for the extra
+// keys Micro$oft put on the keyboard.
+
+// On Irix the backslash key does not work.  A bug in XKeysymToKeycode?
+
+#include "keyboard_ui.C"
+#include 
+
+// these are used to identify which buttons are which:
+void key_cb(Fl_Button*, void*) {}
+void shift_cb(Fl_Button*, void*) {}
+
+// this is used to stop Esc from exiting the program:
+int handle(int e) {
+  return (e == FL_SHORTCUT); // eat all keystrokes
+}
+
+struct {int n; const char* text;} table[] = {
+  {FL_Escape, "FL_Escape"},
+  {FL_BackSpace, "FL_BackSpace"},
+  {FL_Tab, "FL_Tab"},
+  {FL_Enter, "FL_Enter"},
+  {FL_Print, "FL_Print"},
+  {FL_Scroll_Lock, "FL_Scroll_Lock"},
+  {FL_Pause, "FL_Pause"},
+  {FL_Insert, "FL_Insert"},
+  {FL_Home, "FL_Home"},
+  {FL_Page_Up, "FL_Page_Up"},
+  {FL_Delete, "FL_Delete"},
+  {FL_End, "FL_End"},
+  {FL_Page_Down, "FL_Page_Down"},
+  {FL_Left, "FL_Left"},
+  {FL_Up, "FL_Up"},
+  {FL_Right, "FL_Right"},
+  {FL_Down, "FL_Down"},
+  {FL_Shift_L, "FL_Shift_L"},
+  {FL_Shift_R, "FL_Shift_R"},
+  {FL_Control_L, "FL_Control_L"},
+  {FL_Control_R, "FL_Control_R"},
+  {FL_Caps_Lock, "FL_Caps_Lock"},
+  {FL_Alt_L, "FL_Alt_L"},
+  {FL_Alt_R, "FL_Alt_R"},
+  {FL_Meta_L, "FL_Meta_L"},
+  {FL_Meta_R, "FL_Meta_R"},
+  {FL_Menu, "FL_Menu"},
+  {FL_Num_Lock, "FL_Num_Lock"},
+  {FL_KP_Enter, "FL_KP_Enter"}
+};
+
+int main(int argc, char** argv) {
+  Fl::add_handler(handle);
+  Fl_Window *window = make_window();
+  window->show(argc,argv);
+  while (Fl::wait()) {
+    
+    // update all the buttons with the current key and shift state:
+    for (int i = 0; i < window->children(); i++) {
+      Fl_Widget* b = window->child(i);
+      if (b->callback() == (Fl_Callback*)key_cb) {
+	int i = int(b->user_data());
+	if (!i) i = b->label()[0];
+	((Fl_Button*)b)->value(Fl::event_key(i));
+      } else if (b->callback() == (Fl_Callback*)shift_cb) {
+	int i = int(b->user_data());
+	((Fl_Button*)b)->value(Fl::event_state(i));
+      }
+    }
+
+    // figure out the keyname:
+    char buffer[100];
+    const char *keyname = buffer;
+    int k = Fl::event_key();
+    if (!k)
+      keyname = "0";
+    else if (k < 256) {
+      sprintf(buffer, "'%c'", k);
+    } else if (k >= FL_F && k <= FL_F_Last) {
+      sprintf(buffer, "FL_F+%d", k - FL_F);
+    } else if (k >= FL_KP && k <= FL_KP_Last) {
+      sprintf(buffer, "FL_KP+'%c'", k-FL_KP);
+    } else if (k >= FL_Button && k <= FL_Button+7) {
+      sprintf(buffer, "FL_Button+%d", k-FL_Button);
+    } else {
+      sprintf(buffer, "0x%04x", k);
+      for (int i = 0; i < int(sizeof(table)/sizeof(*table)); i++)
+	if (table[i].n == k) {keyname = table[i].text; break;}
+    }
+    key_output->value(keyname);
+
+    text_output->value(Fl::event_text());
+  }
+  return 0;
+}
diff --git a/test/keyboard_ui.C b/test/keyboard_ui.C
new file mode 100644
index 000000000..cf35760bd
--- /dev/null
+++ b/test/keyboard_ui.C
@@ -0,0 +1,558 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+#include "keyboard_ui.H"
+Fl_Output *key_output;
+Fl_Output *text_output;
+
+Fl_Window* make_window() {
+ Fl_Window *w;
+ {Fl_Window* o = new Fl_Window(494, 193);
+  w = o;
+ {Fl_Button* o = new Fl_Button(15, 50, 20, 20, "Esc ");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Escape));
+ }
+ {Fl_Button* o = new Fl_Button(50, 50, 20, 20, "F1");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+1));
+ }
+ {Fl_Button* o = new Fl_Button(70, 50, 20, 20, "F2");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+2));
+ }
+ {Fl_Button* o = new Fl_Button(90, 50, 20, 20, "F3");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+3));
+ }
+ {Fl_Button* o = new Fl_Button(110, 50, 20, 20, "F4");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+4));
+ }
+ {Fl_Button* o = new Fl_Button(140, 50, 20, 20, "F5");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+5));
+ }
+ {Fl_Button* o = new Fl_Button(160, 50, 20, 20, "F6");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+6));
+ }
+ {Fl_Button* o = new Fl_Button(180, 50, 20, 20, "F7");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+7));
+ }
+ {Fl_Button* o = new Fl_Button(200, 50, 20, 20, "F8");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+8));
+ }
+ {Fl_Button* o = new Fl_Button(230, 50, 20, 20, "F9");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+9));
+ }
+ {Fl_Button* o = new Fl_Button(250, 50, 20, 20, "F10");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+10));
+ }
+ {Fl_Button* o = new Fl_Button(270, 50, 20, 20, "F11");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+11));
+ }
+ {Fl_Button* o = new Fl_Button(290, 50, 20, 20, "F12");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_F+12));
+ }
+ {Fl_Button* o = new Fl_Button(325, 50, 20, 20, "Print ");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Print));
+ }
+ {Fl_Button* o = new Fl_Button(345, 50, 20, 20, "Sclk ");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Scroll_Lock));
+ }
+ {Fl_Button* o = new Fl_Button(365, 50, 20, 20, "Paus ");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Pause));
+ }
+ {Fl_Button* o = new Fl_Button(15, 80, 20, 20, "`");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(35, 80, 20, 20, "1");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(55, 80, 20, 20, "2");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(75, 80, 20, 20, "3");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(95, 80, 20, 20, "4");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(115, 80, 20, 20, "5");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(135, 80, 20, 20, "6");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(155, 80, 20, 20, "7");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(175, 80, 20, 20, "8");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(195, 80, 20, 20, "9");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(215, 80, 20, 20, "0");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(235, 80, 20, 20, "-");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(255, 80, 20, 20, "=");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(275, 80, 35, 20, "Bksp");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_BackSpace));
+  o->align(20);
+ }
+ {Fl_Button* o = new Fl_Button(325, 80, 20, 20, "Ins ");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Insert));
+ }
+ {Fl_Button* o = new Fl_Button(345, 80, 20, 20, "Home");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Home));
+ }
+ {Fl_Button* o = new Fl_Button(365, 80, 20, 20, "pgup ");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Page_Up));
+ }
+ {Fl_Button* o = new Fl_Button(400, 80, 20, 20, "Num");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Num_Lock));
+ }
+ {Fl_Button* o = new Fl_Button(420, 80, 20, 20, "/");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'/'));
+ }
+ {Fl_Button* o = new Fl_Button(440, 80, 20, 20, "*");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'*'));
+ }
+ {Fl_Button* o = new Fl_Button(460, 80, 20, 20, "-");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'-'));
+ }
+ {Fl_Button* o = new Fl_Button(15, 100, 27, 20, "Tab");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Tab));
+  o->align(20);
+ }
+ {Fl_Button* o = new Fl_Button(42, 100, 20, 20, "Q");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(62, 100, 20, 20, "W");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(82, 100, 20, 20, "E");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(102, 100, 20, 20, "R");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(122, 100, 20, 20, "T");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(142, 100, 20, 20, "Y");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(162, 100, 20, 20, "U");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(182, 100, 20, 20, "I");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(202, 100, 20, 20, "O");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(222, 100, 20, 20, "P");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(242, 100, 20, 20, "[");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(262, 100, 20, 20, "]");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(282, 100, 28, 20, "\\");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)('|'));
+  o->align(20);
+ }
+ {Fl_Button* o = new Fl_Button(325, 100, 20, 20, "Del ");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Delete));
+ }
+ {Fl_Button* o = new Fl_Button(345, 100, 20, 20, "End ");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_End));
+ }
+ {Fl_Button* o = new Fl_Button(365, 100, 20, 20, "pgdn ");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Page_Down));
+ }
+ {Fl_Button* o = new Fl_Button(400, 100, 20, 20, "7");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'7'));
+ }
+ {Fl_Button* o = new Fl_Button(420, 100, 20, 20, "8");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'8'));
+ }
+ {Fl_Button* o = new Fl_Button(440, 100, 20, 20, "9");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'9'));
+ }
+ {Fl_Button* o = new Fl_Button(460, 100, 20, 40, "+");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'+'));
+  o->align(17);
+ }
+ {Fl_Button* o = new Fl_Button(15, 120, 36, 20, "Lock");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Caps_Lock));
+  o->align(20);
+ }
+ {Fl_Button* o = new Fl_Button(51, 120, 20, 20, "A");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(71, 120, 20, 20, "S");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(91, 120, 20, 20, "D");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(111, 120, 20, 20, "F");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(131, 120, 20, 20, "G");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(151, 120, 20, 20, "H");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(171, 120, 20, 20, "J");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(191, 120, 20, 20, "K");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(211, 120, 20, 20, "L");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(231, 120, 20, 20, ";");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(251, 120, 20, 20, "\'");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(271, 120, 39, 20, "Enter");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Enter));
+  o->align(20);
+ }
+ {Fl_Button* o = new Fl_Button(400, 120, 20, 20, "4");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'4'));
+ }
+ {Fl_Button* o = new Fl_Button(420, 120, 20, 20, "5");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'5'));
+ }
+ {Fl_Button* o = new Fl_Button(440, 120, 20, 20, "6");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'6'));
+ }
+ {Fl_Button* o = new Fl_Button(15, 140, 45, 20, "Shift");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Shift_L));
+  o->align(20);
+ }
+ {Fl_Button* o = new Fl_Button(60, 140, 20, 20, "Z");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(80, 140, 20, 20, "X");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(100, 140, 20, 20, "C");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(120, 140, 20, 20, "V");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(140, 140, 20, 20, "B");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(160, 140, 20, 20, "N");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(180, 140, 20, 20, "M");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(200, 140, 20, 20, ",");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(220, 140, 20, 20, ".");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(240, 140, 20, 20, "/");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb);
+ }
+ {Fl_Button* o = new Fl_Button(260, 140, 50, 20, "Shift");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Shift_R));
+  o->align(20);
+ }
+ {Fl_Button* o = new Fl_Button(345, 140, 20, 20, "@8->");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->labelsize(10);
+  o->labelcolor(47);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Up));
+ }
+ {Fl_Button* o = new Fl_Button(400, 140, 20, 20, "1");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'1'));
+ }
+ {Fl_Button* o = new Fl_Button(420, 140, 20, 20, "2");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'2'));
+ }
+ {Fl_Button* o = new Fl_Button(440, 140, 20, 20, "3");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'3'));
+ }
+ {Fl_Button* o = new Fl_Button(460, 140, 20, 40);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP_Enter));
+ }
+ {Fl_Button* o = new Fl_Button(15, 160, 30, 20, "Ctrl");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Control_L));
+  o->align(20);
+ }
+ {Fl_Button* o = new Fl_Button(45, 160, 30, 20, "Meta ");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Meta_L));
+ }
+ {Fl_Button* o = new Fl_Button(75, 160, 30, 20, "Alt ");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Alt_L));
+ }
+ {Fl_Button* o = new Fl_Button(105, 160, 85, 20);
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(' '));
+ }
+ {Fl_Button* o = new Fl_Button(190, 160, 30, 20, "Alt ");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Alt_R));
+ }
+ {Fl_Button* o = new Fl_Button(220, 160, 30, 20, "Meta ");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Meta_R));
+ }
+ {Fl_Button* o = new Fl_Button(250, 160, 30, 20, "Menu ");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Menu));
+ }
+ {Fl_Button* o = new Fl_Button(280, 160, 30, 20, "Ctrl");
+  o->labelsize(8);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Control_R));
+  o->align(20);
+ }
+ {Fl_Button* o = new Fl_Button(325, 160, 20, 20, "@4->");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->labelsize(10);
+  o->labelcolor(47);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Left));
+ }
+ {Fl_Button* o = new Fl_Button(345, 160, 20, 20, "@2->");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->labelsize(10);
+  o->labelcolor(47);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Down));
+ }
+ {Fl_Button* o = new Fl_Button(365, 160, 20, 20, "@6->");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->labelsize(10);
+  o->labelcolor(47);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_Right));
+ }
+ {Fl_Button* o = new Fl_Button(400, 160, 40, 20, "0");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'0'));
+  o->align(20);
+ }
+ {Fl_Button* o = new Fl_Button(440, 160, 20, 20, ".");
+  o->labelsize(10);
+  o->callback((Fl_Callback*)key_cb, (void*)(FL_KP+'.'));
+ }
+ {Fl_Button* o = new Fl_Button(400, 15, 20, 10, "shift ");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_SHIFT));
+ }
+ {Fl_Button* o = new Fl_Button(420, 15, 20, 10, "lock ");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_CAPS_LOCK));
+ }
+ {Fl_Button* o = new Fl_Button(440, 15, 20, 10, "ctrl");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_CTRL));
+ }
+ {Fl_Button* o = new Fl_Button(460, 15, 20, 10, "alt");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_ALT));
+ }
+ {Fl_Button* o = new Fl_Button(400, 25, 20, 10, "num");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_NUM_LOCK));
+ }
+ {Fl_Button* o = new Fl_Button(420, 25, 20, 10, "?");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(0x20));
+ }
+ {Fl_Button* o = new Fl_Button(440, 25, 20, 10, "meta ");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_META));
+ }
+ {Fl_Button* o = new Fl_Button(460, 25, 20, 10, "sclk");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_SCROLL_LOCK));
+ }
+ {Fl_Button* o = new Fl_Button(400, 35, 20, 10, "b1");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_BUTTON1));
+ }
+ {Fl_Button* o = new Fl_Button(420, 35, 20, 10, "b2");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_BUTTON2));
+ }
+ {Fl_Button* o = new Fl_Button(440, 35, 20, 10, "b3");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(FL_BUTTON3));
+ }
+ {Fl_Button* o = new Fl_Button(460, 35, 20, 10, "?");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(0x800));
+ }
+ {Fl_Button* o = new Fl_Button(400, 45, 20, 10, "?");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(0x1000));
+ }
+ {Fl_Button* o = new Fl_Button(420, 45, 20, 10, "?");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(0x2000));
+ }
+ {Fl_Button* o = new Fl_Button(440, 45, 20, 10, "?");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(0x4000));
+ }
+ {Fl_Button* o = new Fl_Button(460, 45, 20, 10, "?");
+  o->box(FL_THIN_UP_BOX);
+  o->color2(3);
+  o->labelsize(8);
+  o->callback((Fl_Callback*)shift_cb, (void*)(0x8000));
+ }
+ {Fl_Output* o = new Fl_Output(15, 15, 170, 30, "Fl::event_key():");
+  key_output = o;
+  o->labelsize(8);
+  o->align(5);
+ }
+ {Fl_Box* o = new Fl_Box(395, 15, 85, 40, "Fl::event_state():");
+  o->labelsize(8);
+  o->align(5);
+ }
+ {Fl_Output* o = new Fl_Output(195, 15, 190, 30, "Fl::event_text():");
+  text_output = o;
+  o->labelsize(8);
+  o->align(5);
+ }
+ w->end();
+ }
+ return w;
+}
diff --git a/test/keyboard_ui.H b/test/keyboard_ui.H
new file mode 100644
index 000000000..365d2dbc5
--- /dev/null
+++ b/test/keyboard_ui.H
@@ -0,0 +1,11 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+#include 
+#include 
+#include 
+#include 
+#include 
+extern void key_cb(Fl_Button*, void*);
+extern void shift_cb(Fl_Button*, void*);
+extern Fl_Output *key_output;
+extern Fl_Output *text_output;
+Fl_Window* make_window();
diff --git a/test/keyboard_ui.fl b/test/keyboard_ui.fl
new file mode 100644
index 000000000..791cdce5f
--- /dev/null
+++ b/test/keyboard_ui.fl
@@ -0,0 +1,696 @@
+# data file for FL User Interface Designer (fluid)
+version 0.99 
+gridx 5 
+gridy 5 
+snap 3
+Function {make_window()} {open
+} {
+  Fl_Window {} {open
+    xywh {118 466 494 193}
+  } {
+    Fl_Button {} {
+      label {Esc }
+      user_data FL_Escape user_data_type {void*}
+      callback key_cb open
+      xywh {15 50 20 20} labelsize 8
+    }
+    Fl_Button {} {
+      label F1
+      user_data {FL_F+1} user_data_type {void*}
+      callback key_cb open
+      xywh {50 50 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label F2
+      user_data {FL_F+2} user_data_type {void*}
+      callback key_cb open
+      xywh {70 50 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label F3
+      user_data {FL_F+3} user_data_type {void*}
+      callback key_cb open
+      xywh {90 50 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label F4
+      user_data {FL_F+4} user_data_type {void*}
+      callback key_cb open
+      xywh {110 50 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label F5
+      user_data {FL_F+5} user_data_type {void*}
+      callback key_cb open
+      xywh {140 50 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label F6
+      user_data {FL_F+6} user_data_type {void*}
+      callback key_cb open
+      xywh {160 50 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label F7
+      user_data {FL_F+7} user_data_type {void*}
+      callback key_cb open
+      xywh {180 50 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label F8
+      user_data {FL_F+8} user_data_type {void*}
+      callback key_cb open
+      xywh {200 50 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label F9
+      user_data {FL_F+9} user_data_type {void*}
+      callback key_cb open
+      xywh {230 50 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label F10
+      user_data {FL_F+10} user_data_type {void*}
+      callback key_cb open
+      xywh {250 50 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label F11
+      user_data {FL_F+11} user_data_type {void*}
+      callback key_cb open
+      xywh {270 50 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label F12
+      user_data {FL_F+12} user_data_type {void*}
+      callback key_cb open
+      xywh {290 50 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {Print }
+      user_data FL_Print user_data_type {void*}
+      callback key_cb open
+      xywh {325 50 20 20} labelsize 8
+    }
+    Fl_Button {} {
+      label {Sclk }
+      user_data FL_Scroll_Lock user_data_type {void*}
+      callback key_cb open
+      xywh {345 50 20 20} labelsize 8
+    }
+    Fl_Button {} {
+      label {Paus }
+      user_data FL_Pause user_data_type {void*}
+      callback key_cb open
+      xywh {365 50 20 20} labelsize 8
+    }
+    Fl_Button {} {
+      label {`}
+      callback key_cb open
+      xywh {15 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 1
+      callback key_cb open
+      xywh {35 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 2
+      callback key_cb open
+      xywh {55 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 3
+      callback key_cb open
+      xywh {75 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 4
+      callback key_cb open
+      xywh {95 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 5
+      callback key_cb open
+      xywh {115 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 6
+      callback key_cb open
+      xywh {135 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 7
+      callback key_cb open
+      xywh {155 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 8
+      callback key_cb open
+      xywh {175 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 9
+      callback key_cb open
+      xywh {195 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 0
+      callback key_cb open
+      xywh {215 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {-}
+      callback key_cb open
+      xywh {235 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {=}
+      callback key_cb open
+      xywh {255 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label Bksp
+      user_data FL_BackSpace user_data_type {void*}
+      callback key_cb open
+      xywh {275 80 35 20} labeltype 2 labelsize 8 align 20
+    }
+    Fl_Button {} {
+      label {Ins }
+      user_data FL_Insert user_data_type {void*}
+      callback key_cb open
+      xywh {325 80 20 20} labelsize 8
+    }
+    Fl_Button {} {
+      label Home
+      user_data FL_Home user_data_type {void*}
+      callback key_cb open
+      xywh {345 80 20 20} labelsize 8
+    }
+    Fl_Button {} {
+      label {pgup }
+      user_data FL_Page_Up user_data_type {void*}
+      callback key_cb open
+      xywh {365 80 20 20} labelsize 8
+    }
+    Fl_Button {} {
+      label Num
+      user_data FL_Num_Lock user_data_type {void*}
+      callback key_cb open
+      xywh {400 80 20 20} labelsize 8
+    }
+    Fl_Button {} {
+      label {/}
+      user_data {FL_KP+'/'} user_data_type {void*}
+      callback key_cb open
+      xywh {420 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {*}
+      user_data {FL_KP+'*'} user_data_type {void*}
+      callback key_cb open
+      xywh {440 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {-}
+      user_data {FL_KP+'-'} user_data_type {void*}
+      callback key_cb open
+      xywh {460 80 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label Tab
+      user_data FL_Tab user_data_type {void*}
+      callback key_cb open
+      xywh {15 100 27 20} labelsize 8 align 20
+    }
+    Fl_Button {} {
+      label Q
+      callback key_cb open
+      xywh {42 100 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label W
+      callback key_cb open
+      xywh {62 100 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label E
+      callback key_cb open
+      xywh {82 100 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label R
+      callback key_cb open
+      xywh {102 100 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label T
+      callback key_cb open
+      xywh {122 100 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label Y
+      callback key_cb open
+      xywh {142 100 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label U
+      callback key_cb open
+      xywh {162 100 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label I
+      callback key_cb open
+      xywh {182 100 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label O
+      callback key_cb open
+      xywh {202 100 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label P
+      callback key_cb open
+      xywh {222 100 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {[}
+      callback key_cb open
+      xywh {242 100 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {]}
+      callback key_cb open
+      xywh {262 100 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {\\}
+      user_data {'|'}
+      callback key_cb open
+      xywh {282 100 28 20} labelsize 10 align 20
+    }
+    Fl_Button {} {
+      label {Del }
+      user_data FL_Delete user_data_type {void*}
+      callback key_cb open
+      xywh {325 100 20 20} labelsize 8
+    }
+    Fl_Button {} {
+      label {End }
+      user_data FL_End user_data_type {void*}
+      callback key_cb open
+      xywh {345 100 20 20} labelsize 8
+    }
+    Fl_Button {} {
+      label {pgdn }
+      user_data FL_Page_Down user_data_type {void*}
+      callback key_cb open
+      xywh {365 100 20 20} labelsize 8
+    }
+    Fl_Button {} {
+      label 7
+      user_data {FL_KP+'7'} user_data_type {void*}
+      callback key_cb open
+      xywh {400 100 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 8
+      user_data {FL_KP+'8'} user_data_type {void*}
+      callback key_cb open
+      xywh {420 100 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 9
+      user_data {FL_KP+'9'} user_data_type {void*}
+      callback key_cb open
+      xywh {440 100 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {+}
+      user_data {FL_KP+'+'} user_data_type {void*}
+      callback key_cb open
+      xywh {460 100 20 40} labelsize 10 align 17
+    }
+    Fl_Button {} {
+      label Lock
+      user_data FL_Caps_Lock user_data_type {void*}
+      callback key_cb open
+      xywh {15 120 36 20} labelsize 8 align 20
+    }
+    Fl_Button {} {
+      label A
+      callback key_cb open
+      xywh {51 120 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label S
+      callback key_cb open
+      xywh {71 120 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label D
+      callback key_cb open
+      xywh {91 120 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label F
+      callback key_cb open
+      xywh {111 120 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label G
+      callback key_cb open
+      xywh {131 120 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label H
+      callback key_cb open
+      xywh {151 120 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label J
+      callback key_cb open
+      xywh {171 120 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label K
+      callback key_cb open
+      xywh {191 120 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label L
+      callback key_cb open
+      xywh {211 120 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {;}
+      callback key_cb open
+      xywh {231 120 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {'}
+      callback key_cb open
+      xywh {251 120 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label Enter
+      user_data FL_Enter user_data_type {void*}
+      callback key_cb open
+      xywh {271 120 39 20} labelsize 8 align 20
+    }
+    Fl_Button {} {
+      label 4
+      user_data {FL_KP+'4'} user_data_type {void*}
+      callback key_cb open
+      xywh {400 120 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 5
+      user_data {FL_KP+'5'} user_data_type {void*}
+      callback key_cb open
+      xywh {420 120 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 6
+      user_data {FL_KP+'6'} user_data_type {void*}
+      callback key_cb open
+      xywh {440 120 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label Shift
+      user_data FL_Shift_L user_data_type {void*}
+      callback key_cb open
+      xywh {15 140 45 20} labelsize 8 align 20
+    }
+    Fl_Button {} {
+      label Z
+      callback key_cb open
+      xywh {60 140 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label X
+      callback key_cb open
+      xywh {80 140 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label C
+      callback key_cb open
+      xywh {100 140 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label V
+      callback key_cb open
+      xywh {120 140 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label B
+      callback key_cb open
+      xywh {140 140 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label N
+      callback key_cb open
+      xywh {160 140 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label M
+      callback key_cb open
+      xywh {180 140 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {,}
+      callback key_cb open
+      xywh {200 140 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {.}
+      callback key_cb open
+      xywh {220 140 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {/}
+      callback key_cb open
+      xywh {240 140 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label Shift
+      user_data FL_Shift_R user_data_type {void*}
+      callback key_cb open
+      xywh {260 140 50 20} labelsize 8 align 20
+    }
+    Fl_Button {} {
+      label {@8->}
+      user_data FL_Up user_data_type {void*}
+      callback key_cb open
+      xywh {345 140 20 20} labeltype 2 labelsize 10 labelcolor 47
+    }
+    Fl_Button {} {
+      label 1
+      user_data {FL_KP+'1'} user_data_type {void*}
+      callback key_cb open
+      xywh {400 140 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 2
+      user_data {FL_KP+'2'} user_data_type {void*}
+      callback key_cb open
+      xywh {420 140 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label 3
+      user_data {FL_KP+'3'} user_data_type {void*}
+      callback key_cb open
+      xywh {440 140 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      user_data FL_KP_Enter user_data_type {void*}
+      callback key_cb open
+      xywh {460 140 20 40}
+    }
+    Fl_Button {} {
+      label Ctrl
+      user_data FL_Control_L user_data_type {void*}
+      callback key_cb open
+      xywh {15 160 30 20} labelsize 8 align 20
+    }
+    Fl_Button {} {
+      label {Meta }
+      user_data FL_Meta_L user_data_type {void*}
+      callback key_cb open
+      xywh {45 160 30 20} labelsize 8
+    }
+    Fl_Button {} {
+      label {Alt }
+      user_data FL_Alt_L user_data_type {void*}
+      callback key_cb open
+      xywh {75 160 30 20} labelsize 8
+    }
+    Fl_Button {} {
+      user_data {' '} user_data_type {void*}
+      callback key_cb open
+      xywh {105 160 85 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {Alt }
+      user_data FL_Alt_R user_data_type {void*}
+      callback key_cb open
+      xywh {190 160 30 20} labelsize 8
+    }
+    Fl_Button {} {
+      label {Meta }
+      user_data FL_Meta_R user_data_type {void*}
+      callback key_cb open
+      xywh {220 160 30 20} labelsize 8
+    }
+    Fl_Button {} {
+      label {Menu }
+      user_data FL_Menu user_data_type {void*}
+      callback key_cb open
+      xywh {250 160 30 20} labelsize 8
+    }
+    Fl_Button {} {
+      label Ctrl
+      user_data FL_Control_R user_data_type {void*}
+      callback key_cb open
+      xywh {280 160 30 20} labelsize 8 align 20
+    }
+    Fl_Button {} {
+      label {@4->}
+      user_data FL_Left user_data_type {void*}
+      callback key_cb open
+      xywh {325 160 20 20} labeltype 2 labelsize 10 labelcolor 47
+    }
+    Fl_Button {} {
+      label {@2->}
+      user_data FL_Down user_data_type {void*}
+      callback key_cb open
+      xywh {345 160 20 20} labeltype 2 labelsize 10 labelcolor 47
+    }
+    Fl_Button {} {
+      label {@6->}
+      user_data FL_Right user_data_type {void*}
+      callback key_cb open
+      xywh {365 160 20 20} labeltype 2 labelsize 10 labelcolor 47
+    }
+    Fl_Button {} {
+      label 0
+      user_data {FL_KP+'0'} user_data_type {void*}
+      callback key_cb open
+      xywh {400 160 40 20} labelsize 10 align 20
+    }
+    Fl_Button {} {
+      label {.}
+      user_data {FL_KP+'.'} user_data_type {void*}
+      callback key_cb open
+      xywh {440 160 20 20} labelsize 10
+    }
+    Fl_Button {} {
+      label {shift }
+      user_data FL_SHIFT user_data_type {void*}
+      callback shift_cb open
+      xywh {400 15 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Button {} {
+      label {lock }
+      user_data FL_CAPS_LOCK user_data_type {void*}
+      callback shift_cb open
+      xywh {420 15 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Button {} {
+      label ctrl
+      user_data FL_CTRL user_data_type {void*}
+      callback shift_cb open
+      xywh {440 15 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Button {} {
+      label alt
+      user_data FL_ALT user_data_type {void*}
+      callback shift_cb open
+      xywh {460 15 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Button {} {
+      label num
+      user_data FL_NUM_LOCK user_data_type {void*}
+      callback shift_cb open
+      xywh {400 25 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Button {} {
+      label {?}
+      user_data 0x20 user_data_type {void*}
+      callback shift_cb open
+      xywh {420 25 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Button {} {
+      label {meta }
+      user_data FL_META user_data_type {void*}
+      callback shift_cb open
+      xywh {440 25 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Button {} {
+      label sclk
+      user_data FL_SCROLL_LOCK user_data_type {void*}
+      callback shift_cb open
+      xywh {460 25 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Button {} {
+      label b1
+      user_data FL_BUTTON1 user_data_type {void*}
+      callback shift_cb open
+      xywh {400 35 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Button {} {
+      label b2
+      user_data FL_BUTTON2 user_data_type {void*}
+      callback shift_cb open
+      xywh {420 35 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Button {} {
+      label b3
+      user_data FL_BUTTON3 user_data_type {void*}
+      callback shift_cb open
+      xywh {440 35 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Button {} {
+      label {?}
+      user_data 0x800 user_data_type {void*}
+      callback shift_cb open
+      xywh {460 35 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Button {} {
+      label {?}
+      user_data 0x1000 user_data_type {void*}
+      callback shift_cb open
+      xywh {400 45 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Button {} {
+      label {?}
+      user_data 0x2000 user_data_type {void*}
+      callback shift_cb open
+      xywh {420 45 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Button {} {
+      label {?}
+      user_data 0x4000 user_data_type {void*}
+      callback shift_cb open
+      xywh {440 45 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Button {} {
+      label {?}
+      user_data 0x8000 user_data_type {void*}
+      callback shift_cb open
+      xywh {460 45 20 10} box 6 color {47 3} labelsize 8
+    }
+    Fl_Output key_output {
+      label {Fl::event_key():} open
+      xywh {15 15 170 30} labelsize 8 align 5
+    }
+    Fl_Box {} {
+      label {Fl::event_state():} open
+      xywh {395 15 85 40} labelsize 8 align 5
+    }
+    Fl_Output text_output {
+      label {Fl::event_text():} open selected
+      xywh {195 15 190 30} labelsize 8 align 5
+    }
+  }
+} 
diff --git a/test/label.cxx b/test/label.cxx
new file mode 100644
index 000000000..d1ca5be10
--- /dev/null
+++ b/test/label.cxx
@@ -0,0 +1,137 @@
+/*	Test all the built-in labeltypes, and fl_font
+
+	This is also a good double-buffering test.
+
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb,*clipb,*wrapb;
+Fl_Box *text;
+Fl_Input *input;
+Fl_Hor_Value_Slider *fonts;
+Fl_Hor_Value_Slider *sizes;
+Fl_Double_Window *window;
+
+void button_cb(Fl_Widget *,void *) {
+  int i = 0;
+  if (leftb->value()) i |= FL_ALIGN_LEFT;
+  if (rightb->value()) i |= FL_ALIGN_RIGHT;
+  if (topb->value()) i |= FL_ALIGN_TOP;
+  if (bottomb->value()) i |= FL_ALIGN_BOTTOM;
+  if (insideb->value()) i |= FL_ALIGN_INSIDE;
+  if (clipb->value()) i |= FL_ALIGN_CLIP;
+  if (wrapb->value()) i |= FL_ALIGN_WRAP;
+  text->align(i);
+  window->redraw();
+}
+
+void font_cb(Fl_Widget *,void *) {
+  text->labelfont(int(fonts->value()));
+  window->redraw();
+}
+
+void size_cb(Fl_Widget *,void *) {
+  text->labelsize(int(sizes->value()));
+  window->redraw();
+}
+
+void input_cb(Fl_Widget *,void *) {
+  text->label(input->value());
+  window->redraw();
+}
+
+void normal_cb(Fl_Widget *,void *) {
+  text->labeltype(FL_NORMAL_LABEL);
+  window->redraw();
+}
+
+void symbol_cb(Fl_Widget *,void *) {
+  text->labeltype(FL_SYMBOL_LABEL);
+  if (input->value()[0] != '@') {
+    input->static_value("@->");
+    text->label("@->");
+  }
+  window->redraw();
+}
+
+void shadow_cb(Fl_Widget *,void *) {
+  text->labeltype(FL_SHADOW_LABEL);
+  window->redraw();
+}
+
+void embossed_cb(Fl_Widget *,void *) {
+  text->labeltype(FL_EMBOSSED_LABEL);
+  window->redraw();
+}
+
+void engraved_cb(Fl_Widget *,void *) {
+  text->labeltype(FL_ENGRAVED_LABEL);
+  window->redraw();
+}
+
+Fl_Menu_Item choices[] = {
+  {"FL_NORMAL_LABEL",0,normal_cb},
+  {"FL_SYMBOL_LABEL",0,symbol_cb},
+  {"FL_SHADOW_LABEL",0,shadow_cb},
+  {"FL_ENGRAVED_LABEL",0,engraved_cb},
+  {"FL_EMBOSSED_LABEL",0,embossed_cb},
+  {0}};
+
+int main(int argc, char **argv) {
+  window = new Fl_Double_Window(400,400);
+
+  input = new Fl_Input(50,0,350,25);
+  input->static_value("The quick brown fox jumped over the lazy dog.");
+  input->when(FL_WHEN_CHANGED);
+  input->callback(input_cb);
+
+  sizes= new Fl_Hor_Value_Slider(50,25,350,25,"Size:");
+  sizes->align(FL_ALIGN_LEFT);
+  sizes->bounds(1,64);
+  sizes->step(1);
+  sizes->value(14);
+  sizes->callback(size_cb);
+
+  fonts=new Fl_Hor_Value_Slider(50,50,350,25,"Font:");
+  fonts->align(FL_ALIGN_LEFT);
+  fonts->bounds(0,15);
+  fonts->step(1);
+  fonts->value(0);
+  fonts->callback(font_cb);
+
+  Fl_Group *g = new Fl_Group(0,0,0,0);
+  leftb = new Fl_Toggle_Button(50,75,50,25,"left");
+  leftb->callback(button_cb);
+  rightb = new Fl_Toggle_Button(100,75,50,25,"right");
+  rightb->callback(button_cb);
+  topb = new Fl_Toggle_Button(150,75,50,25,"top");
+  topb->callback(button_cb);
+  bottomb = new Fl_Toggle_Button(200,75,50,25,"bottom");
+  bottomb->callback(button_cb);
+  insideb = new Fl_Toggle_Button(250,75,50,25,"inside");
+  insideb->callback(button_cb);
+  wrapb = new Fl_Toggle_Button(300,75,50,25,"wrap");
+  wrapb->callback(button_cb);
+  clipb = new Fl_Toggle_Button(350,75,50,25,"clip");
+  clipb->callback(button_cb);
+  g->resizable(insideb);
+  g->forms_end();
+
+  Fl_Choice *c = new Fl_Choice(50,100,200,25);
+  c->menu(choices);
+
+  text= new Fl_Box(FL_FRAME_BOX,100,225,200,100,input->value());
+  text->align(FL_ALIGN_CENTER);
+  window->resizable(text);
+  window->forms_end();
+  window->show(argc,argv);
+  return Fl::run();
+}
diff --git a/test/list_visuals.cxx b/test/list_visuals.cxx
new file mode 100644
index 000000000..57b1e7e74
--- /dev/null
+++ b/test/list_visuals.cxx
@@ -0,0 +1,205 @@
+// List all the visuals on the screen, and dumps anything interesting
+// about them to stdout.
+//
+// Does not use fltk.
+//
+// This file may be #included in another program to make a function to
+// call to list the visuals.  Fl.H must be included first to indicate this.
+
+#ifdef WIN32
+void list_visuals() {;}
+#else
+
+#include 
+
+#ifndef Fl_H
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+Display *fl_display;
+int fl_screen;
+const char *dname;
+void fl_open_display() {
+  fl_display = XOpenDisplay(dname);
+  if (!fl_display) {
+    fprintf(stderr,"Can't open display: %s\n",XDisplayName(dname));
+    exit(1);
+  }
+  fl_screen = DefaultScreen(fl_display);
+}
+
+#endif
+
+const char *ClassNames[] = {
+  "StaticGray ",
+  "GrayScale  ",
+  "StaticColor",
+  "PseudoColor",
+  "TrueColor  ",
+  "DirectColor"
+};
+
+// SERVER_OVERLAY_VISUALS property element:
+typedef struct _OverlayInfo {
+  long overlay_visual;
+  long transparent_type;
+  long value;
+  long layer;
+} OverlayInfo;
+
+#if HAVE_MULTIBUF
+#include 
+#endif
+
+#if HAVE_XDBE
+#include 
+#endif
+
+static void print_mask(XVisualInfo* p) {
+  int n = 0;
+  int what = 0;
+  int print_anything = 0;
+  char buf[20];
+  char *q = buf;
+  *q = 0;
+  int b; unsigned int m; for (b=32,m=0x80000000; ; b--,m>>=1) {
+    int new_what = 0;
+    if (p->red_mask&m) new_what = 'r';
+    else if (p->green_mask&m) new_what = 'g';
+    else if (p->blue_mask&m) new_what = 'b';
+    else new_what = '?';
+    if (new_what != what) {
+      if (what && (what != '?' || print_anything)) {
+	q += sprintf(q,"%d%c", n, what);
+	print_anything = 1;
+      }
+      what = new_what;
+      n = 1;
+    } else {
+      n++;
+    }
+    if (!b) break;
+  }
+  printf("%7s", buf);
+}
+
+void list_visuals() {
+  fl_open_display();
+  XVisualInfo vTemplate;
+  int num;
+  XVisualInfo *visualList = XGetVisualInfo(fl_display,0,&vTemplate,&num);
+
+  XPixmapFormatValues *pfvlist;
+  static int numpfv;
+  pfvlist = XListPixmapFormats(fl_display, &numpfv);
+
+  OverlayInfo *overlayInfo = 0;
+  int numoverlayinfo = 0;
+  Atom overlayVisualsAtom = XInternAtom(fl_display,"SERVER_OVERLAY_VISUALS",1);
+  if (overlayVisualsAtom) {
+    unsigned long sizeData, bytesLeft;
+    Atom actualType;
+    int actualFormat;
+    if (!XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
+			   overlayVisualsAtom, 0L, 10000L, False,
+			   overlayVisualsAtom, &actualType, &actualFormat,
+			   &sizeData, &bytesLeft,
+			   (unsigned char **) &overlayInfo))
+      numoverlayinfo = int(sizeData/4);
+  }
+
+#if HAVE_MULTIBUF
+  int event_base, error_base;
+  XmbufBufferInfo *mbuf, *sbuf;
+  int nmbuf = 0, nsbuf = 0;
+  if (XmbufQueryExtension(fl_display,&event_base, &error_base)) {
+    XmbufGetScreenInfo(fl_display,RootWindow(fl_display,fl_screen),
+		       &nmbuf, &mbuf, &nsbuf, &sbuf);
+  }
+#endif
+
+#if HAVE_XDBE
+  int event_base, error_base;
+  int numdouble = 0;
+  XdbeVisualInfo *dbe = 0;
+  if (XdbeQueryExtension(fl_display, &event_base, &error_base)) {
+    Drawable root = RootWindow(fl_display,fl_screen);
+    int numscreens = 1;
+    XdbeScreenVisualInfo *a = XdbeGetVisualInfo(fl_display,&root,&numscreens);
+    if (!a) printf("error getting double buffer visuals\n");
+    else {
+      dbe = a->visinfo;
+      numdouble = a->count;
+    }
+  }
+#endif
+
+  for (int i=0; i= pfvlist+numpfv) {pfv = 0; break;} // should not happen!
+      if (pfv->depth == p->depth) break;
+    }
+
+    int j = pfv ? pfv->bits_per_pixel : 0;
+    printf(" %2ld: %s %2d/%d", p->visualid, ClassNames[p->c_class],
+	   p->depth, j);
+    if (j < 10) putchar(' ');
+
+    print_mask(p);
+
+    for (j=0; joverlay_visual == long(p->visualid)) {
+	printf(" overlay(");
+	if (o->transparent_type==1) printf("transparent pixel %ld, ",o->value);
+	else if (o->transparent_type==2) printf("transparent mask %ld, ",o->value);
+	else printf("opaque, ");
+	printf("layer %ld)", o->layer);
+      }
+    }
+
+#if HAVE_MULTIBUF
+    for (j=0; jvisualid == p->visualid)
+	printf(" multibuffer(%d)", m->max_buffers);
+    }
+    for (j=0; jvisualid == p->visualid)
+	printf(" stereo multibuffer(%d)", m->max_buffers);
+    }
+#endif
+
+#if HAVE_XDBE
+    for (j = 0; j < numdouble; j++) if (dbe[j].visual == p->visualid)
+      printf(" doublebuf(perflevel %d)",dbe[j].perflevel);
+#endif
+
+    if (p->visualid==XVisualIDFromVisual(DefaultVisual(fl_display,fl_screen)))
+      printf(" (default visual)");
+
+    putchar('\n');
+  }
+}
+
+#endif
+
+#ifndef Fl_H
+int main(int argc, char **argv) {
+  if (argc == 1);
+  else if (argc == 2 && argv[1][0]!='-') dname = argv[1];
+  else {fprintf(stderr,"usage: %s \n",argv[0]); exit(1);}
+  list_visuals();
+  return 0;
+}
+#endif
+
+// end of list_visuals.C
diff --git a/test/mandelbrot.cxx b/test/mandelbrot.cxx
new file mode 100644
index 000000000..b325736b2
--- /dev/null
+++ b/test/mandelbrot.cxx
@@ -0,0 +1,200 @@
+#include "mandelbrot_ui.C"
+#include 
+#include 
+#include 
+
+Drawing_Window mbrot;
+Drawing_Window jbrot;
+
+void idle() {
+  if (!mbrot.d->idle() && !(jbrot.d && jbrot.d->idle())) Fl::set_idle(0);
+}
+
+void set_idle() {
+  Fl::set_idle(idle);
+}
+
+static void window_callback(Fl_Widget*, void*) {exit(0);}
+
+int main(int argc, char **argv) {
+  make_window(mbrot);
+  mbrot.d->X = -.75;
+  mbrot.d->scale = 2.5;
+  mbrot.update_label();
+  int i = 0;
+  if (Fl::args(argc,argv,i) < argc) Fl::fatal(Fl::help);
+  Fl::visual(FL_RGB);
+  mbrot.window->callback(window_callback);
+  mbrot.window->show(argc,argv);
+  Fl::run();
+  return 0;
+}
+
+void Drawing_Window::update_label() {
+  char buffer[128];
+  sprintf(buffer, "%+.10f", d->X); x_input->value(buffer);
+  sprintf(buffer, "%+.10f", d->Y); y_input->value(buffer);
+  sprintf(buffer, "%.2g", d->scale); w_input->value(buffer);
+}
+
+void Drawing_Area::draw() {
+  draw_box();
+  drawn = 0;
+  set_idle();
+}
+
+int Drawing_Area::idle() {
+  if (!window()->visible()) return 0;
+  if (drawn < nextline) {
+    window()->make_current();
+    int yy = drawn+y()+4;
+    if (yy >= sy && yy <= sy+sh) erase_box();
+    fl_draw_image_mono(buffer+drawn*W,x()+3,yy,W,1,1,W);
+    drawn++;
+    return 1;
+  }
+  if (nextline < H) {
+    if (!buffer) buffer = new uchar[W*H];
+    double yy = Y+(H/2-nextline)*scale/W;
+    double yi = yy; if (julia) yy = jY;
+    uchar *p = buffer+nextline*W;
+    for (int xi = 0; xi < W; xi++) {
+      double xx = X+(xi-W/2)*scale/W;
+      double wx = xx; double wy = yi;
+      if (julia) xx = jX;
+      for (int i=0; ; i++) {
+	if (i >= iterations) {*p = 0; break;}
+	double t = wx*wx - wy*wy + xx;
+	wy = 2*wx*wy + yy;
+	wx = t;
+	if (wx*wx + wy*wy > 4) {
+	  wx = t = 1-double(i)/(1<<10);
+	  if (t <= 0) t = 0; else for (i=brightness; i--;) t*=wx;
+	  *p = 255-int(254*t);
+	  break;
+	}
+      }
+      p++;
+    }
+    nextline++;
+    return nextline < H;
+  }
+  return 0;
+}
+
+void Drawing_Area::erase_box() {
+  window()->make_current();
+  fl_overlay_clear();
+}
+
+int Drawing_Area::handle(int event) {
+  static int ix, iy;
+  static int dragged;
+  static int button;
+  int x2,y2;
+  switch (event) {
+  case FL_PUSH:
+    erase_box();
+    ix = Fl::event_x(); if (ix=x()+w()) ix=x()+w()-1;
+    iy = Fl::event_y(); if (iy=y()+h()) iy=y()+h()-1;
+    dragged = 0;
+    button = Fl::event_button();
+    return 1;
+  case FL_DRAG:
+    dragged = 1;
+    erase_box();
+    x2 = Fl::event_x(); if (x2=x()+w()) x2=x()+w()-1;
+    y2 = Fl::event_y(); if (y2=y()+h()) y2=y()+h()-1;
+    if (button != 1) {ix = x2; iy = y2; return 1;}
+    if (ix < x2) {sx = ix; sw = x2-ix;} else {sx = x2; sw = ix-x2;}
+    if (iy < y2) {sy = iy; sh = y2-iy;} else {sy = y2; sh = iy-y2;}
+    window()->make_current();
+    fl_overlay_rect(sx,sy,sw,sh);
+    return 1;
+  case FL_RELEASE:
+    if (button == 1) {
+      erase_box();
+      if (dragged && sw > 3 && sh > 3) {
+	X = X + (sx+sw/2-x()-W/2)*scale/W;
+	Y = Y + (-sy-sh/2+y()+H/2)*scale/W;
+	scale = sw*scale/W;
+      } else if (!dragged) {
+	scale = 2*scale;
+	if (julia) {
+	  if (scale >= 4) {
+	    scale = 4;
+	    X = Y = 0;
+	  }
+	} else {
+	  if (scale >= 2.5) {
+	    scale = 2.5;
+	    X = -.75;
+	    Y = 0;
+	  }
+	}
+      } else return 1;
+      ((Drawing_Window*)(user_data()))->update_label();
+      new_display();
+    } else if (!julia) {
+      if (!jbrot.d) {
+	make_window(jbrot);
+	jbrot.d->julia = 1;
+	jbrot.d->X = 0;
+	jbrot.d->Y = 0;
+	jbrot.d->scale = 4;
+	jbrot.update_label();
+      }
+      jbrot.d->jX = X + (ix-x()-W/2)*scale/W;
+      jbrot.d->jY = Y + (H/2-iy+y())*scale/W;
+      static char buffer[128];
+      sprintf(buffer, "Julia %.7f %.7f",jbrot.d->jX,jbrot.d->jY);
+      jbrot.window->label(buffer);
+      jbrot.window->show();
+      jbrot.d->new_display();
+    }
+    return 1;
+  }
+  return 0;
+}
+
+void Drawing_Area::new_display() {
+  drawn = nextline = 0;
+  set_idle();
+}
+
+void Drawing_Area::resize(int X,int Y,int W,int H) {
+  if (W != w() || H != h()) {
+    this->W = W-6;
+    this->H = H-8;
+    if (buffer) {delete[] buffer; buffer = 0; new_display();}
+  }
+  Fl_Box::resize(X,Y,W,H);
+}
+
+void brightness_slider_cb(Fl_Slider* o, Drawing_Window* s) {
+  s->d->brightness = int(o->value());
+  s->d->new_display();
+}
+
+void iterations_slider_cb(Fl_Slider* o, Drawing_Window* s) {
+  s->d->iterations = 1<value());
+  s->d->new_display();
+}
+
+void x_callback(Fl_Input* o, Drawing_Window* s) {
+  double v = atof(o->value());
+  s->d->X = v;
+  s->d->new_display();
+}
+
+void y_callback(Fl_Input* o, Drawing_Window* s) {
+  double v = atof(o->value());
+  s->d->Y = v;
+  s->d->new_display();
+}
+
+void w_callback(Fl_Input* o, Drawing_Window* s) {
+  double v = atof(o->value());
+  s->d->scale = v;
+  s->d->new_display();
+}
diff --git a/test/mandelbrot.h b/test/mandelbrot.h
new file mode 100644
index 000000000..fb1f25ddb
--- /dev/null
+++ b/test/mandelbrot.h
@@ -0,0 +1,54 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+
+class Drawing_Window;
+
+class Drawing_Area : public Fl_Box {
+  void draw();
+public:
+  uchar *buffer;
+  int W,H;
+  int nextline;
+  int drawn;
+  int julia;
+  int iterations;
+  int brightness;
+  double jX, jY;
+  double X,Y,scale;
+  int sx, sy, sw, sh; // selection box
+  void erase_box();
+  int handle(int);
+  void resize(int,int,int,int);
+  void new_display();
+  enum {
+    MAX_BRIGHTNESS = 16,
+    DEFAULT_BRIGHTNESS = 16,
+    MAX_ITERATIONS = 14,
+    DEFAULT_ITERATIONS = 7
+  };
+  Drawing_Area(int x,int y,int w,int h) : Fl_Box(x,y,w,h) {
+    buffer = 0;
+    W = w-6;
+    H = h-8;
+    nextline = 0;
+    drawn = 0;
+    julia = 0;
+    X = Y = 0;
+    scale = 4.0;
+    iterations = 1<box(FL_DOWN_BOX);
+  o->color(0);
+  o->user_data((void*)(&s));
+  Fl_Group::current()->resizable(o);
+ }
+ {Fl_Input* o = new Fl_Input(20, 5, 125, 30, "x:");
+  s.x_input = o;
+  o->type(1);
+  o->box(FL_THIN_DOWN_BOX);
+  o->color(8);
+  o->color2(7);
+  o->labelfont(11);
+  o->labelsize(20);
+  o->textfont(11);
+  o->textsize(20);
+  o->callback((Fl_Callback*)x_callback, (void*)(&s));
+  o->when(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE);
+ }
+ {Fl_Input* o = new Fl_Input(165, 5, 125, 30, "y:");
+  s.y_input = o;
+  o->type(1);
+  o->box(FL_THIN_DOWN_BOX);
+  o->color(8);
+  o->color2(7);
+  o->labelfont(11);
+  o->labelsize(20);
+  o->textfont(11);
+  o->textsize(20);
+  o->callback((Fl_Callback*)y_callback, (void*)(&s));
+  o->when(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE);
+ }
+ {Fl_Input* o = new Fl_Input(315, 5, 105, 30, "w:");
+  s.w_input = o;
+  o->type(1);
+  o->box(FL_THIN_DOWN_BOX);
+  o->color(8);
+  o->color2(7);
+  o->labelfont(11);
+  o->labelsize(20);
+  o->textfont(11);
+  o->textsize(20);
+  o->callback((Fl_Callback*)w_callback, (void*)(&s));
+  o->when(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE);
+ }
+ {Fl_Slider* o = new Fl_Slider(70, 40, 160, 15, "brightness:");
+  o->type(1);
+  o->box(FL_THIN_DOWN_BOX);
+  o->labelsize(10);
+  o->step(1);
+  o->slider_size(0.1);
+  o->callback((Fl_Callback*)brightness_slider_cb, (void*)(&s));
+  o->align(4);
+  o->bounds(0,s.d->MAX_BRIGHTNESS);
+  o->value(s.d->DEFAULT_BRIGHTNESS);
+  o->slider(FL_UP_BOX);
+ }
+ {Fl_Box* o = new Fl_Box(230, 40, 190, 30, "left: click = zoom out, drag = zoom in\nright click: Julia set");
+  o->labelsize(10);
+  o->align(24);
+  o->deactivate();
+ }
+ {Fl_Slider* o = new Fl_Slider(70, 55, 160, 15, "iterations:");
+  o->type(1);
+  o->box(FL_THIN_DOWN_BOX);
+  o->labelsize(10);
+  o->step(1);
+  o->slider_size(0.1);
+  o->callback((Fl_Callback*)iterations_slider_cb, (void*)(&s));
+  o->align(4);
+  o->bounds(1,s.d->MAX_ITERATIONS);
+  o->value(s.d->DEFAULT_ITERATIONS);
+  o->slider(FL_UP_BOX);
+ }
+ w->end();
+  o->size_range(220,220);
+ }
+ return w;
+}
diff --git a/test/mandelbrot_ui.H b/test/mandelbrot_ui.H
new file mode 100644
index 000000000..7cac8ea28
--- /dev/null
+++ b/test/mandelbrot_ui.H
@@ -0,0 +1,13 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+#include "mandelbrot.H"
+#include 
+#include 
+#include 
+#include 
+#include 
+extern void brightness_slider_cb(Fl_Slider*, Drawing_Window*);
+extern void iterations_slider_cb(Fl_Slider*, Drawing_Window*);
+extern void w_callback(Fl_Input*, Drawing_Window*);
+extern void x_callback(Fl_Input*, Drawing_Window*);
+extern void y_callback(Fl_Input*, Drawing_Window*);
+Fl_Window* make_window(Drawing_Window& s);
diff --git a/test/mandelbrot_ui.fl b/test/mandelbrot_ui.fl
new file mode 100644
index 000000000..2c864aaad
--- /dev/null
+++ b/test/mandelbrot_ui.fl
@@ -0,0 +1,63 @@
+# data file for FL User Interface Designer (fluid)
+version 0.99 
+gridx 10 
+gridy 10 
+snap 3
+Function {make_window(Drawing_Window& s)} {open
+} {
+  Fl_Window {s.window} {open
+    xywh {92 109 429 510}
+    code0 {o->size_range(220,220);}
+  } {
+    Fl_Box {s.d} {
+      user_data {&s} user_data_type {Drawing_Window*} open
+      xywh {10 70 410 430} box 3 color {0 47} resizable
+      code0 {\#include "mandelbrot.H"}
+      class Drawing_Area
+    }
+    Fl_Input {s.x_input} {
+      label {x:}
+      user_data {&s} user_data_type {Drawing_Window*}
+      callback x_callback open
+      xywh {20 5 125 30} type 1 box 7 color {8 7} labelfont 11 labelsize 20 textfont 11 textsize 20
+      code0 {o->when(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE);}
+    }
+    Fl_Input {s.y_input} {
+      label {y:}
+      user_data {&s} user_data_type {Drawing_Window*}
+      callback y_callback open
+      xywh {165 5 125 30} type 1 box 7 color {8 7} labelfont 11 labelsize 20 textfont 11 textsize 20
+      code0 {o->when(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE);}
+    }
+    Fl_Input {s.w_input} {
+      label {w:}
+      user_data {&s} user_data_type {Drawing_Window*}
+      callback w_callback open
+      xywh {315 5 105 30} type 1 box 7 color {8 7} labelfont 11 labelsize 20 textfont 11 textsize 20
+      code0 {o->when(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE);}
+    }
+    Fl_Slider {} {
+      label {brightness:}
+      user_data {&s} user_data_type {Drawing_Window*}
+      callback brightness_slider_cb open
+      xywh {70 40 160 15} type 1 box 7 labelsize 10 align 4 step 1 slider_size 0.1
+      code0 {o->bounds(0,s.d->MAX_BRIGHTNESS);}
+      code2 {o->value(s.d->DEFAULT_BRIGHTNESS);}
+      code3 {o->slider(FL_UP_BOX);}
+    }
+    Fl_Box {} {
+      label {left: click = zoom out, drag = zoom in
+right click: Julia set} open
+      xywh {230 40 190 30} labelsize 10 align 24 deactivate
+    }
+    Fl_Slider {} {
+      label {iterations:}
+      user_data {&s} user_data_type {Drawing_Window*}
+      callback iterations_slider_cb open selected
+      xywh {70 55 160 15} type 1 box 7 labelsize 10 align 4 step 1 slider_size 0.1
+      code0 {o->bounds(1,s.d->MAX_ITERATIONS);}
+      code2 {o->value(s.d->DEFAULT_ITERATIONS);}
+      code3 {o->slider(FL_UP_BOX);}
+    }
+  }
+} 
diff --git a/test/menubar.cxx b/test/menubar.cxx
new file mode 100644
index 000000000..f1a8945e9
--- /dev/null
+++ b/test/menubar.cxx
@@ -0,0 +1,182 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+void test_cb(Fl_Widget* w, void*) {
+  Fl_Menu_* mw = (Fl_Menu_*)w;
+  const Fl_Menu_Item* m = mw->mvalue();
+  if (!m)
+    printf("NULL\n");
+  else if (m->shortcut())
+    printf("%s - %s\n", m->label(), fl_shortcut_label(m->shortcut()));
+  else
+    printf("%s\n", m->label());
+}
+
+void quit_cb(Fl_Widget*, void*) {exit(0);}
+
+Fl_Menu_Item hugemenu[100];
+
+Fl_Menu_Item menutable[] = {
+  {"foo",0,0,0,FL_MENU_INACTIVE},
+  {"&File",0,0,0,FL_SUBMENU},
+    {"&Open",	FL_ALT+'o', 0, 0, FL_MENU_INACTIVE},
+    {"&Close",	0,	0},
+    {"&Quit",	FL_ALT+'q', quit_cb, 0, FL_MENU_DIVIDER},
+    {"shortcut",'a'},
+    {"shortcut",FL_SHIFT+'a'},
+    {"shortcut",FL_CTRL+'a'},
+    {"shortcut",FL_CTRL+FL_SHIFT+'a'},
+    {"shortcut",FL_ALT+'a'},
+    {"shortcut",FL_ALT+FL_SHIFT+'a'},
+    {"shortcut",FL_ALT+FL_CTRL+'a'},
+    {"shortcut",FL_ALT+FL_SHIFT+FL_CTRL+'a', 0,0, FL_MENU_DIVIDER},
+  {"shortcut",'\r'/*FL_Enter*/},
+    {"shortcut",FL_CTRL+FL_Enter, 0,0, FL_MENU_DIVIDER},
+    {"shortcut",FL_F+1},
+    {"shortcut",FL_SHIFT+FL_F+1},
+    {"shortcut",FL_CTRL+FL_F+1},
+    {"shortcut",FL_SHIFT+FL_CTRL+FL_F+1},
+    {"shortcut",FL_ALT+FL_F+1},
+    {"shortcut",FL_ALT+FL_SHIFT+FL_F+1},
+    {"shortcut",FL_ALT+FL_CTRL+FL_F+1},
+    {"shortcut",FL_ALT+FL_SHIFT+FL_CTRL+FL_F+1, 0,0, FL_MENU_DIVIDER},
+    {"&Submenus", FL_ALT+'S',	0, (void*)"Submenu1", FL_SUBMENU},
+      {"A very long menu item"},
+      {"&submenu",FL_CTRL+'S',	0, (void*)"submenu2", FL_SUBMENU},
+	{"item 1"},
+	{"item 2"},
+	{"item 3"},
+	{"item 4"},
+	{0},
+      {"after submenu"},
+      {0},
+    {0},
+  {"&Edit",0,0,0,FL_SUBMENU},
+    {"Undo",	FL_ALT+'z',	0},
+    {"Redo",	FL_ALT+'r',	0, 0, FL_MENU_DIVIDER},
+    {"Cut",	FL_ALT+'x',	0},
+    {"Copy",	FL_ALT+'c',	0},
+    {"Paste",	FL_ALT+'v',	0},
+    {"Inactive",FL_ALT+'d',	0, 0, FL_MENU_INACTIVE},
+    {"Clear",	0,	0, 0, FL_MENU_DIVIDER},
+    {"Invisible",FL_ALT+'e',	0, 0, FL_MENU_INVISIBLE},
+    {"Preferences",0,	0},
+    {"Size",	0,	0},
+    {0},
+  {"&Checkbox",0,0,0,FL_SUBMENU},
+    {"&Alpha",	0,	0, (void *)1, FL_MENU_TOGGLE},
+    {"&Beta",	0,	0, (void *)2, FL_MENU_TOGGLE},
+    {"&Gamma",	0,	0, (void *)3, FL_MENU_TOGGLE},
+    {"&Delta",	0,	0, (void *)4, FL_MENU_TOGGLE|FL_MENU_VALUE},
+    {"&Epsilon",0,	0, (void *)5, FL_MENU_TOGGLE},
+    {"&Pi",	0,	0, (void *)6, FL_MENU_TOGGLE},
+    {"&Mu",	0,	0, (void *)7, FL_MENU_TOGGLE|FL_MENU_DIVIDER},
+    {"Red",	0,	0, (void *)1, FL_MENU_TOGGLE, 0, 0, 0, 1},
+    {"Black",	0,	0, (void *)1, FL_MENU_TOGGLE|FL_MENU_DIVIDER},
+    {"00",	0,	0, (void *)1, FL_MENU_TOGGLE},
+    {"000",	0,	0, (void *)1, FL_MENU_TOGGLE},
+    {0},
+  {"&Radio",0,0,0,FL_SUBMENU},
+    {"&Alpha",	0,	0, (void *)1, FL_MENU_RADIO},
+    {"&Beta",	0,	0, (void *)2, FL_MENU_RADIO},
+    {"&Gamma",	0,	0, (void *)3, FL_MENU_RADIO},
+    {"&Delta",	0,	0, (void *)4, FL_MENU_RADIO|FL_MENU_VALUE},
+    {"&Epsilon",0,	0, (void *)5, FL_MENU_RADIO},
+    {"&Pi",	0,	0, (void *)6, FL_MENU_RADIO},
+    {"&Mu",	0,	0, (void *)7, FL_MENU_RADIO|FL_MENU_DIVIDER},
+    {"Red",	0,	0, (void *)1, FL_MENU_RADIO},
+    {"Black",	0,	0, (void *)1, FL_MENU_RADIO|FL_MENU_DIVIDER},
+    {"00",	0,	0, (void *)1, FL_MENU_RADIO},
+    {"000",	0,	0, (void *)1, FL_MENU_RADIO},
+    {0},
+  {"&Font",0,0,0,FL_SUBMENU /*, 0, FL_BOLD, 20*/},
+    {"Normal",	0, 0, 0, 0, 0, 0, 14},
+    {"Bold",	0, 0, 0, 0, 0, FL_BOLD, 14},
+    {"Italic",	0, 0, 0, 0, 0, FL_ITALIC, 14},
+    {"BoldItalic",0,0,0, 0, 0, FL_BOLD+FL_ITALIC, 14},
+    {"Small",	0, 0, 0, 0, 0, FL_BOLD+FL_ITALIC, 10},
+    {"Emboss",	0, 0, 0, 0, FL_EMBOSSED_LABEL},
+    {"Engrave",	0, 0, 0, 0, FL_ENGRAVED_LABEL},
+    {"Shadow",	0, 0, 0, 0, FL_SHADOW_LABEL},
+    {"@->",	0, 0, 0, 0, FL_SYMBOL_LABEL},
+    {0},
+  {"E&mpty",0,0,0,FL_SUBMENU},
+    {0},
+  {"&Inactive", 0,	0, 0, FL_MENU_INACTIVE|FL_SUBMENU},
+    {"A very long menu item"},
+    {"A very long menu item"},
+    {0},
+  {"Invisible",0,	0, 0, FL_MENU_INVISIBLE|FL_SUBMENU},
+    {"A very long menu item"},
+    {"A very long menu item"},
+    {0},
+  {"&Huge", 0, 0, (void*)hugemenu, FL_SUBMENU_POINTER},
+  {"button",0, 0, 0, FL_MENU_TOGGLE},
+  {0}
+};
+
+Fl_Menu_Item pulldown[] = {
+  {"Red",	FL_ALT+'r'},
+  {"Green",	FL_ALT+'g'},
+  {"Blue",	FL_ALT+'b'},
+  {"Strange",	FL_ALT+'s'},
+  {"&Charm",	FL_ALT+'c'},
+  {"Truth",	FL_ALT+'t'},
+  {"Beauty",	FL_ALT+'b'},
+  {0}
+};
+
+#define WIDTH 600
+
+Fl_Menu_* menus[4];
+
+// turn MicroSoft style on/off
+void button_cb(Fl_Widget* w, void*) {
+  if (((Fl_Button*)w)->value()) {
+    Fl::set_color(FL_SELECTION_COLOR, 0, 36, 127);
+    Fl_Menu_::default_font(FL_HELVETICA);
+  } else {
+    Fl::set_color(FL_SELECTION_COLOR, 170, 170, 170);
+    Fl_Menu_::default_font(FL_HELVETICA_BOLD_ITALIC);
+  }
+  menus[0]->parent()->redraw();
+}
+
+int main(int argc, char **argv) {
+  for (int i=0; i<99; i++) {
+    char buf[100];
+    sprintf(buf,"item %d",i);
+    hugemenu[i].text = strdup(buf);
+  }
+  Fl_Window window(WIDTH,400);
+  Fl_Menu_Bar menubar(0,0,WIDTH,30); menubar.menu(menutable);
+  menubar.callback(test_cb);
+  menus[0] = &menubar;
+  Fl_Menu_Button mb1(100,100,120,25,"&menubutton"); mb1.menu(pulldown);
+  mb1.callback(test_cb);
+  menus[1] = &mb1;
+  Fl_Choice ch(300,100,80,25,"&choice:"); ch.menu(pulldown);
+  ch.callback(test_cb);
+  menus[2] = &ch;
+  Fl_Menu_Button mb(0,0,WIDTH,400,"&popup");
+  mb.type(Fl_Menu_Button::POPUP3);
+  mb.menu(menutable);
+  mb.callback(test_cb);
+  menus[3] = &mb;
+  Fl_Box b(200,200,200,100,"Press right button\nfor a pop-up menu");
+  Fl_Toggle_Button t(250,50,150,25,"MicroSoft Style");
+  t.callback(button_cb);
+  window.resizable(&mb);
+  window.end();
+  window.show(argc, argv);
+  return Fl::run();
+}
diff --git a/test/message.cxx b/test/message.cxx
new file mode 100644
index 000000000..1f339320d
--- /dev/null
+++ b/test/message.cxx
@@ -0,0 +1,18 @@
+#include 
+#include 
+#include 
+#include 
+
+int main(int, char **) {
+  fl_message("Spelling check sucessfull.");
+  fl_alert("Quantum fluctuations in the space-time continuim detected.");
+  printf("fl_ask returned %d\n",
+    fl_ask("Do you really want to?"));
+  printf("fl_choice returned %d\n",
+    fl_choice("Choose one of the following:","choice0","choice1","choice2"));
+  printf("fl_show_input returned \"%s\"\n",
+    fl_show_input("Please enter a string:", "this is the default value"));
+  printf("fl_password returned \"%s\"\n",
+    fl_password("Enter your password:"));
+  return 0;
+}
diff --git a/test/minimum.cxx b/test/minimum.cxx
new file mode 100644
index 000000000..f946639a6
--- /dev/null
+++ b/test/minimum.cxx
@@ -0,0 +1,49 @@
+// This is a test of the minimal update code.  The right slider has a
+// label that extends outside it's border, and the minimal update
+// assummes this does not happen.  Thus there is *supposed* to be
+// display errors when you move the right-most or any other slider.
+// If you *don't* see these errors, then the minimal update is
+// broken!!!
+
+// I cannot emphasize how important it is to test this and make sure
+// any changes have not broken the minimal update.  These sort of bugs
+// are extremely hard to fix and must be detected right away!
+
+// The reason it is important to fix this is that otherwise you will
+// swiftly end up with a toolkit that thinks it has to draw the window
+// 20 times each time the display changes.  I don't care how fast the
+// machine is, this is an insane waste of resources, and should be
+// stopped!
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int main(int argc, char **argv) {
+  Fl_Window *window = new Fl_Window(400,320,argv[0]);
+  window->resizable(*(new Fl_Box(FL_ENGRAVED_FRAME,10,10,300,300,
+"MINIMUM UPDATE TEST\n"
+"\n"
+"The slider on the right purposely\n"
+"draws outside it's boundaries.\n"
+"Moving it should leave old copies\n"
+"of the label.  These copies should\n"
+"*not* be erased by any actions\n"
+"other than hiding and showing\n"
+"of that portion of the window\n"
+"or changing the button that\n"
+"intesects them.")));
+
+  Fl_Slider *s;
+  s = new Fl_Slider(320,10,20,300,"Too_Big_Label");
+  s->align(0);
+
+  new Fl_Button(20,270,100,30,"Button");
+  new Fl_Return_Button(200,270,100,30,"Button");
+
+  window->show(argc, argv);
+  return Fl::run();
+}
diff --git a/test/navigation.cxx b/test/navigation.cxx
new file mode 100644
index 000000000..e6477852c
--- /dev/null
+++ b/test/navigation.cxx
@@ -0,0 +1,42 @@
+/* 	Silly test of navigation keys.
+	This is not a recommended method of laying out your panels!
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define WIDTH 600
+#define HEIGHT 300
+#define GRID 25
+
+int main(int argc, char **argv) {
+  if (argc > 1) srand(atoi(argv[1]));
+  Fl_Window window(WIDTH,HEIGHT,argv[0]);
+  window.end(); // don't auto-add children
+  for (int i = 0; i<10000; i++) {
+    // make up a random size of widget:
+    int x = rand()%(WIDTH/GRID+1) * GRID;
+    int y = rand()%(HEIGHT/GRID+1) * GRID;
+    int w = rand()%(WIDTH/GRID+1) * GRID;
+    if (w < x) {w = x-w; x-=w;} else {w = w-x;}
+    int h = rand()%(HEIGHT/GRID+1) * GRID;
+    if (h < y) {h = y-h; y-=h;} else {h = h-y;}
+    if (w < GRID || h < GRID || w < h) continue;
+    // find where to insert it and see if it intersects something:
+    Fl_Widget *i = 0;
+    int n; for (n=0; n < window.children(); n++) {
+      Fl_Widget *o = window.child(n);
+      if (xx()+o->w() && x+w>o->x() &&
+	  yy()+o->h() && y+h>o->y()) break;
+      if (!i && (y < o->y() || y == o->y() && x < o->x())) i = o;
+    }
+    // skip if intersection:
+    if (n < window.children()) continue;
+    window.insert(*(new Fl_Input(x,y,w,h)),i);
+  }
+  window.show();
+  return Fl::run();
+}
diff --git a/test/output.cxx b/test/output.cxx
new file mode 100644
index 000000000..5158f6311
--- /dev/null
+++ b/test/output.cxx
@@ -0,0 +1,74 @@
+// Test of Fl_Output and Fl_Multiline_Output
+
+#include 
+#include  // necessary for bug in mingw32?
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+Fl_Output *text;
+Fl_Multiline_Output *text2;
+Fl_Input *input;
+Fl_Value_Slider *fonts;
+Fl_Value_Slider *sizes;
+Fl_Window *window;
+
+void font_cb(Fl_Widget *,void *) {
+  text->textfont(int(fonts->value()));
+  text->redraw();
+  text2->textfont(int(fonts->value()));
+  text2->redraw();
+}
+
+void size_cb(Fl_Widget *,void *) {
+  text->textsize(int(sizes->value()));
+  text->redraw();
+  text2->textsize(int(sizes->value()));
+  text2->redraw();
+}
+
+void input_cb(Fl_Widget *,void *) {
+  text->value(input->value());
+  text2->value(input->value());
+}
+
+int main(int argc, char **argv) {
+  window = new Fl_Window(400,400);
+
+  input = new Fl_Input(50,0,350,25);
+  input->static_value("The quick brown fox\njumped over\nthe lazy dog.");
+  input->when(FL_WHEN_CHANGED);
+  input->callback(input_cb);
+
+  sizes = new Fl_Hor_Value_Slider(50,25,350,25,"Size");
+  sizes->align(FL_ALIGN_LEFT);
+  sizes->bounds(1,64);
+  sizes->step(1);
+  sizes->value(14);
+  sizes->callback(size_cb);
+
+  fonts = new Fl_Hor_Value_Slider(50,50,350,25,"Font");
+  fonts->align(FL_ALIGN_LEFT);
+  fonts->bounds(0,15);
+  fonts->step(1);
+  fonts->value(0);
+  fonts->callback(font_cb);
+
+  text2 = new Fl_Multiline_Output(100,150,200,100,"Fl_Multiline_Output");
+  text2->value(input->value());
+  text2->align(FL_ALIGN_BOTTOM);
+  window->resizable(text2);
+
+  text = new Fl_Output(100,280,200,30,"Fl_Output");
+  text->value(input->value());
+  text->align(FL_ALIGN_BOTTOM);
+
+  window->forms_end();
+  window->show(argc,argv);
+  return Fl::run();
+}
diff --git a/test/overlay.cxx b/test/overlay.cxx
new file mode 100644
index 000000000..0fd52315e
--- /dev/null
+++ b/test/overlay.cxx
@@ -0,0 +1,57 @@
+/*	Test the Fl_Overlay_Window	*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int width=10,height=10;
+
+class overlay : public Fl_Overlay_Window {
+public:
+  overlay(int w,int h) : Fl_Overlay_Window(w,h) {}
+  void draw_overlay();
+};
+
+void overlay::draw_overlay() {
+  fl_color(FL_RED); fl_rect((w()-width)/2,(h()-height)/2,width,height);
+}
+
+overlay *ovl;
+
+void bcb1(Fl_Widget *,void *) {width+=20; ovl->redraw_overlay();}
+void bcb2(Fl_Widget *,void *) {width-=20; ovl->redraw_overlay();}
+void bcb3(Fl_Widget *,void *) {height+=20; ovl->redraw_overlay();}
+void bcb4(Fl_Widget *,void *) {height-=20; ovl->redraw_overlay();}
+
+int arg(int, char **argv, int& i) {
+  Fl_Color n = (Fl_Color)atoi(argv[i]);
+  if (n<=0) return 0;
+  i++;
+  uchar r,g,b;
+  Fl::get_color(n,r,g,b);
+  Fl::set_color(FL_RED,r,g,b);
+  return i;
+}
+
+int main(int argc, char **argv) {
+  int i=0; Fl::args(argc,argv,i,arg);
+  ovl = new overlay(400,400);
+  Fl_Button *b;
+  b = new Fl_Button(50,50,100,100,"wider\n(a)");
+  b->callback(bcb1); b->shortcut('a');
+  b = new Fl_Button(250,50,100,100,"narrower\n(b)");
+  b->callback(bcb2); b->shortcut('b');
+  b = new Fl_Button(50,250,100,100,"taller\n(c)");
+  b->callback(bcb3); b->shortcut('c');
+  b = new Fl_Button(250,250,100,100,"shorter\n(d)");
+  b->callback(bcb4); b->shortcut('d');
+  ovl->resizable(ovl);
+  ovl->end();
+  ovl->show(argc,argv);
+  ovl->redraw_overlay();
+  return Fl::run();
+}
diff --git a/test/pack.cxx b/test/pack.cxx
new file mode 100644
index 000000000..72c715a04
--- /dev/null
+++ b/test/pack.cxx
@@ -0,0 +1,89 @@
+// Rather crude test of the Fl_Pack object.
+// Changing the type() of an Fl_Pack after it is displayed is not supported
+// so I have to do a lot of resizing of things before that.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+Fl_Pack *pack;
+Fl_Scroll *scroll;
+
+void type_cb(Fl_Light_Button*, long v) {
+  for (int i = 0; i < pack->children(); i++) {
+    Fl_Widget* o = pack->child(i);
+    o->resize(0,0,25,25);
+  }
+  pack->resize(scroll->x(),scroll->y(),scroll->w(),scroll->h());
+  pack->parent()->redraw();
+  pack->type(uchar(v));
+  pack->redraw();
+}
+
+void spacing_cb(Fl_Value_Slider*o, long) {
+  pack->spacing(int(o->value()));
+  scroll->redraw();
+}
+
+int main(int argc, char **argv) {
+ Fl_Window *w;
+ {Fl_Window* o = new Fl_Window(365, 525);
+  w = o;
+  scroll = new Fl_Scroll(10,10,345,285);
+ {Fl_Pack* o = new Fl_Pack(10, 10, 345, 285);
+  pack = o;
+  o->box(FL_DOWN_FRAME);
+  //o->box(FL_ENGRAVED_FRAME);
+ new Fl_Button(35, 35, 25, 25, "b1");
+ new Fl_Button(45, 45, 25, 25, "b2");
+ new Fl_Button(55, 55, 25, 25, "b3");
+ new Fl_Button(65, 65, 25, 25, "b4");
+ new Fl_Button(75, 75, 25, 25, "b5");
+ new Fl_Button(85, 85, 25, 25, "b6");
+ new Fl_Button(95, 95, 25, 25, "b7");
+ new Fl_Button(105, 105, 25, 25, "b8");
+ new Fl_Button(115, 115, 25, 25, "b9");
+ new Fl_Button(125, 125, 25, 25, "b10");
+ new Fl_Button(135, 135, 25, 25, "b11");
+ new Fl_Button(145, 145, 25, 25, "b12");
+ new Fl_Button(155, 155, 25, 25, "b13");
+ new Fl_Button(165, 165, 25, 25, "b14");
+ new Fl_Button(175, 175, 25, 25, "b15");
+ new Fl_Button(185, 185, 25, 25, "b16");
+ new Fl_Button(195, 195, 25, 25, "b17");
+ new Fl_Button(205, 205, 25, 25, "b18");
+ new Fl_Button(215, 215, 25, 25, "b19");
+ new Fl_Button(225, 225, 25, 25, "b20");
+ new Fl_Button(235, 235, 25, 25, "b21");
+ new Fl_Button(245, 245, 25, 25, "b22");
+ new Fl_Button(255, 255, 25, 25, "b23");
+ new Fl_Button(265, 265, 25, 25, "b24");
+  o->end();
+  w->resizable(o);
+ }
+ scroll->end();
+ {Fl_Light_Button* o = new Fl_Light_Button(10, 325, 175, 25, "HORIZONTAL");
+ o->type(FL_RADIO_BUTTON);
+  o->callback((Fl_Callback*)type_cb, (void*)(Fl_Pack::HORIZONTAL));
+ }
+ {Fl_Light_Button* o = new Fl_Light_Button(10, 350, 175, 25, "VERTICAL");
+ o->type(FL_RADIO_BUTTON);
+ o->value(1);
+  o->callback((Fl_Callback*)type_cb, (void*)(Fl_Pack::VERTICAL));
+ }
+ {Fl_Value_Slider* o = new Fl_Value_Slider(50,375, 295,25,"spacing:");
+ o->align(FL_ALIGN_LEFT);
+ o->type(FL_HORIZONTAL);
+ o->range(0,30);
+ o->step(1);
+ o->callback((Fl_Callback*)spacing_cb);
+ }
+ w->end();
+ }
+ w->show(argc, argv);
+ return Fl::run();
+}
diff --git a/test/pixmap.cxx b/test/pixmap.cxx
new file mode 100644
index 000000000..d0ced9c4f
--- /dev/null
+++ b/test/pixmap.cxx
@@ -0,0 +1,64 @@
+//	test how pixmap label type draws
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "porsche.xpm"
+
+#include 
+
+Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb;
+Fl_Button *b;
+Fl_Window *w;
+
+void button_cb(Fl_Widget *,void *) {
+  int i = 0;
+  if (leftb->value()) i |= FL_ALIGN_LEFT;
+  if (rightb->value()) i |= FL_ALIGN_RIGHT;
+  if (topb->value()) i |= FL_ALIGN_TOP;
+  if (bottomb->value()) i |= FL_ALIGN_BOTTOM;
+  if (insideb->value()) i |= FL_ALIGN_INSIDE;
+  b->align(i);
+  w->redraw();
+}
+
+int dvisual = 0;
+int arg(int, char **argv, int &i) {
+  if (argv[i][1] == '8') {dvisual = 1; i++; return 1;}
+  return 0;
+}
+
+#include 
+
+Fl_Multi_Label multi = {
+  0, "This is the text", 0, FL_NORMAL_LABEL
+};
+
+int main(int argc, char **argv) {
+  int i = 1;
+  if (Fl::args(argc,argv,i,arg) < argc)
+    Fl::fatal(" -8 # : use default visual\n%s\n",Fl::help);
+
+  Fl_Window window(400,400); ::w = &window;
+  Fl_Button b(140,160,120,120,0); ::b = &b;
+  (new Fl_Pixmap(porsche_xpm))->label(&b);
+  multi.labela = b.label(); multi.typea = b.labeltype(); multi.label(&b);
+  leftb = new Fl_Toggle_Button(50,75,50,25,"left");
+  leftb->callback(button_cb);
+  rightb = new Fl_Toggle_Button(100,75,50,25,"right");
+  rightb->callback(button_cb);
+  topb = new Fl_Toggle_Button(150,75,50,25,"top");
+  topb->callback(button_cb);
+  bottomb = new Fl_Toggle_Button(200,75,50,25,"bottom");
+  bottomb->callback(button_cb);
+  insideb = new Fl_Toggle_Button(250,75,50,25,"inside");
+  insideb->callback(button_cb);
+  if (!dvisual) Fl::visual(FL_RGB);
+  window.resizable(window);
+  window.end();
+  window.show(argc,argv);
+  return Fl::run();
+}
diff --git a/test/pixmap_browser.cxx b/test/pixmap_browser.cxx
new file mode 100644
index 000000000..ae5e6345d
--- /dev/null
+++ b/test/pixmap_browser.cxx
@@ -0,0 +1,141 @@
+// More complex and hacked pixmap demo.
+
+// On purpose, I do NOT provide a fltk method to turn a file
+// into a pixmap.  This program uses a rather simplistic one.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+Fl_Box *b;
+Fl_Window *w;
+
+char **data;
+int sizeofdata;
+int numlines;
+
+static int hexdigit(int x) {
+  if (isdigit(x)) return x-'0';
+  if (isupper(x)) return x-'A'+10;
+  if (islower(x)) return x-'a'+10;
+  return 20;
+}
+
+int load_file(const char *name) {
+  FILE *f = fopen(name,"r");
+  if (!f) {
+    fl_show_message("Can't open",name,strerror(errno));
+    return 0;
+  }
+  if (data) {
+    for (int i=numlines; i--;) delete[] data[i];
+  }
+  char buffer[1024];
+  int i = 0;
+  while (fgets(buffer,1024,f)) {
+    if (buffer[0] != '\"') continue;
+    char *p = buffer;
+    char *q = buffer+1;
+    while (*q != '\"') {
+      if (*q == '\\') switch (*++q) {
+      case '\n':
+	fgets(q,(buffer+1024)-q,f); break;
+      case 0:
+	break;
+      case 'x': {
+	q++;
+	int n = 0;
+	for (int x = 0; x < 3; x++) {
+	  int d = hexdigit(*q);
+	  if (d > 15) break;
+	  n = (n<<4)+d;
+	  q++;
+	}
+	*p++ = n;
+      } break;
+      default: {
+	int c = *q++;
+	if (c>='0' && c<='7') {
+	  c -= '0';
+	  for (int x=0; x<2; x++) {
+	    int d = hexdigit(*q);
+	    if (d>7) break;
+	    c = (c<<3)+d;
+	    q++;
+	  }
+	}
+	*p++ = c;
+      } break;
+      } else {
+	*p++ = *q++;
+      }
+    }
+    *p++ = 0;
+    if (i >= sizeofdata) {
+      sizeofdata = 2*sizeofdata+100;
+      char **newdata = new char *[sizeofdata];
+      for (int j=0; jlabel(b);
+  w->redraw();
+}
+
+static char name[1024];
+
+void file_cb(const char *n) {
+  if (!strcmp(name,n)) return;
+  if (!load_file(n)) return;
+  strcpy(name,n);
+  w->label(name);
+  newpixmap();
+}
+
+void button_cb(Fl_Widget *,void *) {
+  fl_file_chooser_callback(file_cb);
+  fl_file_chooser("XPM file","*.xpm",name);
+  fl_file_chooser_callback(0);
+}
+
+int dvisual = 0;
+int arg(int, char **argv, int &i) {
+  if (argv[i][1] == '8') {dvisual = 1; i++; return 1;}
+  return 0;
+}
+
+int main(int argc, char **argv) {
+  int i = 1;
+  if (Fl::args(argc,argv,i,arg) < argc)
+    Fl::fatal(" -8 # : use default visual\n%s\n",Fl::help);
+
+  Fl_Window window(400,400); ::w = &window;
+  Fl_Box b(0,0,window.w(),window.h()); ::b = &b;
+  Fl_Button button(5,5,100,35,"load");
+  button.callback(button_cb);
+  if (!dvisual) Fl::visual(FL_RGB);
+  window.resizable(window);
+  window.show(argc,argv);
+  return Fl::run();
+}
diff --git a/test/porsche.xpm b/test/porsche.xpm
new file mode 100644
index 000000000..1dc60e9b6
--- /dev/null
+++ b/test/porsche.xpm
@@ -0,0 +1,71 @@
+/* XPM */
+static char * porsche_xpm[] = {
+"64 64 4 1",
+" 	c #background",
+".	c #000000000000",
+"X	c #ffd100",
+"o	c #FFFF00000000",
+"                                                                ",
+"                   ..........................                   ",
+"              .....................................             ",
+"        ............XXXXXXXXXXXXXXXXXXXXXXXX............        ",
+"        ......XXXXXXX...XX...XXXXXXXX...XXXXXXXXXX......        ",
+"        ..XXXXXXXXXX..X..XX..XXXX.XXXX..XXXXXXXXXXXXXX..        ",
+"        ..XXXXXXXXXX..X..XX..XXX..XXXX..X...XXXXXXXXXX..        ",
+"        ..XXXXXXXXXX..XXXXX..XX.....XX..XX.XXXXXXXXXXX..        ",
+"        ..XXXXXXXXX.....XXX..XXX..XXXX..X.XXXXXXXXXXXX..        ",
+"        ..XXXXXXXXXX..XXXXX..XXX..XXXX....XXXXXXXXXXXX..        ",
+"        ..XXXXXXXXXX..XXXXX..XXX..XXXX..X..XXXXXXXXXXX..        ",
+"        ..XXXXXXXXXX..XXXXX..XXX..X.XX..XX..XXXXXXXXXX..        ",
+"        ..XXXXXXXXX....XXX....XXX..XX....XX..XXXXXXXXX..        ",
+"        ..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX..        ",
+"        ..XXXXXXXXX..........................XXXXXXXXX..        ",
+"        ..XXX.......XXXXXXXXXXX...................XXXX..        ",
+"        ......XX.XXX.XXX..XXXXX.........................        ",
+"        ..XXXXX.XXX.XXX.XXXX.XX.........................        ",
+"        ..XXXX.XXX.XX.......XXX.........................        ",
+"        ..XXXX.......XXXXXX..XX..ooooooooooooooooooooo..        ",
+"        ..X.....XXXXXXXXXXXXXXX..ooooooooooooooooooooo..        ",
+"        ..X...XXXXXXXXXXXXXXXXX..ooooooooooooooooooooo..        ",
+"        ..X..XXXXXXX.XX.XXXXXXX..ooooooooooooooooooooo..        ",
+"        ..XXXXX.XXX.XX.XXXXXXXX..ooooooooooooooooooooo..        ",
+"        ..XXXX.XXX.XX.XX................................        ",
+"        ..XXXX.X.........X....X.X.X.....................        ",
+"        ..XXXX...XXXXXXX.X..X...X.X.X.X.................        ",
+"        ..X....XXXXXXXXXX.X...X.X.X.....................        ",
+"        ..X...XXXXXXXXXX.XXXXXXXXXXXXXX.................        ",
+"        ..X..XXXXXX.XX.X.XXX...XXXXXXXX.................        ",
+"        ..XXXXX.XX.XX.XX.XX.....XXXXXXX.oooooooooooooo..        ",
+"        ..XXXX.XX.XX.XX..XX.X...XXXXX.X.oooooooooooooo..        ",
+"        ..XXXX.X.......X.XXXX...XXXX..X.oooooooooooooo..        ",
+"        ..X......XXXXXX..XXXX...XXXX..X.oooooooooooooo..        ",
+"        ..X...XXXXXXXXXX.XXX.....XXX.XX.oooooooooooooo..        ",
+"        ..X..XXXXXXXXXXX.X...........XX.oooooooooooooo..        ",
+"        .................X.X.........XX.................        ",
+"        .................X.X.XXXX....XX.XXXXXXXXXXXXXX..        ",
+"        .................XXX.XXXXX.X.XX.XXX.XX.XXXXXXX..        ",
+"         ................XXXX.XXX..X..X.XX.XX.XXX.XXX..         ",
+"         ................XXXXXXXX.XX.XX.X.XX.XXX.XXXX..         ",
+"         .................XXXXXX.XX.XX.X..........XXX..         ",
+"          ..oooooooooooooo.XXXXXXXXXX....XXXXXXXX..X..          ",
+"          ..ooooooooooooooo.XXXXXXXX....XXXXXXXXXXXX..          ",
+"           ..ooooooooooooooo........XXXXXXX.XX.XXXX..           ",
+"           ..oooooooooooooooooo..XXXXX.XXX.XX.XX.XX..           ",
+"            ..ooooooooooooooooo..XXXX.XXX.XX.XX.XX..            ",
+"            ..ooooooooooooooooo..XXX.XX........XXX..            ",
+"             ....................XXX....XXXXXX..X..             ",
+"              ...................XX...XXXXXXXXXXX.              ",
+"              ...................X...XXXXXXXXXXX..              ",
+"               ..................X..XXXX.XXXXXX..               ",
+"                .................XXX.XX.XX.XXX..                ",
+"                 ................XX.XX.XX.XXX..                 ",
+"                  ..ooooooooooo..XX.......XX..                  ",
+"                   ..oooooooooo..X...XXXX.X..                   ",
+"                    ..ooooooooo..X..XXXXXX..                    ",
+"                     ...ooooooo..X..XXXX...                     ",
+"                      ....ooooo..XXXXX....                      ",
+"                        ....ooo..XXX....                        ",
+"                          ....o..X....                          ",
+"                            ........                            ",
+"                              ....                              ",
+"                                                                "};
diff --git a/test/porsche1.xpm b/test/porsche1.xpm
new file mode 100644
index 000000000..cb53d0e4b
--- /dev/null
+++ b/test/porsche1.xpm
@@ -0,0 +1,76 @@
+/* XPM */
+static char * porsche[] = {
+/* width height ncolors chars_per_pixel */
+"64 64 -4 1 ",
+/* colormap */
+"\
+ \x50\x50\x80\
+.\xff\xff\0\
+r\xff\x00\0\
+b\0\0\0",
+/* pixels */
+"        bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb        ",
+"        bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb        ",
+"        bb............................................bb        ",
+"        bb.......................bbbbbbb.bb...........bb        ",
+"        bb.......................bbbbbbb.bb...........bb        ",
+"        bb......bbb...bb..bb.....bb......bb...........bb        ",
+"        bb......bbb...bb..bb.....bb......bb...........bb        ",
+"        bb.......bb.......bbbb...bbbbb...bb...........bb        ",
+"        bb.......bb...bb..bbbbb..bbbbb...bb...........bb        ",
+"        bb.......bb...bb..bb.bb..bb......bb...........bb        ",
+"        bb......bbbb..bb..bbbbb..bb......bbbbbb.......bb        ",
+"        bb......bbbb..bb..bbbb...bb......bbbbbb.......bb        ",
+"        bb............................................bb        ",
+"        bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb        ",
+"        bb.....................bbbbbbbbbbbbbbbbbbbbbbbbb        ",
+"        bb......b...b...bb.....bbbbbbbbbbbbbbbbbbbbbbbbb        ",
+"        bb.....b...b...b....b..bbbbbbbbbbbbbbbbbbbbbbbbb        ",
+"        bb....bb..bb.bbbbbbb...bbbbbbbbbbbbbbbbbbbbbbbbb        ",
+"        bb...bbbbbbbb......bb..bbrrrrrrrrrrrrrrrrrrrrrbb        ",
+"        bb..bbbb...............bbrrrrrrrrrrrrrrrrrrrrrbb        ",
+"        bb.bbb.................bbrrrrrrrrrrrrrrrrrrrrrbb        ",
+"        bb..........b..b.......bbrrrrrrrrrrrrrrrrrrrrrbb        ",
+"        bb.....b...b..b........bbrrrrrrrrrrrrrrrrrrrrrbb        ",
+"        bb....b...b..b..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb        ",
+"        bb....b.bbbbbbbbb..............bbbbbbbbbbbbbbbbb        ",
+"        bb...bbbb.......bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb        ",
+"        bb..bbb.........b..............bbbbbbbbbbbbbbbbb        ",
+"        bb.bbb..........b...bbb........bbbbbbbbbbbbbbbbb        ",
+"        bb.........b..b.b..bbbbb.......bbbbbbbbbbbbbbbbb        ",
+"        bb.....b..b..b..b..b.bbb.....b.brrrrrrrrrrrrrrbb        ",
+"        bb....b..b..b..bb....bbb....bb.brrrrrrrrrrrrrrbb        ",
+"        bb...bb.bbbbbbb.b....bbb....bb.brrrrrrrrrrrrrrbb        ",
+"        bb..bbbbb......bb...bbbbb...b..brrrrrrrrrrrrrrbb        ",
+"        bb.bbb..........b.bbbbbbbbbbb..brrrrrrrrrrrrrrbb        ",
+"        bb..............b.b.bbbbbbbbb..brrrrrrrrrrrrrrbb        ",
+"        bbbbbbbbbbbbbbbbb.b.b....bbbb..bbbbbbbbbbbbbbbbb        ",
+"        bbbbbbbbbbbbbbbbb...b.....b.b..b..............bb        ",
+"        bbbbbbbbbbbbbbbbb........bb.bb.b...b..b.......bb        ",
+"         bbbbbbbbbbbbbbbb........b..b..b..b..b...b...bb         ",
+"         bbbbbbbbbbbbbbbb.......b..b...b.b..b...b....bb         ",
+"         bbbbbbbbbbbbbbbbb............b.bbbbbbbbbb...bb         ",
+"          bbrrrrrrrrrrrrrrb..........bbbb........bb.bb          ",
+"          bbrrrrrrrrrrrrrrrb........bbbb............bb          ",
+"           bbrrrrrrrrrrrrrrrbbbbbbbb.......b..b....bb           ",
+"           bbrrrrrrrrrrrrrrrrrrbb.....b...b..b..b..bb           ",
+"            bbrrrrrrrrrrrrrrrrrbb....b...b..b..b..bb            ",
+"            bbrrrrrrrrrrrrrrrrrbb...bb.bbbbbbbb...bb            ",
+"             bbbbbbbbbbbbbbbbbbbb...bbbb......bb.bb             ",
+"              bbbbbbbbbbbbbbbbbbb..bbb...........b              ",
+"              bbbbbbbbbbbbbbbbbbb.bbb...........bb              ",
+"               bbbbbbbbbbbbbbbbbb..............bb               ",
+"                bbbbbbbbbbbbbbbbb...b.b.b.....bb                ",
+"                 bbbbbbbbbbbbbbbb..b.b.b..b..bb                 ",
+"                  bbrrrrrrrrrrrbb..bbbbbbb..bb                  ",
+"                   bbrrrrrrrrrrbb.bbb....b.bb                   ",
+"                    bbrrrrrrrrrbb.bb......bb                    ",
+"                     bbbrrrrrrrbb.......bbb                     ",
+"                      bbbbrrrrrbb.....bbbb                      ",
+"                        bbbbrrrbb...bbbb                        ",
+"                          bbbbrbb.bbbb                          ",
+"                            bbbbbbbb                            ",
+"                              bbbb                              ",
+"                               bb                               ",
+"                                                                "
+} ;
diff --git a/test/radio.C b/test/radio.C
new file mode 100644
index 000000000..ab15d3e8f
--- /dev/null
+++ b/test/radio.C
@@ -0,0 +1,67 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+#include "radio.H"
+
+int main(int argc, char **argv) {
+ Fl_Window *w;
+ {Fl_Window* o = new Fl_Window(462, 453);
+  w = o;
+ new Fl_Button(20, 10, 160, 30, "Fl_Button");
+ new Fl_Return_Button(20, 50, 160, 30, "Fl_Return_Button");
+ new Fl_Light_Button(20, 90, 160, 30, "Fl_Light_Button");
+ {Fl_Check_Button* o = new Fl_Check_Button(20, 130, 160, 30, "Fl_Check_Button");
+  o->box(FL_UP_BOX);
+  o->down_box(FL_DIAMOND_DOWN_BOX);
+ }
+ {Fl_Round_Button* o = new Fl_Round_Button(20, 170, 160, 30, "Fl_Round_Button");
+  o->box(FL_UP_BOX);
+  o->down_box(FL_ROUND_DOWN_BOX);
+ }
+ {Fl_Group* o = new Fl_Group(190, 10, 70, 120);
+  o->box(FL_THIN_UP_FRAME);
+ {Fl_Check_Button* o = new Fl_Check_Button(190, 10, 70, 30, "radio");
+  o->type(102);
+  o->down_box(FL_DIAMOND_DOWN_BOX);
+ }
+ {Fl_Check_Button* o = new Fl_Check_Button(190, 40, 70, 30, "radio");
+  o->type(102);
+  o->down_box(FL_DIAMOND_DOWN_BOX);
+ }
+ {Fl_Check_Button* o = new Fl_Check_Button(190, 70, 70, 30, "radio");
+  o->type(102);
+  o->down_box(FL_DIAMOND_DOWN_BOX);
+ }
+ {Fl_Check_Button* o = new Fl_Check_Button(190, 100, 70, 30, "radio");
+  o->type(102);
+  o->down_box(FL_DIAMOND_DOWN_BOX);
+ }
+  o->end();
+ }
+ {Fl_Group* o = new Fl_Group(270, 10, 90, 115);
+  o->box(FL_THIN_UP_BOX);
+ {Fl_Button* o = new Fl_Button(280, 20, 20, 20, "radio");
+  o->type(102);
+  o->color2(1);
+  o->align(8);
+ }
+ {Fl_Button* o = new Fl_Button(280, 45, 20, 20, "radio");
+  o->type(102);
+  o->color2(1);
+  o->align(8);
+ }
+ {Fl_Button* o = new Fl_Button(280, 70, 20, 20, "radio");
+  o->type(102);
+  o->color2(1);
+  o->align(8);
+ }
+ {Fl_Button* o = new Fl_Button(280, 95, 20, 20, "radio");
+  o->type(102);
+  o->color2(1);
+  o->align(8);
+ }
+  o->end();
+ }
+ w->end();
+ }
+ w->show(argc, argv);
+ return Fl::run();
+}
diff --git a/test/radio.H b/test/radio.H
new file mode 100644
index 000000000..534a8870a
--- /dev/null
+++ b/test/radio.H
@@ -0,0 +1,9 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
diff --git a/test/radio.fl b/test/radio.fl
new file mode 100644
index 000000000..360ed58fc
--- /dev/null
+++ b/test/radio.fl
@@ -0,0 +1,72 @@
+# data file for FL User Interface Designer (fluid)
+version 0.99 
+gridx 10 
+gridy 5 
+snap 3
+Function {} {open
+} {
+  Fl_Window {} {open selected
+    xywh {447 255 462 453}
+  } {
+    Fl_Button {} {
+      label Fl_Button open
+      xywh {20 10 160 30}
+    }
+    Fl_Return_Button {} {
+      label Fl_Return_Button open
+      xywh {20 50 160 30}
+    }
+    Fl_Light_Button {} {
+      label Fl_Light_Button open
+      xywh {20 90 160 30}
+    }
+    Fl_Check_Button {} {
+      label Fl_Check_Button open
+      xywh {20 130 160 30} box 2
+    }
+    Fl_Round_Button {} {
+      label Fl_Round_Button open
+      xywh {20 170 160 30} box 2
+    }
+    Fl_Group {} {
+      xywh {190 10 70 120} box 8
+    } {
+      Fl_Check_Button {} {
+        label radio open
+        xywh {190 10 70 30} type 102
+      }
+      Fl_Check_Button {} {
+        label radio open
+        xywh {190 40 70 30} type 102
+      }
+      Fl_Check_Button {} {
+        label radio open
+        xywh {190 70 70 30} type 102
+      }
+      Fl_Check_Button {} {
+        label radio open
+        xywh {190 100 70 30} type 102
+      }
+    }
+    Fl_Group {} {open
+      xywh {270 10 90 115} box 6
+    } {
+      Fl_Button {} {
+        label radio open
+        xywh {280 20 20 20} type 102 color {47 1} align 8
+      }
+      Fl_Button {} {
+        label radio open
+        xywh {280 45 20 20} type 102 color {47 1} align 8
+      }
+      Fl_Button {} {
+        label radio open
+        xywh {280 70 20 20} type 102 color {47 1} align 8
+      }
+      Fl_Button {} {
+        label radio open
+        xywh {280 95 20 20} type 102 color {47 1} align 8
+      }
+    }
+  }
+} 
diff --git a/test/resize.C b/test/resize.C
new file mode 100644
index 000000000..11185a2d0
--- /dev/null
+++ b/test/resize.C
@@ -0,0 +1,71 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+#include "resize.H"
+
+static void callback_1008ed30(Fl_Button* o, void*) {
+Fl_Window* w = o->window();
+w->position(w->x()-50,w->y());
+}
+
+static void callback_1008ee58(Fl_Button* o, void*) {
+Fl_Window* w = o->window();
+w->position(w->x(),w->y()+50);
+}
+
+static void callback_1008ef40(Fl_Button* o, void*) {
+Fl_Window* w = o->window();
+w->position(w->x()+50,w->y());
+}
+
+static void callback_1008f048(Fl_Button* o, void*) {
+Fl_Window* w = o->window();
+w->position(w->x(),w->y()-50);
+}
+
+static void callback_1008f130(Fl_Button* o, void*) {
+Fl_Window* w = o->window();
+w->size(w->w()+50, w->h()+50);
+}
+
+static void callback_1008f360(Fl_Button* o, void*) {
+Fl_Window* w = o->window();
+w->size(w->w()/2+1, w->h()/2+1);
+}
+
+int main(int argc, char **argv) {
+ Fl_Window *w;
+ {Fl_Window* o = new Fl_Window(366, 261);
+  w = o;
+  Fl_Group::current()->resizable(o);
+ {Fl_Button* o = new Fl_Button(20, 40, 40, 40, "@<-");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->callback((Fl_Callback*)callback_1008ed30);
+ }
+ {Fl_Button* o = new Fl_Button(60, 80, 40, 40, "@2->");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->callback((Fl_Callback*)callback_1008ee58);
+ }
+ {Fl_Button* o = new Fl_Button(100, 40, 40, 40, "@->");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->callback((Fl_Callback*)callback_1008ef40);
+ }
+ {Fl_Button* o = new Fl_Button(60, 0, 40, 40, "@8->");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->callback((Fl_Callback*)callback_1008f048);
+ }
+ {Fl_Button* o = new Fl_Button(30, 130, 110, 40, "grow");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->labelfont(1);
+  o->labelsize(18);
+  o->callback((Fl_Callback*)callback_1008f130);
+ }
+ {Fl_Button* o = new Fl_Button(30, 190, 110, 40, "shrink");
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->labelfont(1);
+  o->labelsize(18);
+  o->callback((Fl_Callback*)callback_1008f360);
+ }
+ w->end();
+ }
+ w->show(argc, argv);
+ return Fl::run();
+}
diff --git a/test/resize.H b/test/resize.H
new file mode 100644
index 000000000..e728ef05f
--- /dev/null
+++ b/test/resize.H
@@ -0,0 +1,4 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+#include 
+#include 
+#include 
diff --git a/test/resize.fl b/test/resize.fl
new file mode 100644
index 000000000..7524bc79e
--- /dev/null
+++ b/test/resize.fl
@@ -0,0 +1,48 @@
+# data file for FL User Interface Designer (fluid)
+version 0.99 
+gridx 10 
+gridy 10 
+snap 3
+Function {} {open
+} {
+  Fl_Window {} {open selected
+    xywh {490 248 366 261} resizable
+  } {
+    Fl_Button {} {
+      label {@<-}
+      callback {Fl_Window* w = o->window();
+w->position(w->x()-50,w->y());} open
+      xywh {20 40 40 40} labeltype 2
+    }
+    Fl_Button {} {
+      label {@2->}
+      callback {Fl_Window* w = o->window();
+w->position(w->x(),w->y()+50);} open
+      xywh {60 80 40 40} labeltype 2
+    }
+    Fl_Button {} {
+      label {@->}
+      callback {Fl_Window* w = o->window();
+w->position(w->x()+50,w->y());} open
+      xywh {100 40 40 40} labeltype 2
+    }
+    Fl_Button {} {
+      label {@8->}
+      callback {Fl_Window* w = o->window();
+w->position(w->x(),w->y()-50);} open
+      xywh {60 0 40 40} labeltype 2
+    }
+    Fl_Button {} {
+      label grow
+      callback {Fl_Window* w = o->window();
+w->size(w->w()+50, w->h()+50);} open
+      xywh {30 130 110 40} labeltype 2 labelfont 1 labelsize 18
+    }
+    Fl_Button {} {
+      label shrink
+      callback {Fl_Window* w = o->window();
+w->size(w->w()/2+1, w->h()/2+1);} open
+      xywh {30 190 110 40} labeltype 2 labelfont 1 labelsize 18
+    }
+  }
+} 
diff --git a/test/resizebox.cxx b/test/resizebox.cxx
new file mode 100644
index 000000000..a8184e380
--- /dev/null
+++ b/test/resizebox.cxx
@@ -0,0 +1,74 @@
+// Test the position of the resizebox
+
+#define W1 (big ? 60 : 40)
+#define B 0
+#define W3 (5*W1+6*B)
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+Fl_Single_Window *window;
+Fl_Box *box;
+
+int big = 0;
+
+void b_cb(Fl_Widget *,long w) {
+  if (window->w() != W3 || window->h() != W3) {
+    fl_message("Put window back to minimum size before changing");
+    return;
+  }
+  window->init_sizes();
+  switch (w) {
+  case 0: box->hide(); window->box(FL_FLAT_BOX); window->resizable(0); return;
+  case 8: box->resize(W1+B,W1,2*W1,B); break;
+  case 2: box->resize(W1+B,W1+B+2*W1,2*W1,B); break;
+  case 4: box->resize(W1+B,W1,B,2*W1); break;
+  case 6: box->resize(W1+B+2*W1,W1+B,B,2*W1); break;
+  }
+  window->box(FL_NO_BOX);
+  if (w == 6 || w == 4)
+    box->label("re\nsiz\nab\nle");
+  else box->label("resizable");
+  box->show();
+  window->resizable(box);
+  window->redraw();
+}
+
+int main(int argc, char **argv) {
+  window = new Fl_Single_Window(W3,W3);
+  window->box(FL_NO_BOX);
+  Fl_Box *n;
+  for (int x = 0; x<4; x++) for (int y = 0; y<4; y++) {
+    if ((x==1 || x==2) && (y==1 || y==2)) continue;
+    n = new Fl_Box(FL_FRAME_BOX,x*(B+W1)+B,y*(B+W1)+B,W1,W1,0);
+    n->color(x+y+8);
+  }
+  n = new Fl_Box(FL_FRAME_BOX,B,4*W1+5*B,4*W1+3*B,W1,0);
+  n->color(12);
+  n = new Fl_Box(FL_FRAME_BOX,4*W1+5*B,B,W1,5*W1+4*B,0);
+  n->color(13);
+  n = new Fl_Box(FL_FRAME_BOX,W1+B+B,W1+B+B,2*W1+B,2*W1+B,0);
+  n->color(8);
+
+  Fl::enable_symbols();
+  Fl_Button *b = new Fl_Radio_Button(W1+B+50,W1+B+30,20,20,"@6>");
+  b->callback(b_cb,6);
+  (new Fl_Radio_Button(W1+B+30,W1+B+10,20,20,"@8>"))->callback(b_cb,8);
+  (new Fl_Radio_Button(W1+B+10,W1+B+30,20,20,"@4>"))->callback(b_cb,4);
+  (new Fl_Radio_Button(W1+B+30,W1+B+50,20,20,"@2>"))->callback(b_cb,2);
+  (new Fl_Radio_Button(W1+B+30,W1+B+30,20,20,"off"))->callback(b_cb,0);
+
+  box = new Fl_Box(FL_FLAT_BOX,0,0,0,0,"resizable");
+  box->color(FL_DARK2);
+  b->set();
+  b->do_callback();
+  window->end();
+
+  window->size_range(W3,W3);
+  window->show(argc,argv);
+  return Fl::run();
+}
diff --git a/test/scroll.cxx b/test/scroll.cxx
new file mode 100644
index 000000000..d74321444
--- /dev/null
+++ b/test/scroll.cxx
@@ -0,0 +1,112 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+class Drawing : public Fl_Widget {
+  void draw();
+public:
+  Drawing(int X,int Y,int W,int H,const char* L) : Fl_Widget(X,Y,W,H,L) {
+    align(FL_ALIGN_TOP);
+    box(FL_FLAT_BOX);
+    color(FL_WHITE);
+  }
+};
+
+void Drawing::draw() {
+  draw_box();
+  fl_push_matrix();
+  fl_translate(x()+w()/2, y()+h()/2);
+  fl_scale(w()/2, h()/2);
+  fl_color(FL_BLACK);
+  for (int i = 0; i < 20; i++) {
+    for (int j = i+1; j < 20; j++) {
+      fl_begin_line();
+      fl_vertex(cos(M_PI*i/10+.1), sin(M_PI*i/10+.1));
+      fl_vertex(cos(M_PI*j/10+.1), sin(M_PI*j/10+.1));
+      fl_end_line();
+    }
+  }
+  fl_pop_matrix();
+}
+
+Fl_Scroll* thescroll;
+
+void box_cb(Fl_Widget* o, void*) {
+  thescroll->box(((Fl_Button*)o)->value() ? FL_DOWN_FRAME : FL_NO_BOX);
+  thescroll->redraw();
+}
+
+void type_cb(Fl_Widget*, void* v) {
+  thescroll->type(int(v));
+  thescroll->redraw();
+}
+
+Fl_Menu_Item choices[] = {
+  {"0", 0, type_cb, (void*)0},
+  {"HORIZONTAL", 0, type_cb, (void*)Fl_Scroll::HORIZONTAL},
+  {"VERTICAL", 0, type_cb, (void*)Fl_Scroll::VERTICAL},
+  {"BOTH", 0, type_cb, (void*)Fl_Scroll::BOTH},
+  {"HORIZONTAL_ALWAYS", 0, type_cb, (void*)Fl_Scroll::HORIZONTAL_ALWAYS},
+  {"VERTICAL_ALWAYS", 0, type_cb, (void*)Fl_Scroll::VERTICAL_ALWAYS},
+  {"BOTH_ALWAYS", 0, type_cb, (void*)Fl_Scroll::BOTH_ALWAYS},
+  {0}
+};
+
+void align_cb(Fl_Widget*, void* v) {
+  thescroll->scrollbar.align(int(v));
+  thescroll->redraw();
+}
+
+Fl_Menu_Item align_choices[] = {
+  {"left+top", 0, align_cb, (void*)(FL_ALIGN_LEFT+FL_ALIGN_TOP)},
+  {"left+bottom", 0, align_cb, (void*)(FL_ALIGN_LEFT+FL_ALIGN_BOTTOM)},
+  {"right+top", 0, align_cb, (void*)(FL_ALIGN_RIGHT+FL_ALIGN_TOP)},
+  {"right+bottom", 0, align_cb, (void*)(FL_ALIGN_RIGHT+FL_ALIGN_BOTTOM)},
+  {0}
+};
+
+int main(int argc, char** argv) {
+  Fl_Window window(5*75,400);
+  window.box(FL_NO_BOX);
+  Fl_Scroll scroll(0,0,5*75,300);
+
+  int n = 0;
+  for (int y=0; y<16; y++) for (int x=0; x<5; x++) {
+    char buf[20]; sprintf(buf,"%d",n++);
+    Fl_Button* b = new Fl_Button(x*75,y*25+(y>=8?5*75:0),75,25,strdup(buf));
+    b->color(n);
+    b->labelcolor(FL_WHITE);
+  }
+  Drawing drawing(0,8*25,5*75,5*75,0);
+  scroll.end();
+  window.resizable(scroll);
+
+  Fl_Box box(0,300,5*75,window.h()-300); // gray area below the scroll
+  box.box(FL_FLAT_BOX);
+
+  Fl_Toggle_Button but1(150, 310, 200, 25, "box");
+  but1.callback(box_cb);
+  
+  Fl_Choice choice(150, 335, 200, 25, "type():");
+  choice.menu(choices);
+  choice.value(3);
+
+  Fl_Choice achoice(150, 360, 200, 25, "scrollbar.align():");
+  achoice.menu(align_choices);
+  achoice.value(3);
+
+  thescroll = &scroll;
+
+  //scroll.box(FL_DOWN_BOX);
+  //scroll.type(Fl_Scroll::VERTICAL);
+  window.end();
+  window.show(argc,argv);
+  return Fl::run();
+}
diff --git a/test/shape.cxx b/test/shape.cxx
new file mode 100644
index 000000000..1451c241e
--- /dev/null
+++ b/test/shape.cxx
@@ -0,0 +1,91 @@
+/*	Tiny GL-drawing demo from documentation		*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if HAVE_GL
+
+#include 
+#include 
+
+class shape_window : public Fl_Gl_Window {
+  void draw();
+public:
+  int sides;
+  shape_window(int x,int y,int w,int h,const char *l=0);
+};
+
+shape_window::shape_window(int x,int y,int w,int h,const char *l) :
+Fl_Gl_Window(x,y,w,h,l) {
+  sides = 3;
+}
+
+void shape_window::draw() {
+// the valid() property may be used to avoid reinitializing your
+// GL transformation for each redraw:
+  if (!valid()) {
+    valid(1);
+    glLoadIdentity();
+    glViewport(0,0,w(),h());
+  }
+// draw an amazing graphic:
+  glClear(GL_COLOR_BUFFER_BIT);
+  glColor3f(.5,.6,.7);
+  glBegin(GL_POLYGON);
+  for (int i=0; i
+class shape_window : public Fl_Box {
+public:	
+  int sides;
+  shape_window(int x,int y,int w,int h,const char *l=0)
+    :Fl_Box(FL_DOWN_BOX,x,y,w,h,l){
+      label("This demo does\nnot work without GL");
+  }
+};
+
+#endif
+
+// when you change the data, as in this callback, you must call redraw():
+void sides_cb(Fl_Widget *o, void *p) {
+  shape_window *sw = (shape_window *)p;
+  sw->sides = int(((Fl_Slider *)o)->value());
+  sw->redraw();
+}
+
+int main(int argc, char **argv) {
+
+  Fl_Window window(300, 330);
+
+// the shape window could be it's own window, but here we make it
+// a child window:
+  shape_window sw(10, 10, 280, 280);
+// make it resize:
+  window.resizable(&sw);
+  //  window.size_range(300,330,0,0,1,1,1);
+// add a knob to control it:
+  Fl_Hor_Slider slider(50, 295, window.w()-60, 30, "Sides:");
+  slider.align(FL_ALIGN_LEFT);
+  slider.callback(sides_cb,&sw);
+  slider.value(sw.sides);
+  slider.step(1);
+  slider.bounds(3,40);
+
+  window.end();
+  window.show(argc,argv);
+// in the X version you must show() all Fl_Window's in top/down order
+// other systems may not require this, but it will be harmless:
+  //sw.show();
+    
+  return Fl::run();
+}
diff --git a/test/shiny.cxx b/test/shiny.cxx
new file mode 100644
index 000000000..24846e218
--- /dev/null
+++ b/test/shiny.cxx
@@ -0,0 +1,281 @@
+// Test of gl_start() and gl_finish()
+// Also sample code of using OpenGL to draw a boxtype.
+
+#include 
+#include "shiny_panel.C"
+#include 
+#include 
+
+static uchar color[8][3] = {
+  {128,136,149},
+  {63,54,21},
+  {128,136,146},
+  {223,223,223},
+  {121,128,128},
+  {192,206,220},
+  {137,143,145},
+  {99,81,64}
+};
+static int thickness = 3;
+
+int which = 0;
+
+static Fl_Color pcolor;
+
+Fl_Window *window;
+
+void color_slider_cb(Fl_Value_Slider *o, long i) {
+  int v = int(o->value());
+  if (!i) {
+    color[which][0] = color[which][1] = color[which][2] = v;
+    color_slider[1]->value(v);
+    color_slider[2]->value(v);
+    color_slider[3]->value(v);
+  } else {
+    color[which][i-1] = v;
+  }
+  for (int n=0; nchildren(); n++) window->child(n)->redraw();
+  pcolor = FL_BLACK; // make it recalculate actual colors
+//   test_box[0]->redraw();
+//   test_box[1]->redraw();
+//   test_box[2]->redraw();
+}
+
+void set_sliders() {
+  color_slider[0]->value(color[which][0]);
+  color_slider[1]->value(color[which][0]);
+  color_slider[2]->value(color[which][1]);
+  color_slider[3]->value(color[which][2]);
+}
+
+void thickness_cb(Fl_Slider* s,void*) {
+  thickness = int(s->value());
+  for (int n=0; nchildren(); n++) window->child(n)->redraw();
+}
+
+void which_cb(Fl_Button *, long i) {
+  which = which&(~3) | i;
+  set_sliders();
+}
+
+void inside_cb(Fl_Button *b, void*) {
+  if (b->value()) which = which | 4;
+  else which = which & (3|8);
+  set_sliders();
+}
+
+void dump_cb(Fl_Button *, void*) {
+  printf("static uchar color[8][3] = {\n");
+  for (int i=0; i<8; i++) {
+    printf("  {%d,%d,%d}",color[i][0],color[i][1],color[i][2]);
+    if (i<7) printf(",\n");
+  }
+  printf("\n};\nstatic int thickness = %d;\n",thickness);
+}
+
+#include 
+
+#if HAVE_GL
+#include 
+
+static uchar C[8][3]; // actual colors for current button
+
+static void calc_color(Fl_Color c) {
+  uchar r[3];
+  pcolor = c;
+  Fl::get_color(c,r[0],r[1],r[2]);
+  for (int x = 0; x<8; x++) for (int y=0; y<3; y++) {
+    int i = r[y]-166+color[x][y];
+    if (i<0) i = 0; else if (i>255) i = 255;
+    C[x][y] = i;
+  }
+}
+void shiny_up_box(int x1, int y1, int w1, int h1, Fl_Color c) {
+  if (c != pcolor) calc_color(c);
+  int x = x1+1;
+  int y = Fl_Window::current()->h()-(y1+h1-1);
+  int w = w1-2;
+  int h = h1-2;
+  gl_start();
+
+  // left edge:
+  glBegin(GL_POLYGON);
+  glColor3ub(C[0][0],C[0][1],C[0][2]);
+  glVertex2i(x,y);
+  glVertex2i(x+thickness,y+thickness);
+  glColor3ub(C[3][0],C[3][1],C[3][2]);
+  glVertex2i(x+thickness,y+h-thickness);
+  glVertex2i(x,y+h);
+  glEnd();
+
+  // top edge:
+  glBegin(GL_POLYGON);
+  glVertex2i(x,y+h);
+  glVertex2i(x+thickness,y+h-thickness);
+  glColor3ub(C[2][0],C[2][1],C[2][2]);
+  glVertex2i(x+w-thickness,y+h-thickness);
+  glVertex2i(x+w,y+h);
+  glEnd();
+
+  // right edge:
+  glColor3ub(C[1][0],C[1][1],C[1][2]);
+  glBegin(GL_POLYGON);
+  glVertex2i(x+w-thickness,y+thickness);
+  glVertex2i(x+w,y+thickness);
+  glVertex2i(x+w,y+h);
+  glVertex2i(x+w-thickness,y+h-thickness);
+  glEnd();
+
+  // bottom edge:
+  glBegin(GL_POLYGON);
+  glVertex2i(x,y);
+  glVertex2i(x+w,y);
+  glVertex2i(x+w,y+thickness);
+  glVertex2i(x+thickness,y+thickness);
+  glEnd();
+
+  glBegin(GL_POLYGON);
+  glColor3ub(C[4][0],C[4][1],C[4][2]);
+  glVertex2i(x+thickness,y+thickness);
+  glColor3ub(C[5][0],C[5][1],C[5][2]);
+  glVertex2i(x+w-thickness,y+thickness);
+  glColor3ub(C[6][0],C[6][1],C[6][2]);
+  glVertex2i(x+w-thickness,y+h-thickness);
+  glColor3ub(C[7][0],C[7][1],C[7][2]);
+  glVertex2i(x+thickness,y+h-thickness);
+  glEnd();
+
+  gl_finish();
+  fl_color(FL_BLACK);
+  fl_rect(x1,y1,w1,h1);
+}
+
+void shiny_down_box(int x1, int y1, int w1, int h1, Fl_Color c) {
+  if (c != pcolor) calc_color(c);
+  int x = x1+1;
+  int y = Fl_Window::current()->h()-(y1+h1-1);
+  int w = w1-2;
+  int h = h1-2;
+  gl_start();
+
+  // left edge:
+  glColor3ub(C[1][0],C[1][1],C[1][2]);
+  glBegin(GL_POLYGON);
+  glVertex2i(x,y);
+  glVertex2i(x+thickness,y+thickness);
+  glVertex2i(x+thickness,y+h-thickness);
+  glVertex2i(x,y+h);
+  glEnd();
+
+  // top edge:
+  glBegin(GL_POLYGON);
+  glVertex2i(x,y+h);
+  glVertex2i(x+thickness,y+h-thickness);
+  glVertex2i(x+w-thickness,y+h-thickness);
+  glVertex2i(x+w,y+h);
+  glEnd();
+
+  // bottom edge:
+  glBegin(GL_POLYGON);
+  glColor3ub(C[0][0],C[0][1],C[0][2]);
+  glVertex2i(x+thickness,y+thickness);
+  glVertex2i(x,y);
+  glColor3ub(C[1][0],C[1][1],C[1][2]);
+  glVertex2i(x+w,y);
+  glVertex2i(x+w-thickness,y+thickness);
+  glEnd();
+
+  // right edge:
+  glBegin(GL_POLYGON);
+  glVertex2i(x+w-thickness,y+thickness);
+  glVertex2i(x+w,y);
+  glColor3ub(C[2][0],C[2][1],C[2][2]);
+  glVertex2i(x+w,y+h);
+  glVertex2i(x+w-thickness,y+h-thickness);
+  glEnd();
+
+  // inside:
+  glBegin(GL_POLYGON);
+  glColor3ub(C[4][0],C[4][1],C[4][2]);
+  glVertex2i(x+thickness,y+thickness);
+  glColor3ub(C[5][0],C[5][1],C[5][2]);
+  glVertex2i(x+w-thickness,y+thickness);
+  glColor3ub(C[6][0],C[6][1],C[6][2]);
+  glVertex2i(x+w-thickness,y+h-thickness);
+  glColor3ub(C[7][0],C[7][1],C[7][2]);
+  glVertex2i(x+thickness,y+h-thickness);
+  glEnd();
+
+  gl_finish();
+  fl_color(FL_BLACK);
+  fl_rect(x1,y1,w1,h1);
+}
+
+// It looks interesting if you use this for the window's boxtype,
+// but it is way too slow under MESA:
+void shiny_flat_box(int x, int y1, int w, int h, Fl_Color c) {
+  if (c != pcolor) calc_color(c);
+  int y = Fl_Window::current()->h()-(y1+h);
+  gl_start();
+  glBegin(GL_POLYGON);
+  glColor3ub(C[4][0],C[4][1],C[4][2]);
+  glVertex2i(x,y);
+  glColor3ub(C[5][0],C[5][1],C[5][2]);
+  glVertex2i(x+w,y);
+  glColor3ub(C[6][0],C[6][1],C[6][2]);
+  glVertex2i(x+w,y+h);
+  glColor3ub(C[7][0],C[7][1],C[7][2]);
+  glVertex2i(x,y+h);
+  glEnd();
+  gl_finish();
+}
+#endif
+
+// If you use a shiny box as a background, things like the sliders that
+// expect to erase a flat area will not work, as you will see the edges
+// of the area.  This "box type" clips to the area and then draws the
+// parent's box.  Perhaps sliders should be fixed to do this automatically?
+void invisible_box(int x, int y, int w, int h, Fl_Color c) {
+  fl_clip(x,y,w,h);
+  Fl_Window *W = Fl_Window::current();
+  fl_draw_box(W->box(),0,0,W->w(),W->h(),c);
+  fl_pop_clip();
+}
+
+#define SHINY_BOX (Fl_Boxtype)30
+#define INVISIBLE_BOX (Fl_Boxtype)31
+
+int main(int argc, char **argv) {
+  window = make_panels();
+#if HAVE_GL
+  // This will cause all buttons to be shiny:
+  Fl::set_boxtype(FL_UP_BOX, shiny_up_box,3,3,6,6);
+  Fl::set_boxtype(FL_DOWN_BOX, shiny_down_box,3,3,6,6);
+  // replacing FL_FLAT_BOX does not work!  Fl_Window makes assumptions
+  // about what FL_FLAT_BOX does, and sets the X background pixel.
+//Fl::set_boxtype(FL_FLAT_BOX, shiny_flat_box, 0,0,0,0);
+  // Instead you must change box() on Fl_Window to a different value:
+  Fl::set_boxtype(SHINY_BOX, shiny_flat_box, 0,0,0,0);
+  window->box(SHINY_BOX);
+  Fl::set_boxtype(INVISIBLE_BOX, invisible_box, 0,0,0,0);
+#endif
+  set_sliders();
+//color_slider[0]->box(INVISIBLE_BOX);
+//color_slider[1]->box(INVISIBLE_BOX);
+//color_slider[2]->box(INVISIBLE_BOX);
+//color_slider[3]->box(INVISIBLE_BOX);
+  thickness_slider->value(thickness);
+  thickness_slider->box(INVISIBLE_BOX);
+  thickness_slider->slider(FL_UP_BOX);
+  // we must eat the switches first so -display is done before trying
+  // to set the visual:
+  int i = 0;
+  if (Fl::args(argc,argv,i) < argc) Fl::fatal(Fl::help);
+#if HAVE_GL
+  if (!Fl::gl_visual(FL_RGB)) Fl::fatal("Display does not do OpenGL");
+#else
+  fl_message("This demo does not work without OpenGL");
+#endif
+  window->show(argc,argv);
+  return Fl::run();
+}
diff --git a/test/shiny_panel.C b/test/shiny_panel.C
new file mode 100644
index 000000000..f568a7d90
--- /dev/null
+++ b/test/shiny_panel.C
@@ -0,0 +1,103 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+#include "shiny_panel.H"
+Fl_Box *test_box[3];
+Fl_Value_Slider *color_slider[4];
+Fl_Slider *thickness_slider;
+
+Fl_Window* make_panels() {
+ Fl_Window *w;
+ {Fl_Window* o = new Fl_Window(452, 320);
+  w = o;
+ {Fl_Box* o = new Fl_Box(130, 80, 180, 30, "label");
+  test_box[0] = o;
+  o->box(FL_UP_BOX);
+ }
+ {Fl_Box* o = new Fl_Box(130, 120, 180, 30, "label");
+  test_box[1] = o;
+  o->box(FL_UP_BOX);
+ }
+ {Fl_Box* o = new Fl_Box(130, 150, 180, 70, "label");
+  test_box[2] = o;
+  o->box(FL_UP_BOX);
+  Fl_Group::current()->resizable(o);
+ }
+ {Fl_Group* o = new Fl_Group(10, 70, 80, 80);
+ {Fl_Button* o = new Fl_Button(10, 70, 40, 40, "@7->");
+  o->type(102);
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->callback((Fl_Callback*)which_cb, (void*)(3));
+ }
+ {Fl_Button* o = new Fl_Button(50, 70, 40, 40, "@9->");
+  o->type(102);
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->callback((Fl_Callback*)which_cb, (void*)(2));
+ }
+ {Fl_Button* o = new Fl_Button(10, 110, 40, 40, "@1->");
+  o->type(102);
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->callback((Fl_Callback*)which_cb, (void*)(0));
+  o->set();
+ }
+ {Fl_Button* o = new Fl_Button(50, 110, 40, 40, "@3->");
+  o->type(102);
+  o->labeltype(FL_SYMBOL_LABEL);
+  o->callback((Fl_Callback*)which_cb, (void*)(1));
+ }
+  o->end();
+ }
+ {Fl_Button* o = new Fl_Button(10, 150, 80, 40, "INSIDE");
+  o->type(1);
+  o->callback((Fl_Callback*)inside_cb);
+ }
+ {Fl_Value_Slider* o = new Fl_Value_Slider(320, 0, 30, 320);
+  color_slider[0] = o;
+  o->type(4);
+  o->box(FL_FLAT_BOX);
+  o->color(7);
+  o->callback((Fl_Callback*)color_slider_cb, (void*)(0));
+  o->minimum(255); o->maximum(0);;
+  o->precision(0);
+ }
+ {Fl_Value_Slider* o = new Fl_Value_Slider(350, 0, 30, 320);
+  color_slider[1] = o;
+  o->type(4);
+  o->box(FL_FLAT_BOX);
+  o->color(9);
+  o->callback((Fl_Callback*)color_slider_cb, (void*)(1));
+  o->minimum(255); o->maximum(0);;
+  o->precision(0);
+ }
+ {Fl_Value_Slider* o = new Fl_Value_Slider(380, 0, 30, 320);
+  color_slider[2] = o;
+  o->type(4);
+  o->box(FL_FLAT_BOX);
+  o->color(10);
+  o->callback((Fl_Callback*)color_slider_cb, (void*)(2));
+  o->minimum(255); o->maximum(0);;
+  o->precision(0);
+ }
+ {Fl_Value_Slider* o = new Fl_Value_Slider(410, 0, 30, 320);
+  color_slider[3] = o;
+  o->type(4);
+  o->box(FL_FLAT_BOX);
+  o->color(12);
+  o->callback((Fl_Callback*)color_slider_cb, (void*)(3));
+  o->minimum(255); o->maximum(0);;
+  o->precision(0);
+ }
+ {Fl_Slider* o = new Fl_Slider(130, 240, 180, 30, "thickness");
+  thickness_slider = o;
+  o->type(5);
+  o->box(FL_FLAT_BOX);
+  o->callback((Fl_Callback*)thickness_cb);
+  o->minimum(1);
+  o->maximum(10);
+  o->step(1);
+ }
+ {Fl_Button* o = new Fl_Button(10, 230, 80, 30, "dump");
+  o->callback((Fl_Callback*)dump_cb);
+ }
+ w->end();
+ }
+ return w;
+}
diff --git a/test/shiny_panel.H b/test/shiny_panel.H
new file mode 100644
index 000000000..9e86fc52f
--- /dev/null
+++ b/test/shiny_panel.H
@@ -0,0 +1,17 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+extern void color_slider_cb(Fl_Value_Slider*, long);
+extern void dump_cb(Fl_Button*, void*);
+extern void inside_cb(Fl_Button*, void*);
+extern void thickness_cb(Fl_Slider*, void*);
+extern void which_cb(Fl_Button*, long);
+extern Fl_Box *test_box[3];
+extern Fl_Value_Slider *color_slider[4];
+extern Fl_Slider *thickness_slider;
+Fl_Window* make_panels();
diff --git a/test/shiny_panel.fl b/test/shiny_panel.fl
new file mode 100644
index 000000000..a4d5dfa4f
--- /dev/null
+++ b/test/shiny_panel.fl
@@ -0,0 +1,96 @@
+# data file for FL User Interface Designer (fluid)
+version 0.97
+Function {make_panels()} {open
+} {
+  Fl_Window {} {open
+    xywh {594 419 452 320}
+  } {
+    Fl_Box {test_box[0]} {
+      label label open
+      xywh {130 80 180 30} box 2
+    }
+    Fl_Box {test_box[1]} {
+      label label open
+      xywh {130 120 180 30} box 2
+    }
+    Fl_Box {test_box[2]} {
+      label label open
+      xywh {130 150 180 70} box 2 resizable
+    }
+    Fl_Group {} {open
+      xywh {10 70 80 80}
+    } {
+      Fl_Button {} {
+        label {@7->}
+        user_data 3 user_data_type long
+        callback which_cb open
+        xywh {10 70 40 40} type 102 labeltype 2
+      }
+      Fl_Button {} {
+        label {@9->}
+        user_data 2 user_data_type long
+        callback which_cb open
+        xywh {50 70 40 40} type 102 labeltype 2
+      }
+      Fl_Button {} {
+        label {@1->}
+        user_data 0 user_data_type long
+        callback which_cb open
+        xywh {10 110 40 40} type 102 labeltype 2
+        code0 {o->set();}
+      }
+      Fl_Button {} {
+        label {@3->}
+        user_data 1 user_data_type long
+        callback which_cb open
+        xywh {50 110 40 40} type 102 labeltype 2
+      }
+    }
+    Fl_Button {} {
+      label INSIDE
+      callback inside_cb open
+      xywh {10 150 80 40} type 1
+    }
+    Fl_Value_Slider {color_slider[0]} {
+      user_data 0 user_data_type long
+      callback color_slider_cb open
+      xywh {320 0 30 320} type 4 box 1 color {7 47}
+      code0 {o->minimum(255); o->maximum(0);;}
+      code1 {o->precision(0);}
+    }
+    Fl_Value_Slider {color_slider[1]} {
+      user_data 1 user_data_type long
+      callback color_slider_cb open
+      xywh {350 0 30 320} type 4 box 1 color {9 47}
+      code0 {o->minimum(255); o->maximum(0);;}
+      code1 {o->precision(0);}
+    }
+    Fl_Value_Slider {color_slider[2]} {
+      user_data 2 user_data_type long
+      callback color_slider_cb open
+      xywh {380 0 30 320} type 4 box 1 color {10 47}
+      code0 {o->minimum(255); o->maximum(0);;}
+      code1 {o->precision(0);}
+    }
+    Fl_Value_Slider {color_slider[3]} {
+      user_data 3 user_data_type long
+      callback color_slider_cb open
+      xywh {410 0 30 320} type 4 box 1 color {12 47}
+      code0 {o->minimum(255); o->maximum(0);;}
+      code1 {o->precision(0);}
+    }
+    Fl_Slider thickness_slider {
+      label thickness
+      callback thickness_cb open
+      xywh {130 240 180 30} type 5 box 1
+      code0 {o->minimum(1);}
+      code1 {o->maximum(10);}
+      code2 {o->step(1);}
+    }
+    Fl_Button {} {
+      label dump
+      callback dump_cb open selected
+      xywh {10 230 80 30}
+    }
+  }
+} 
diff --git a/test/srs.xbm b/test/srs.xbm
new file mode 100644
index 000000000..b6a9c7440
--- /dev/null
+++ b/test/srs.xbm
@@ -0,0 +1,67 @@
+#define sorceress_width 75
+#define sorceress_height 75
+static unsigned char sorceress_bits[] =
+{
+  0xfc, 0x7e, 0x40, 0x20, 0x90, 0x00, 0x07, 0x80, 0x23, 0x00, 0x00, 0xc6,
+  0xc1, 0x41, 0x98, 0xb8, 0x01, 0x07, 0x66, 0x00, 0x15, 0x9f, 0x03, 0x47,
+  0x8c, 0xc6, 0xdc, 0x7b, 0xcc, 0x00, 0xb0, 0x71, 0x0e, 0x4d, 0x06, 0x66,
+  0x73, 0x8e, 0x8f, 0x01, 0x18, 0xc4, 0x39, 0x4b, 0x02, 0x23, 0x0c, 0x04,
+  0x1e, 0x03, 0x0c, 0x08, 0xc7, 0xef, 0x08, 0x30, 0x06, 0x07, 0x1c, 0x02,
+  0x06, 0x30, 0x18, 0xae, 0xc8, 0x98, 0x3f, 0x78, 0x20, 0x06, 0x02, 0x20,
+  0x60, 0xa0, 0xc4, 0x1d, 0xc0, 0xff, 0x41, 0x04, 0xfa, 0x63, 0x80, 0xa1,
+  0xa4, 0x3d, 0x00, 0x84, 0xbf, 0x04, 0x0f, 0x06, 0xfc, 0xa1, 0x34, 0x6b,
+  0x01, 0x1c, 0xc9, 0x05, 0x06, 0xc7, 0x06, 0xbe, 0x11, 0x1e, 0x43, 0x30,
+  0x91, 0x05, 0xc3, 0x61, 0x02, 0x30, 0x1b, 0x30, 0xcc, 0x20, 0x11, 0x00,
+  0xc1, 0x3c, 0x03, 0x20, 0x0a, 0x00, 0xe8, 0x60, 0x21, 0x00, 0x61, 0x1b,
+  0xc1, 0x63, 0x08, 0xf0, 0xc6, 0xc7, 0x21, 0x03, 0xf8, 0x08, 0xe1, 0xcf,
+  0x0a, 0xfc, 0x4d, 0x99, 0x43, 0x07, 0x3c, 0x0c, 0xf1, 0x9f, 0x0b, 0xfc,
+  0x5b, 0x81, 0x47, 0x02, 0x16, 0x04, 0x31, 0x1c, 0x0b, 0x1f, 0x17, 0x89,
+  0x4d, 0x06, 0x1a, 0x04, 0x31, 0x38, 0x02, 0x07, 0x56, 0x89, 0x49, 0x04,
+  0x0b, 0x04, 0xb1, 0x72, 0x82, 0xa1, 0x54, 0x9a, 0x49, 0x04, 0x1d, 0x66,
+  0x50, 0xe7, 0xc2, 0xf0, 0x54, 0x9a, 0x58, 0x04, 0x0d, 0x62, 0xc1, 0x1f,
+  0x44, 0xfc, 0x51, 0x90, 0x90, 0x04, 0x86, 0x63, 0xe0, 0x74, 0x04, 0xef,
+  0x31, 0x1a, 0x91, 0x00, 0x02, 0xe2, 0xc1, 0xfd, 0x84, 0xf9, 0x30, 0x0a,
+  0x91, 0x00, 0x82, 0xa9, 0xc0, 0xb9, 0x84, 0xf9, 0x31, 0x16, 0x81, 0x00,
+  0x42, 0xa9, 0xdb, 0x7f, 0x0c, 0xff, 0x1c, 0x16, 0x11, 0x00, 0x02, 0x28,
+  0x0b, 0x07, 0x08, 0x60, 0x1c, 0x02, 0x91, 0x00, 0x46, 0x29, 0x0e, 0x00,
+  0x00, 0x00, 0x10, 0x16, 0x11, 0x02, 0x06, 0x29, 0x04, 0x00, 0x00, 0x00,
+  0x10, 0x16, 0x91, 0x06, 0xa6, 0x2a, 0x04, 0x00, 0x00, 0x00, 0x18, 0x24,
+  0x91, 0x04, 0x86, 0x2a, 0x04, 0x00, 0x00, 0x00, 0x18, 0x27, 0x93, 0x04,
+  0x96, 0x4a, 0x04, 0x00, 0x00, 0x00, 0x04, 0x02, 0x91, 0x04, 0x86, 0x4a,
+  0x0c, 0x00, 0x00, 0x00, 0x1e, 0x23, 0x93, 0x04, 0x56, 0x88, 0x08, 0x00,
+  0x00, 0x00, 0x90, 0x21, 0x93, 0x04, 0x52, 0x0a, 0x09, 0x80, 0x01, 0x00,
+  0xd0, 0x21, 0x95, 0x04, 0x57, 0x0a, 0x0f, 0x80, 0x27, 0x00, 0xd8, 0x20,
+  0x9d, 0x04, 0x5d, 0x08, 0x1c, 0x80, 0x67, 0x00, 0xe4, 0x01, 0x85, 0x04,
+  0x79, 0x8a, 0x3f, 0x00, 0x00, 0x00, 0xf4, 0x11, 0x85, 0x06, 0x39, 0x08,
+  0x7d, 0x00, 0x00, 0x18, 0xb7, 0x10, 0x81, 0x03, 0x29, 0x12, 0xcb, 0x00,
+  0x7e, 0x30, 0x28, 0x00, 0x85, 0x03, 0x29, 0x10, 0xbe, 0x81, 0xff, 0x27,
+  0x0c, 0x10, 0x85, 0x03, 0x29, 0x32, 0xfa, 0xc1, 0xff, 0x27, 0x94, 0x11,
+  0x85, 0x03, 0x28, 0x20, 0x6c, 0xe1, 0xff, 0x07, 0x0c, 0x01, 0x85, 0x01,
+  0x28, 0x62, 0x5c, 0xe3, 0x8f, 0x03, 0x4e, 0x91, 0x80, 0x05, 0x39, 0x40,
+  0xf4, 0xc2, 0xff, 0x00, 0x9f, 0x91, 0x84, 0x05, 0x31, 0xc6, 0xe8, 0x07,
+  0x7f, 0x80, 0xcd, 0x00, 0xc4, 0x04, 0x31, 0x06, 0xc9, 0x0e, 0x00, 0xc0,
+  0x48, 0x88, 0xe0, 0x04, 0x79, 0x04, 0xdb, 0x12, 0x00, 0x30, 0x0c, 0xc8,
+  0xe4, 0x04, 0x6d, 0x06, 0xb6, 0x23, 0x00, 0x18, 0x1c, 0xc0, 0x84, 0x04,
+  0x25, 0x0c, 0xff, 0xc2, 0x00, 0x4e, 0x06, 0xb0, 0x80, 0x04, 0x3f, 0x8a,
+  0xb3, 0x83, 0xff, 0xc3, 0x03, 0x91, 0x84, 0x04, 0x2e, 0xd8, 0x0f, 0x3f,
+  0x00, 0x00, 0x5f, 0x83, 0x84, 0x04, 0x2a, 0x70, 0xfd, 0x7f, 0x00, 0x00,
+  0xc8, 0xc0, 0x84, 0x04, 0x4b, 0xe2, 0x2f, 0x01, 0x00, 0x08, 0x58, 0x60,
+  0x80, 0x04, 0x5b, 0x82, 0xff, 0x01, 0x00, 0x08, 0xd0, 0xa0, 0x84, 0x04,
+  0x72, 0x80, 0xe5, 0x00, 0x00, 0x08, 0xd2, 0x20, 0x44, 0x04, 0xca, 0x02,
+  0xff, 0x00, 0x00, 0x08, 0xde, 0xa0, 0x44, 0x04, 0x82, 0x02, 0x6d, 0x00,
+  0x00, 0x08, 0xf6, 0xb0, 0x40, 0x02, 0x82, 0x07, 0x3f, 0x00, 0x00, 0x08,
+  0x44, 0x58, 0x44, 0x02, 0x93, 0x3f, 0x1f, 0x00, 0x00, 0x30, 0x88, 0x4f,
+  0x44, 0x03, 0x83, 0x23, 0x3e, 0x00, 0x00, 0x00, 0x18, 0x60, 0xe0, 0x07,
+  0xe3, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x70, 0x70, 0xe4, 0x07, 0xc7, 0x1b,
+  0xfe, 0x01, 0x00, 0x00, 0xe0, 0x3c, 0xe4, 0x07, 0xc7, 0xe3, 0xfe, 0x1f,
+  0x00, 0x00, 0xff, 0x1f, 0xfc, 0x07, 0xc7, 0x03, 0xf8, 0x33, 0x00, 0xc0,
+  0xf0, 0x07, 0xff, 0x07, 0x87, 0x02, 0xfc, 0x43, 0x00, 0x60, 0xf0, 0xff,
+  0xff, 0x07, 0x8f, 0x06, 0xbe, 0x87, 0x00, 0x30, 0xf8, 0xff, 0xff, 0x07,
+  0x8f, 0x14, 0x9c, 0x8f, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x07, 0x9f, 0x8d,
+  0x8a, 0x0f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x07, 0xbf, 0x0b, 0x80, 0x1f,
+  0x00, 0x00, 0xff, 0xff, 0xff, 0x07, 0x7f, 0x3a, 0x80, 0x3f, 0x00, 0x80,
+  0xff, 0xff, 0xff, 0x07, 0xff, 0x20, 0xc0, 0x3f, 0x00, 0x80, 0xff, 0xff,
+  0xff, 0x07, 0xff, 0x01, 0xe0, 0x7f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x07,
+  0xff, 0x0f, 0xf8, 0xff, 0x40, 0xe0, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff,
+  0xff, 0xff, 0x40, 0xf0, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff,
+  0x41, 0xf0, 0xff, 0xff, 0xff, 0x07};
diff --git a/test/style.C b/test/style.C
new file mode 100644
index 000000000..9e8d24535
--- /dev/null
+++ b/test/style.C
@@ -0,0 +1,141 @@
+// style.C
+
+// Demo of a control panel for Fltk "style" changes.
+
+// You can use this as-is, or modify it to your needs.
+
+// To save & restore a style you should write the data to a file of
+// your own design.  Most likely your program has it's own configuration
+// that you want to save as well, and it is user friendly to put all
+// this into the same file.
+
+////////////////////////////////////////////////////////////////
+// This is the part you want to copy to another program.  The
+// program should call "show_style_panel()" in response to a button
+// that the user presses.
+
+#include "style_ui.C"
+
+#include 
+
+Fl_Menu_Item* font_menu() {
+  static Fl_Menu_Item* menu;
+  if (menu) return menu;
+  int k = Fl::set_fonts(/*"*"*/);
+  menu = new Fl_Menu_Item[k+1];
+  memset(menu, 0, (k+1)*sizeof(Fl_Menu_Item));
+  for (int i = 0; i < k; i++) {
+    int t; const char *name = Fl::get_font_name((Fl_Font)i,&t);
+    char buf[256];
+    strcpy(buf, name);
+    if (t & FL_BOLD) strcat(buf," bold");
+    if (t & FL_ITALIC) strcat(buf," italic");
+    menu[i].text = strdup(buf);
+  }
+  return menu;
+}
+
+void font_cb(Fl_Choice* c, long i) {
+  Fl_Font n = Fl_Font(c->value());
+  switch (i) {
+  case 2: Fl_Menu_::default_font(n); break;
+  case 1: Fl_Input_::default_font(n); break;
+  default: Fl_Widget::default_font(n); break;
+  }
+  Fl::redraw();
+}
+
+void font_size_cb(Fl_Value_Input* c, long i) {
+  int n = int(c->value()); if (n <= 0) n = 1; n -= FL_NORMAL_SIZE;
+  switch (i) {
+  case 2: Fl_Menu_::default_size(n); break;
+  case 1: Fl_Input_::default_size(n); break;
+  default: Fl_Widget::default_size(n); break;
+  }
+  Fl::redraw();
+}
+
+#include 
+
+void color_button_cb(Fl_Button* w, void*) {
+  Fl_Color c = w->color();
+  uchar r,g,b; Fl::get_color(c, r,g,b);
+  if (fl_color_chooser(0,r,g,b)) {
+    if (c == FL_GRAY) Fl::background(r,g,b);
+    else Fl::set_color(c,r,g,b);
+    Fl::redraw();
+  }
+}
+
+// functions hidden inside fl_boxtype.C:
+void fl_thin_down_frame(int, int, int, int, Fl_Color);
+void fl_thin_up_frame(int, int, int, int, Fl_Color);
+void fl_thin_down_box(int, int, int, int, Fl_Color);
+void fl_thin_up_box(int, int, int, int, Fl_Color);
+void fl_down_frame(int, int, int, int, Fl_Color);
+void fl_up_frame(int, int, int, int, Fl_Color);
+void fl_down_box(int, int, int, int, Fl_Color);
+void fl_up_box(int, int, int, int, Fl_Color);
+
+// define the 2-pixel boxes:
+#include 
+void fl_2_up_frame(int x, int y, int w, int h, Fl_Color) {
+  fl_frame2("AAPPMMWU",x,y,w,h);
+}
+void fl_2_up_box(int x, int y, int w, int h, Fl_Color c) {
+  fl_2_up_frame(x,y,w,h,c);
+  fl_color(c); fl_rectf(x+2, y+2, w-4, h-4);
+}
+void fl_2_down_frame(int x, int y, int w, int h, Fl_Color) {
+  fl_frame2("UWMMPPAA",x,y,w,h);
+}
+void fl_2_down_box(int x, int y, int w, int h, Fl_Color c) {
+  fl_2_down_frame(x,y,w,h,c);
+  fl_color(c); fl_rectf(x+2, y+2, w-4, h-4);
+}
+
+void box_thickness_cb(Fl_Value_Slider*v, void*) {
+  switch (int(v->value())) {
+  case 1:
+    Fl::set_boxtype(FL_UP_BOX, fl_thin_up_box, 1,1,2,2);
+    Fl::set_boxtype(FL_DOWN_BOX, fl_thin_down_box, 1,1,2,2);
+    Fl::set_boxtype(FL_UP_FRAME, fl_thin_up_frame, 1,1,2,2);
+    Fl::set_boxtype(FL_DOWN_FRAME, fl_thin_down_frame, 1,1,2,2);
+    break;
+  case 2:
+    Fl::set_boxtype(FL_UP_BOX, fl_2_up_box, 2,2,4,4);
+    Fl::set_boxtype(FL_DOWN_BOX, fl_2_down_box, 2,2,4,4);
+    Fl::set_boxtype(FL_UP_FRAME, fl_2_up_frame, 2,2,4,4);
+    Fl::set_boxtype(FL_DOWN_FRAME, fl_2_down_frame, 2,2,4,4);
+    break;
+  default:
+    Fl::set_boxtype(FL_UP_BOX, fl_up_box, 3,3,6,6);
+    Fl::set_boxtype(FL_DOWN_BOX, fl_down_box, 3,3,6,6);
+    Fl::set_boxtype(FL_UP_FRAME, fl_up_frame, 3,3,6,6);
+    Fl::set_boxtype(FL_DOWN_FRAME, fl_down_frame, 3,3,6,6);
+    break;
+  }
+  Fl::redraw();
+}
+
+void text_box_thickness_cb(Fl_Value_Slider* v, void*) {
+  int n = int(v->value());
+  switch (n) {
+  case 0: Fl_Input_::default_box(FL_FLAT_BOX); break;
+  case 1: Fl_Input_::default_box(FL_THIN_DOWN_BOX); break;
+  case 2: Fl_Input_::default_box(FL_DOWN_BOX); break;
+  }
+  Fl::redraw();
+}
+
+void scrollbar_thickness_cb(Fl_Value_Slider* v, void*) {
+  Fl_Browser::scrollbar_width(int(v->value()));
+  Fl::redraw();
+}
+
+#include 
+
+void defaults_cb(Fl_Button*, void*) {
+  fl_alert("Sorry, I didn't implement that");
+}
+
diff --git a/test/style_ui.C b/test/style_ui.C
new file mode 100644
index 000000000..65d52b883
--- /dev/null
+++ b/test/style_ui.C
@@ -0,0 +1,273 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "style_ui.H"
+
+Fl_Window *style_panel;
+
+static void cb_OK(Fl_Return_Button* o, void*) {
+  o->window()->hide();
+}
+
+static void cb_Quit(Fl_Menu_*, void*) {
+  exit(0);
+}
+
+Fl_Menu_Item menu_[] = {
+ {"File", 0,  0, 0, 64, 0, 0, 14, 0},
+ {"Open", 0x8006f,  0, 0, 0, 0, 0, 14, 0},
+ {"Save", 0x80073,  0, 0, 0, 0, 0, 14, 0},
+ {"Merge", 0,  0, 0, 0, 0, 0, 14, 0},
+ {"Quit", 0x80071,  (Fl_Callback*)cb_Quit, 0, 0, 0, 0, 14, 0},
+ {0},
+ {"Edit", 0,  0, 0, 64, 0, 0, 14, 0},
+ {"Undo", 0x8007a,  0, 0, 0, 0, 0, 14, 0},
+ {"Cut", 0x80078,  0, 0, 0, 0, 0, 14, 0},
+ {"Copy", 0x80076,  0, 0, 0, 0, 0, 14, 0},
+ {"Paste", 0x80076,  0, 0, 0, 0, 0, 14, 0},
+ {0},
+ {"Font", 0,  0, 0, 64, 0, 0, 14, 0},
+ {"Normal", 0,  0, 0, 0, 0, 0, 14, 0},
+ {"Bold", 0,  0, 0, 0, 0, 1, 14, 0},
+ {"Italic", 0,  0, 0, 0, 0, 2, 14, 0},
+ {"Bold Italic", 0,  0, 0, 0, 0, 0, 14, 0},
+ {"Engrave", 0,  0, 0, 0, 4, 0, 14, 0},
+ {"Emboss", 0,  0, 0, 0, 5, 0, 14, 0},
+ {"@->", 0,  0, 0, 0, 2, 0, 14, 0},
+ {"Small", 0,  0, 0, 0, 0, 0, 10, 0},
+ {0},
+ {"Other", 0,  0, 0, 64, 0, 0, 14, 0},
+ {"help!", 0,  0, 0, 0, 0, 0, 14, 0},
+ {0},
+ {0}
+};
+
+static void cb_click(Fl_Button*, void*) {
+  show_style_panel();
+}
+static Fl_Menu_Item* font_menu();
+
+void show_style_panel() {
+  Fl_Window *w;
+  if (!style_panel) {
+    { Fl_Window* o = style_panel = w = new Fl_Double_Window(335, 425, "style");
+      { Fl_Choice* o = new Fl_Choice(60, 155, 220, 25, "labels:");
+        o->callback((Fl_Callback*)font_cb, (void*)(0));
+        o->menu(font_menu());
+      }
+      { Fl_Value_Input* o = new Fl_Value_Input(280, 155, 50, 25);
+        o->minimum(1);
+        o->maximum(128);
+        o->step(1);
+        o->value(14);
+        o->callback((Fl_Callback*)font_size_cb, (void*)(0));
+        o->when(4);
+      }
+      { Fl_Choice* o = new Fl_Choice(60, 190, 220, 25, "text:");
+        o->callback((Fl_Callback*)font_cb, (void*)(1));
+        o->menu(font_menu());
+      }
+      { Fl_Value_Input* o = new Fl_Value_Input(280, 190, 50, 25);
+        o->minimum(1);
+        o->maximum(128);
+        o->step(1);
+        o->value(14);
+        o->callback((Fl_Callback*)font_size_cb, (void*)(1));
+        o->when(4);
+      }
+      { Fl_Choice* o = new Fl_Choice(60, 225, 220, 25, "menus:");
+        o->callback((Fl_Callback*)font_cb, (void*)(2));
+        o->menu(font_menu());
+      }
+      { Fl_Value_Input* o = new Fl_Value_Input(280, 225, 50, 25);
+        o->minimum(1);
+        o->maximum(128);
+        o->step(1);
+        o->value(14);
+        o->callback((Fl_Callback*)font_size_cb, (void*)(2));
+        o->when(4);
+      }
+      { Fl_Button* o = new Fl_Button(255, 30, 75, 25, "background:");
+        o->box(FL_ENGRAVED_BOX);
+        o->callback((Fl_Callback*)color_button_cb);
+        o->align(4);
+      }
+      { Fl_Button* o = new Fl_Button(255, 60, 75, 25, "foreground:");
+        o->box(FL_ENGRAVED_BOX);
+        o->color(0);
+        o->callback((Fl_Callback*)color_button_cb);
+        o->align(4);
+      }
+      { Fl_Button* o = new Fl_Button(255, 90, 75, 25, "text background:");
+        o->box(FL_ENGRAVED_BOX);
+        o->color(7);
+        o->callback((Fl_Callback*)color_button_cb);
+        o->align(4);
+      }
+      { Fl_Button* o = new Fl_Button(255, 120, 75, 25, "selection:");
+        o->box(FL_ENGRAVED_BOX);
+        o->color(15);
+        o->callback((Fl_Callback*)color_button_cb);
+        o->align(4);
+      }
+      { Fl_Return_Button* o = new Fl_Return_Button(260, 395, 70, 25, "OK");
+        o->callback((Fl_Callback*)cb_OK);
+      }
+      { Fl_Button* o = new Fl_Button(175, 395, 70, 25, "defaults");
+        o->callback((Fl_Callback*)defaults_cb);
+      }
+      { Fl_Value_Slider* o = new Fl_Value_Slider(235, 260, 95, 25, "box thickness:");
+        o->type(1);
+        o->minimum(1);
+        o->maximum(3);
+        o->step(1);
+        o->value(3);
+        o->slider_size(0.3333);
+        o->callback((Fl_Callback*)box_thickness_cb);
+        o->align(4);
+      }
+      { Fl_Value_Slider* o = new Fl_Value_Slider(235, 295, 95, 25, "text box thickness:");
+        o->type(1);
+        o->maximum(2);
+        o->step(1);
+        o->value(2);
+        o->slider_size(0.3333);
+        o->callback((Fl_Callback*)text_box_thickness_cb);
+        o->align(4);
+      }
+      { Fl_Value_Slider* o = new Fl_Value_Slider(235, 335, 95, 25, "scrollbar thickness:");
+        o->type(1);
+        o->minimum(3);
+        o->maximum(30);
+        o->step(1);
+        o->value(17);
+        o->callback((Fl_Callback*)scrollbar_thickness_cb);
+        o->align(4);
+      }
+      o->end();
+    }
+      }
+      style_panel->show();
+}
+
+int main(int argc, char **argv) {
+  Fl_Window *w;
+  { Fl_Window* o = w = new Fl_Double_Window(445, 435);
+    { Fl_Group* o = new Fl_Group(270, 35, 140, 75, "Packed buttons:");
+      o->align(4);
+      { Fl_Button* o = new Fl_Button(270, 35, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(305, 35, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(340, 35, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(375, 35, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(270, 60, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(305, 60, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(340, 60, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(375, 60, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(270, 85, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(305, 85, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(340, 85, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(375, 85, 35, 25, "A");
+        o->type(102);
+      }
+      o->end();
+    }
+    { Fl_Adjuster* o = new Fl_Adjuster(105, 90, 75, 25);
+      o->labeltype(FL_ENGRAVED_LABEL);
+      o->align(4);
+    }
+    { Fl_Counter* o = new Fl_Counter(20, 120, 170, 25, "counter");
+      o->minimum(-1e+06);
+      o->maximum(1e+06);
+    }
+    { Fl_Adjuster* o = new Fl_Adjuster(80, 40, 25, 75, "adjuster:");
+      o->labeltype(FL_SYMBOL_LABEL);
+      o->align(4);
+    }
+    { Fl_Group* o = new Fl_Group(270, 130, 140, 75, "Inactive buttons:");
+      o->align(4);
+      o->deactivate();
+      { Fl_Button* o = new Fl_Button(270, 130, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(305, 130, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(340, 130, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(375, 130, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(270, 155, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(305, 155, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(340, 155, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(375, 155, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(270, 180, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(305, 180, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(340, 180, 35, 25, "A");
+        o->type(102);
+      }
+      { Fl_Button* o = new Fl_Button(375, 180, 35, 25, "A");
+        o->type(102);
+      }
+      o->end();
+    }
+    { Fl_Input* o = new Fl_Input(65, 175, 200, 25, "input:");
+      o->static_value("This is a text input field");
+    }
+    { Fl_Output* o = new Fl_Output(65, 200, 200, 25, "output:");
+      o->static_value("This is a text output field");
+    }
+    { Fl_Menu_Bar* o = new Fl_Menu_Bar(0, 0, 445, 30);
+      o->menu(menu_);
+    }
+    { Fl_Browser* o = new Fl_Browser(0, 235, 440, 200);
+      o->type(3);
+      Fl_Group::current()->resizable(o);
+      o->load("browser.C");
+      o->position(0);
+    }
+    { Fl_Button* o = new Fl_Button(235, 2, 170, 25, "click this to set style");
+      o->color(12);
+      o->selection_color(12);
+      o->callback((Fl_Callback*)cb_click);
+    }
+    o->end();
+  }
+  Fl::visual(FL_RGB);
+  w->show(argc, argv);
+  return Fl::run();
+}
diff --git a/test/style_ui.H b/test/style_ui.H
new file mode 100644
index 000000000..78a9f55d7
--- /dev/null
+++ b/test/style_ui.H
@@ -0,0 +1,27 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+extern void box_thickness_cb(Fl_Value_Slider*, void*);
+extern void color_button_cb(Fl_Button*, void*);
+extern void defaults_cb(Fl_Button*, void*);
+extern void font_cb(Fl_Choice*, long);
+extern void font_size_cb(Fl_Value_Input*, long);
+extern void scrollbar_thickness_cb(Fl_Value_Slider*, void*);
+extern void text_box_thickness_cb(Fl_Value_Slider*, void*);
+extern Fl_Window *style_panel;
+void show_style_panel();
+extern Fl_Menu_Item menu_[];
diff --git a/test/style_ui.fl b/test/style_ui.fl
new file mode 100644
index 000000000..7eb67ef15
--- /dev/null
+++ b/test/style_ui.fl
@@ -0,0 +1,343 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 0.99 
+header_name {.H} 
+code_name {.C} 
+gridx 5 
+gridy 5 
+snap 3
+decl {Fl_Menu_Item* font_menu();} {} 
+
+Function {show_style_panel()} {open
+} {
+  codeblock {if (!style_panel)} {open
+  } {
+    Fl_Window style_panel {
+      label style
+      xywh {767 205 335 425} type Double visible
+    } {
+      Fl_Choice {} {
+        label {labels:}
+        user_data 0 user_data_type long
+        callback font_cb open
+        xywh {60 155 220 25}
+        code0 {o->menu(font_menu());}
+      } {}
+      Fl_Value_Input {} {
+        user_data 0 user_data_type long
+        callback font_size_cb
+        xywh {280 155 50 25} when 4 minimum 1 maximum 128 step 1 value 14
+      }
+      Fl_Choice {} {
+        label {text:}
+        user_data 1 user_data_type long
+        callback font_cb open
+        xywh {60 190 220 25}
+        code0 {o->menu(font_menu());}
+      } {}
+      Fl_Value_Input {} {
+        user_data 1 user_data_type long
+        callback font_size_cb
+        xywh {280 190 50 25} when 4 minimum 1 maximum 128 step 1 value 14
+      }
+      Fl_Choice {} {
+        label {menus:}
+        user_data 2 user_data_type long
+        callback font_cb open
+        xywh {60 225 220 25}
+        code0 {o->menu(font_menu());}
+      } {}
+      Fl_Value_Input {} {
+        user_data 2 user_data_type long
+        callback font_size_cb
+        xywh {280 225 50 25} when 4 minimum 1 maximum 128 step 1 value 14
+      }
+      Fl_Button {} {
+        label {background:}
+        callback color_button_cb
+        xywh {255 30 75 25} box ENGRAVED_BOX align 4
+      }
+      Fl_Button {} {
+        label {foreground:}
+        callback color_button_cb
+        xywh {255 60 75 25} box ENGRAVED_BOX color 0 align 4
+      }
+      Fl_Button {} {
+        label {text background:}
+        callback color_button_cb
+        xywh {255 90 75 25} box ENGRAVED_BOX color 7 align 4
+      }
+      Fl_Button {} {
+        label {selection:}
+        callback color_button_cb
+        xywh {255 120 75 25} box ENGRAVED_BOX color 15 align 4
+      }
+      Fl_Return_Button {} {
+        label OK
+        callback {o->window()->hide();}
+        xywh {260 395 70 25}
+      }
+      Fl_Button {} {
+        label defaults
+        callback defaults_cb
+        xywh {175 395 70 25}
+      }
+      Fl_Value_Slider {} {
+        label {box thickness:}
+        callback box_thickness_cb
+        xywh {235 260 95 25} type Horizontal align 4 minimum 1 maximum 3 step 1 value 3 slider_size 0.3333
+      }
+      Fl_Value_Slider {} {
+        label {text box thickness:}
+        callback text_box_thickness_cb
+        xywh {235 295 95 25} type Horizontal align 4 maximum 2 step 1 value 2 slider_size 0.3333
+      }
+      Fl_Value_Slider {} {
+        label {scrollbar thickness:}
+        callback scrollbar_thickness_cb
+        xywh {235 335 95 25} type Horizontal align 4 minimum 3 maximum 30 step 1 value 17
+      }
+    }
+  }
+  code {style_panel->show();} {}
+} 
+
+Function {} {open
+} {
+  Fl_Window {} {open
+    xywh {356 409 445 435} type Double resizable visible
+  } {
+    Fl_Group {} {
+      label {Packed buttons:}
+      xywh {270 35 140 75} align 4
+    } {
+      Fl_Button {} {
+        label A
+        xywh {270 35 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {305 35 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {340 35 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {375 35 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {270 60 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {305 60 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {340 60 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {375 60 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {270 85 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {305 85 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {340 85 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {375 85 35 25} type Radio
+      }
+    }
+    Fl_Adjuster {} {
+      xywh {105 90 75 25} labeltype ENGRAVED_LABEL align 4
+    }
+    Fl_Counter {} {
+      label counter
+      xywh {20 120 170 25} minimum -1e+06 maximum 1e+06
+    }
+    Fl_Adjuster {} {
+      label {adjuster:}
+      xywh {80 40 25 75} labeltype SYMBOL_LABEL align 4
+    }
+    Fl_Group {} {
+      label {Inactive buttons:}
+      xywh {270 130 140 75} align 4 deactivate
+    } {
+      Fl_Button {} {
+        label A
+        xywh {270 130 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {305 130 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {340 130 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {375 130 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {270 155 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {305 155 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {340 155 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {375 155 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {270 180 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {305 180 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {340 180 35 25} type Radio
+      }
+      Fl_Button {} {
+        label A
+        xywh {375 180 35 25} type Radio
+      }
+    }
+    Fl_Input {} {
+      label {input:}
+      xywh {65 175 200 25}
+      code0 {o->static_value("This is a text input field");}
+    }
+    Fl_Output {} {
+      label {output:}
+      xywh {65 200 200 25}
+      code0 {o->static_value("This is a text output field");}
+    }
+    Fl_Menu_Bar {} {
+      xywh {0 0 445 30}
+    } {
+      submenu {} {
+        label File
+        xywh {0 0 100 20}
+      } {
+        menuitem {} {
+          label Open
+          xywh {0 0 100 20} shortcut 0x8006f
+        }
+        menuitem {} {
+          label Save
+          xywh {10 10 100 20} shortcut 0x80073
+        }
+        menuitem {} {
+          label Merge
+          xywh {20 20 100 20}
+        }
+        menuitem {} {
+          label Quit
+          callback {exit(0);}
+          xywh {30 30 100 20} shortcut 0x80071
+          code0 {\#include }
+        }
+      }
+      submenu {} {
+        label Edit open
+        xywh {0 0 100 20}
+      } {
+        menuitem {} {
+          label Undo
+          xywh {75 75 100 20} shortcut 0x8007a
+        }
+        menuitem {} {
+          label Cut
+          xywh {45 45 100 20} shortcut 0x80078
+        }
+        menuitem {} {
+          label Copy
+          xywh {55 55 100 20} shortcut 0x80076
+        }
+        menuitem {} {
+          label Paste
+          xywh {65 65 100 20} shortcut 0x80076
+        }
+      }
+      submenu {} {
+        label Font
+        xywh {10 10 100 20}
+      } {
+        menuitem {} {
+          label Normal
+          xywh {0 0 100 20}
+        }
+        menuitem {} {
+          label Bold
+          xywh {10 10 100 20} labelfont 1
+        }
+        menuitem {} {
+          label Italic
+          xywh {20 20 100 20} labelfont 2
+        }
+        menuitem {} {
+          label {Bold Italic}
+          xywh {30 30 100 20}
+        }
+        menuitem {} {
+          label Engrave
+          xywh {40 40 100 20} labeltype ENGRAVED_LABEL
+        }
+        menuitem {} {
+          label Emboss
+          xywh {50 50 100 20} labeltype EMBOSSED_LABEL
+        }
+        menuitem {} {
+          label {@->}
+          xywh {60 60 100 20} labeltype SYMBOL_LABEL
+        }
+        menuitem {} {
+          label Small
+          xywh {70 70 100 20} labelsize 10
+        }
+      }
+      submenu {} {
+        label Other
+        xywh {20 20 100 20}
+      } {
+        menuitem {} {
+          label {help!}
+          xywh {0 0 100 20}
+        }
+      }
+    }
+    Fl_Browser {} {
+      xywh {0 235 440 200} type Multi resizable
+      code0 {o->load("browser.C");}
+      code1 {o->position(0);}
+    }
+    Fl_Button {} {
+      label {click this to set style}
+      callback {show_style_panel();}
+      xywh {235 2 170 25} color 12 selection_color 12
+    }
+  }
+  code {Fl::visual(FL_RGB);} {selected
+  }
+} 
diff --git a/test/subwindow.cxx b/test/subwindow.cxx
new file mode 100644
index 000000000..9644b457d
--- /dev/null
+++ b/test/subwindow.cxx
@@ -0,0 +1,107 @@
+// Test to make sure nested windows work.
+// Events should be reported for enter/exit and all mouse operations
+// Buttons and pop-up menu should work, indicating that mouse positions
+// are being correctly translated.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+class testwindow : public Fl_Window {
+  int handle(int);
+  void draw();
+public:
+  testwindow(Fl_Boxtype b,int x,int y,const char *l)
+    : Fl_Window(x,y,l) {box(b);}
+  testwindow(Fl_Boxtype b,int x,int y,int w,int h,const char *l)
+    : Fl_Window(x,y,w,h,l) {box(b);}
+};
+
+void testwindow::draw() {
+#ifdef DEBUG
+  printf("%s : draw\n",label());
+#endif
+  Fl_Window::draw();
+}
+
+class EnterExit : public Fl_Box {
+  int handle(int);
+public:
+  EnterExit(int x, int y, int w, int h, const char *l) : Fl_Box(FL_BORDER_BOX,x,y,w,h,l) {}
+};
+
+int EnterExit::handle(int e) {
+  if (e == FL_ENTER) {color(FL_RED); redraw(); return 1;}
+  else if (e == FL_LEAVE) {color(FL_GRAY); redraw(); return 1;}
+  else return 0;
+}
+
+#ifdef DEBUG
+const char *eventnames[] = {
+"zero",
+"FL_PUSH",
+"FL_RELEASE",
+"FL_ENTER",
+"FL_LEAVE",
+"FL_DRAG",
+"FL_FOCUS",
+"FL_UNFOCUS",
+"FL_KEYBOARD",
+"9",
+"FL_MOVE",
+"FL_SHORTCUT",
+"12",
+"FL_DEACTIVATE",
+"FL_ACTIVATE",
+"FL_HIDE",
+"FL_SHOW",
+"FL_PASTE",
+"FL_SELECTIONCLEAR",
+};
+#endif
+
+Fl_Menu_Button* popup;
+
+int testwindow::handle(int e) {
+#ifdef DEBUG
+  if (e != FL_MOVE) printf("%s : %s\n",label(),eventnames[e]);
+#endif
+  if (Fl_Window::handle(e)) return 1;
+  //  if (e==FL_PUSH) return popup->handle(e);
+  return 0;
+}
+
+int main(int, char **) {
+  testwindow *window =
+    new testwindow(FL_UP_BOX,400,400,"outer");
+  new Fl_Toggle_Button(310,310,80,80,"&outer");
+  new EnterExit(10,310,80,80,"enterexit");
+  new Fl_Input(150,310,150,25,"input:");
+  (new Fl_Menu_Button(5,150,80,25,"menu&1"))->add("this|is|only|a test");
+  testwindow *subwindow =
+    new testwindow(FL_DOWN_BOX,100,100,200,200,"inner");
+  new Fl_Toggle_Button(110,110,80,80,"&inner");
+  new EnterExit(10,110,80,80,"enterexit");
+  (new Fl_Menu_Button(50,50,80,25,"menu&2"))->add("this|is|only|a test");
+  new Fl_Input(45,80,150,25,"input:");
+  subwindow->resizable(subwindow);
+  window->resizable(subwindow);
+  subwindow->end();
+  (new Fl_Box(FL_NO_BOX,0,0,400,100,
+	     "A child Fl_Window with children of it's own may "
+	     "be useful for imbedding controls into a GL or display "
+	     "that needs a different visual.  There are bugs with the "
+	     "origins being different between drawing and events, "
+	     "which I hope I have solved."
+	     )) -> align(FL_ALIGN_WRAP);
+  popup = new Fl_Menu_Button(0,0,400,400);
+  popup->type(Fl_Menu_Button::POPUP3);
+  popup->add("This|is|a popup|menu");
+  window->show();
+  return Fl::run();
+}
diff --git a/test/symbols.cxx b/test/symbols.cxx
new file mode 100644
index 000000000..b66e6e142
--- /dev/null
+++ b/test/symbols.cxx
@@ -0,0 +1,62 @@
+//	produce diagram used in the documentation:
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int N = 0;
+#define W 60
+#define H 60
+#define ROWS 5
+#define COLS 5
+
+Fl_Window *window;
+
+void bt(const char *name) {
+  int x = N%COLS;
+  int y = N/COLS;
+  N++;
+  x = x*W+10;
+  y = y*H+10;
+  Fl_Box *a = new Fl_Box(FL_NO_BOX,x,y,W-20,H-20,name);
+  a->align(FL_ALIGN_BOTTOM);
+  a->labelsize(11);
+  Fl_Box *b = new Fl_Box(FL_UP_BOX,x,y,W-20,H-20,name);
+  b->labeltype(FL_SYMBOL_LABEL);
+  b->labelcolor(FL_DARK3);
+}
+
+int main(int argc, char ** argv) {
+  window = new Fl_Single_Window(COLS*W,ROWS*H+20);
+bt("@->");
+bt("@>");
+bt("@>>");
+bt("@>|");
+bt("@>[]");
+bt("@|>");
+bt("@<-");
+bt("@<");
+bt("@<<");
+bt("@|<");
+bt("@[]<");
+bt("@<|");
+bt("@<->");
+bt("@-->");
+bt("@+");
+bt("@->|");
+bt("@||");
+bt("@arrow");
+bt("@returnarrow");
+bt("@square");
+bt("@circle");
+bt("@line");
+bt("@menu");
+bt("@UpArrow");
+bt("@DnArrow");
+  window->resizable(window);
+  window->show(argc,argv);
+  return Fl::run();
+}
diff --git a/test/tabs.C b/test/tabs.C
new file mode 100644
index 000000000..239510458
--- /dev/null
+++ b/test/tabs.C
@@ -0,0 +1,84 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "tabs.H"
+
+Fl_Window *foo_window;
+
+static void cb_cancel(Fl_Button*, void*) {
+  exit(1);
+}
+
+static void cb_OK(Fl_Return_Button*, void*) {
+  exit(0);
+}
+
+int main(int argc, char **argv) {
+  Fl_Window *w;
+  { Fl_Window* o = new Fl_Window(321, 324);
+    w = foo_window = o;
+    Fl_Group::current()->resizable(o);
+    { Fl_Tabs* o = new Fl_Tabs(10, 10, 300, 200);
+      o->color2(15);
+      Fl_Group::current()->resizable(o);
+      { Fl_Group* o = new Fl_Group(10, 30, 300, 180, "Label1");
+        o->hide();
+        Fl_Group::current()->resizable(o);
+        new Fl_Input(60, 50, 240, 40, "input:");
+        new Fl_Input(60, 90, 240, 30, "input2:");
+        new Fl_Input(60, 120, 240, 80, "input3:");
+        o->end();
+        Fl_Group::current()->resizable(o);
+      }
+      { Fl_Group* o = new Fl_Group(10, 30, 300, 180, "tab2");
+        o->hide();
+        new Fl_Button(20, 60, 100, 30, "button1");
+        new Fl_Input(140, 100, 100, 30, "input in box2");
+        new Fl_Button(30, 140, 260, 30, "This is stuff inside the Fl_Group \"tab2\"");
+        o->end();
+      }
+      { Fl_Group* o = new Fl_Group(10, 30, 300, 180, "tab3");
+        o->hide();
+        new Fl_Button(20, 60, 60, 80, "button2");
+        new Fl_Button(80, 60, 60, 80, "button");
+        new Fl_Button(140, 60, 60, 80, "button");
+        o->end();
+      }
+      { Fl_Group* o = new Fl_Group(10, 30, 300, 180, "tab4");
+        o->labelfont(2);
+        o->hide();
+        new Fl_Button(20, 50, 60, 110, "button2");
+        new Fl_Button(80, 50, 60, 110, "button");
+        new Fl_Button(140, 50, 60, 110, "button");
+        o->end();
+      }
+      { Fl_Group* o = new Fl_Group(10, 30, 300, 180, "     tab5      ");
+        o->labeltype(FL_ENGRAVED_LABEL);
+        new Fl_Button(20, 80, 60, 80, "button2");
+        new Fl_Button(90, 90, 60, 80, "button");
+        { Fl_Clock* o = new Fl_Clock(160, 50, 100, 100, "Make sure this clock does not use processor time when this tab is hidden o\
+r window is iconized");
+          o->box(FL_OSHADOW_BOX);
+          o->color(238);
+          o->color2(0);
+          o->labelfont(8);
+          o->labelsize(10);
+          o->align(130);
+        }
+        o->end();
+      }
+      o->end();
+      Fl_Group::current()->resizable(o);
+    }
+    new Fl_Input(60, 220, 130, 30, "inputA:");
+    new Fl_Input(60, 250, 250, 30, "inputB:");
+    { Fl_Button* o = new Fl_Button(180, 290, 60, 30, "cancel");
+      o->callback((Fl_Callback*)cb_cancel);
+    }
+    { Fl_Return_Button* o = new Fl_Return_Button(250, 290, 60, 30, "OK");
+      o->callback((Fl_Callback*)cb_OK);
+    }
+    w->end();
+  }
+  w->show(argc, argv);
+  return Fl::run();
+}
diff --git a/test/tabs.H b/test/tabs.H
new file mode 100644
index 000000000..2ec7bc12c
--- /dev/null
+++ b/test/tabs.H
@@ -0,0 +1,12 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+extern Fl_Window *foo_window;
diff --git a/test/tabs.fl b/test/tabs.fl
new file mode 100644
index 000000000..13b97796a
--- /dev/null
+++ b/test/tabs.fl
@@ -0,0 +1,121 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 0.99 
+gridx 10 
+gridy 10 
+snap 3
+Function {} {open
+} {
+  Fl_Window foo_window {open
+    xywh {329 266 321 324} hide resizable
+  } {
+    Fl_Tabs {} {open
+      xywh {10 10 300 200} color {47 15} resizable
+    } {
+      Fl_Group {} {
+        label Label1 open
+        xywh {10 30 300 180} hide resizable
+      } {
+        Fl_Input {} {
+          label {input:}
+          xywh {60 50 240 40}
+        }
+        Fl_Input {} {
+          label {input2:}
+          xywh {60 90 240 30}
+        }
+        Fl_Input {} {
+          label {input3:}
+          xywh {60 120 240 80}
+        }
+      }
+      Fl_Group {} {
+        label tab2 open
+        xywh {10 30 300 180} hide
+      } {
+        Fl_Button {} {
+          label button1
+          xywh {20 60 100 30}
+        }
+        Fl_Input {} {
+          label {input in box2}
+          xywh {140 100 100 30}
+        }
+        Fl_Button {} {
+          label {This is stuff inside the Fl_Group "tab2"} selected
+          xywh {30 140 260 30}
+        }
+      }
+      Fl_Group {} {
+        label tab3 open
+        xywh {10 30 300 180} hide
+      } {
+        Fl_Button {} {
+          label button2
+          xywh {20 60 60 80}
+        }
+        Fl_Button {} {
+          label button
+          xywh {80 60 60 80}
+        }
+        Fl_Button {} {
+          label button
+          xywh {140 60 60 80}
+        }
+      }
+      Fl_Group {} {
+        label tab4 open
+        xywh {10 30 300 180} labelfont 2 hide
+      } {
+        Fl_Button {} {
+          label button2
+          xywh {20 50 60 110}
+        }
+        Fl_Button {} {
+          label button
+          xywh {80 50 60 110}
+        }
+        Fl_Button {} {
+          label button
+          xywh {140 50 60 110}
+        }
+      }
+      Fl_Group {} {
+        label {     tab5      } open
+        xywh {10 30 300 180} labeltype ENGRAVED_LABEL
+      } {
+        Fl_Button {} {
+          label button2
+          xywh {20 80 60 80}
+        }
+        Fl_Button {} {
+          label button
+          xywh {90 90 60 80}
+        }
+        Fl_Clock {} {
+          label {Make sure this clock does not use processor time when this tab is hidden or window is iconized}
+          xywh {160 50 100 100} box OSHADOW_BOX color {238 0} labelfont 8 labelsize 10 align 130
+        }
+      }
+    }
+    Fl_Input {} {
+      label {inputA:}
+      xywh {60 220 130 30}
+    }
+    Fl_Input {} {
+      label {inputB:}
+      xywh {60 250 250 30}
+    }
+    Fl_Button {} {
+      label cancel
+      callback {exit(1);}
+      xywh {180 290 60 30}
+      code0 {\#include }
+    }
+    Fl_Return_Button {} {
+      label OK
+      callback {exit(0);}
+      xywh {250 290 60 30}
+      code0 {\#include }
+    }
+  }
+} 
diff --git a/test/tile.cxx b/test/tile.cxx
new file mode 100755
index 000000000..e5364fe1b
--- /dev/null
+++ b/test/tile.cxx
@@ -0,0 +1,61 @@
+#include 
+#include 
+#include 
+#include 
+
+int main(int argc, char** argv) {
+  Fl_Window window(300,300);
+  window.box(FL_NO_BOX);
+  window.resizable(window);
+  Fl_Tile tile(0,0,300,300);
+  Fl_Box box0(0,0,150,150,"0");
+  box0.box(FL_DOWN_BOX);
+  box0.color(9);
+  box0.labelsize(36);
+  box0.align(FL_ALIGN_CLIP);
+  Fl_Window w1(150,0,150,150,"1");
+  w1.box(FL_NO_BOX);
+  Fl_Box box1(0,0,150,150,"1\nThis is a\nchild\nX window");
+  box1.box(FL_DOWN_BOX);
+  box1.color(19);
+  box1.labelsize(18);
+  box1.align(FL_ALIGN_CLIP);
+  w1.resizable(box1);
+  w1.end();
+
+  //  Fl_Tile tile2(0,150,150,150);
+  Fl_Box box2a(0,150,70,150,"2a");
+  box2a.box(FL_DOWN_BOX);
+  box2a.color(12);
+  box2a.labelsize(36);
+  box2a.align(FL_ALIGN_CLIP);
+  Fl_Box box2b(70,150,80,150,"2b");
+  box2b.box(FL_DOWN_BOX);
+  box2b.color(13);
+  box2b.labelsize(36);
+  box2b.align(FL_ALIGN_CLIP);
+  //tile2.end();
+
+  //Fl_Tile tile3(150,150,150,150);
+  Fl_Box box3a(150,150,150,70,"3a");
+  box3a.box(FL_DOWN_BOX);
+  box3a.color(12);
+  box3a.labelsize(36);
+  box3a.align(FL_ALIGN_CLIP);
+  Fl_Box box3b(150,150+70,150,80,"3b");
+  box3b.box(FL_DOWN_BOX);
+  box3b.color(13);
+  box3b.labelsize(36);
+  box3b.align(FL_ALIGN_CLIP);
+  //tile3.end();
+  
+  Fl_Box r(10,0,300-10,300-10);
+  tile.resizable(r);
+  // r.box(FL_BORDER_FRAME);
+
+  tile.end();
+  window.end();
+  window.show(argc,argv);
+  w1.show();
+  return Fl::run();
+}
diff --git a/test/trackball.c b/test/trackball.c
new file mode 100644
index 000000000..f23d3db30
--- /dev/null
+++ b/test/trackball.c
@@ -0,0 +1,324 @@
+/*
+ * (c) Copyright 1993, 1994, Silicon Graphics, Inc.
+ * ALL RIGHTS RESERVED
+ * Permission to use, copy, modify, and distribute this software for
+ * any purpose and without fee is hereby granted, provided that the above
+ * copyright notice appear in all copies and that both the copyright notice
+ * and this permission notice appear in supporting documentation, and that
+ * the name of Silicon Graphics, Inc. not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission.
+ *
+ * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
+ * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
+ * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
+ * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
+ * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
+ * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
+ * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
+ * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
+ * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
+ * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * US Government Users Restricted Rights
+ * Use, duplication, or disclosure by the Government is subject to
+ * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
+ * (c)(1)(ii) of the Rights in Technical Data and Computer Software
+ * clause at DFARS 252.227-7013 and/or in similar or successor
+ * clauses in the FAR or the DOD or NASA FAR Supplement.
+ * Unpublished-- rights reserved under the copyright laws of the
+ * United States.  Contractor/manufacturer is Silicon Graphics,
+ * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
+ *
+ * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
+ */
+/*
+ * Trackball code:
+ *
+ * Implementation of a virtual trackball.
+ * Implemented by Gavin Bell, lots of ideas from Thant Tessman and
+ *   the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129.
+ *
+ * Vector manip code:
+ *
+ * Original code from:
+ * David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli
+ *
+ * Much mucking with by:
+ * Gavin Bell
+ */
+#include 
+#include "trackball.h"
+
+/*
+ * This size should really be based on the distance from the center of
+ * rotation to the point on the object underneath the mouse.  That
+ * point would then track the mouse as closely as possible.  This is a
+ * simple example, though, so that is left as an Exercise for the
+ * Programmer.
+ */
+#define TRACKBALLSIZE  (0.8)
+
+/*
+ * Local function prototypes (not defined in trackball.h)
+ */
+static float tb_project_to_sphere(float, float, float);
+static void normalize_quat(float [4]);
+
+void
+vzero(float *v)
+{
+    v[0] = 0.0;
+    v[1] = 0.0;
+    v[2] = 0.0;
+}
+
+void
+vset(float *v, float x, float y, float z)
+{
+    v[0] = x;
+    v[1] = y;
+    v[2] = z;
+}
+
+void
+vsub(const float *src1, const float *src2, float *dst)
+{
+    dst[0] = src1[0] - src2[0];
+    dst[1] = src1[1] - src2[1];
+    dst[2] = src1[2] - src2[2];
+}
+
+void
+vcopy(const float *v1, float *v2)
+{
+    register int i;
+    for (i = 0 ; i < 3 ; i++)
+        v2[i] = v1[i];
+}
+
+void
+vcross(const float *v1, const float *v2, float *cross)
+{
+    float temp[3];
+
+    temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]);
+    temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]);
+    temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]);
+    vcopy(temp, cross);
+}
+
+float
+vlength(const float *v)
+{
+    return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+}
+
+void
+vscale(float *v, float div)
+{
+    v[0] *= div;
+    v[1] *= div;
+    v[2] *= div;
+}
+
+void
+vnormal(float *v)
+{
+    vscale(v,1.0/vlength(v));
+}
+
+float
+vdot(const float *v1, const float *v2)
+{
+    return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
+}
+
+void
+vadd(const float *src1, const float *src2, float *dst)
+{
+    dst[0] = src1[0] + src2[0];
+    dst[1] = src1[1] + src2[1];
+    dst[2] = src1[2] + src2[2];
+}
+
+/*
+ * Ok, simulate a track-ball.  Project the points onto the virtual
+ * trackball, then figure out the axis of rotation, which is the cross
+ * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
+ * Note:  This is a deformed trackball-- is a trackball in the center,
+ * but is deformed into a hyperbolic sheet of rotation away from the
+ * center.  This particular function was chosen after trying out
+ * several variations.
+ *
+ * It is assumed that the arguments to this routine are in the range
+ * (-1.0 ... 1.0)
+ */
+void
+trackball(float q[4], float p1x, float p1y, float p2x, float p2y)
+{
+    float a[3]; /* Axis of rotation */
+    float phi;  /* how much to rotate about axis */
+    float p1[3], p2[3], d[3];
+    float t;
+
+    if (p1x == p2x && p1y == p2y) {
+        /* Zero rotation */
+        vzero(q);
+        q[3] = 1.0;
+        return;
+    }
+
+    /*
+     * First, figure out z-coordinates for projection of P1 and P2 to
+     * deformed sphere
+     */
+    vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y));
+    vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y));
+
+    /*
+     *  Now, we want the cross product of P1 and P2
+     */
+    vcross(p2,p1,a);
+
+    /*
+     *  Figure out how much to rotate around that axis.
+     */
+    vsub(p1,p2,d);
+    t = vlength(d) / (2.0*TRACKBALLSIZE);
+
+    /*
+     * Avoid problems with out-of-control values...
+     */
+    if (t > 1.0) t = 1.0;
+    if (t < -1.0) t = -1.0;
+    phi = 2.0 * asin(t);
+
+    axis_to_quat(a,phi,q);
+}
+
+/*
+ *  Given an axis and angle, compute quaternion.
+ */
+void
+axis_to_quat(float a[3], float phi, float q[4])
+{
+    vnormal(a);
+    vcopy(a,q);
+    vscale(q,sin(phi/2.0));
+    q[3] = cos(phi/2.0);
+}
+
+/*
+ * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
+ * if we are away from the center of the sphere.
+ */
+static float
+tb_project_to_sphere(float r, float x, float y)
+{
+    float d, t, z;
+
+    d = sqrt(x*x + y*y);
+    if (d < r * 0.70710678118654752440) {    /* Inside sphere */
+        z = sqrt(r*r - d*d);
+    } else {           /* On hyperbola */
+        t = r / 1.41421356237309504880;
+        z = t*t / d;
+    }
+    return z;
+}
+
+/*
+ * Given two rotations, e1 and e2, expressed as quaternion rotations,
+ * figure out the equivalent single rotation and stuff it into dest.
+ *
+ * This routine also normalizes the result every RENORMCOUNT times it is
+ * called, to keep error from creeping in.
+ *
+ * NOTE: This routine is written so that q1 or q2 may be the same
+ * as dest (or each other).
+ */
+
+#define RENORMCOUNT 97
+
+void
+add_quats(float q1[4], float q2[4], float dest[4])
+{
+    static int count=0;
+    float t1[4], t2[4], t3[4];
+    float tf[4];
+
+    vcopy(q1,t1);
+    vscale(t1,q2[3]);
+
+    vcopy(q2,t2);
+    vscale(t2,q1[3]);
+
+    vcross(q2,q1,t3);
+    vadd(t1,t2,tf);
+    vadd(t3,tf,tf);
+    tf[3] = q1[3] * q2[3] - vdot(q1,q2);
+
+    dest[0] = tf[0];
+    dest[1] = tf[1];
+    dest[2] = tf[2];
+    dest[3] = tf[3];
+
+    if (++count > RENORMCOUNT) {
+        count = 0;
+        normalize_quat(dest);
+    }
+}
+
+/*
+ * Quaternions always obey:  a^2 + b^2 + c^2 + d^2 = 1.0
+ * If they don't add up to 1.0, dividing by their magnitued will
+ * renormalize them.
+ *
+ * Note: See the following for more information on quaternions:
+ *
+ * - Shoemake, K., Animating rotation with quaternion curves, Computer
+ *   Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985.
+ * - Pletinckx, D., Quaternion calculus as a basic tool in computer
+ *   graphics, The Visual Computer 5, 2-13, 1989.
+ */
+static void
+normalize_quat(float q[4])
+{
+    int i;
+    float mag;
+
+    mag = (q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
+    for (i = 0; i < 4; i++) q[i] /= mag;
+}
+
+/*
+ * Build a rotation matrix, given a quaternion rotation.
+ *
+ */
+void
+build_rotmatrix(float m[4][4], float q[4])
+{
+    m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]);
+    m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]);
+    m[0][2] = 2.0 * (q[2] * q[0] + q[1] * q[3]);
+    m[0][3] = 0.0;
+
+    m[1][0] = 2.0 * (q[0] * q[1] + q[2] * q[3]);
+    m[1][1]= 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]);
+    m[1][2] = 2.0 * (q[1] * q[2] - q[0] * q[3]);
+    m[1][3] = 0.0;
+
+    m[2][0] = 2.0 * (q[2] * q[0] - q[1] * q[3]);
+    m[2][1] = 2.0 * (q[1] * q[2] + q[0] * q[3]);
+    m[2][2] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]);
+    m[2][3] = 0.0;
+
+    m[3][0] = 0.0;
+    m[3][1] = 0.0;
+    m[3][2] = 0.0;
+    m[3][3] = 1.0;
+}
+
diff --git a/test/trackball.h b/test/trackball.h
new file mode 100644
index 000000000..b676fb4e5
--- /dev/null
+++ b/test/trackball.h
@@ -0,0 +1,78 @@
+/*
+ * (c) Copyright 1993, 1994, Silicon Graphics, Inc.
+ * ALL RIGHTS RESERVED
+ * Permission to use, copy, modify, and distribute this software for
+ * any purpose and without fee is hereby granted, provided that the above
+ * copyright notice appear in all copies and that both the copyright notice
+ * and this permission notice appear in supporting documentation, and that
+ * the name of Silicon Graphics, Inc. not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission.
+ *
+ * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
+ * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
+ * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
+ * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
+ * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
+ * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
+ * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
+ * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
+ * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
+ * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * US Government Users Restricted Rights
+ * Use, duplication, or disclosure by the Government is subject to
+ * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
+ * (c)(1)(ii) of the Rights in Technical Data and Computer Software
+ * clause at DFARS 252.227-7013 and/or in similar or successor
+ * clauses in the FAR or the DOD or NASA FAR Supplement.
+ * Unpublished-- rights reserved under the copyright laws of the
+ * United States.  Contractor/manufacturer is Silicon Graphics,
+ * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
+ *
+ * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
+ */
+/*
+ * trackball.h
+ * A virtual trackball implementation
+ * Written by Gavin Bell for Silicon Graphics, November 1988.
+ */
+
+/*
+ * Pass the x and y coordinates of the last and current positions of
+ * the mouse, scaled so they are from (-1.0 ... 1.0).
+ *
+ * The resulting rotation is returned as a quaternion rotation in the
+ * first paramater.
+ */
+void
+trackball(float q[4], float p1x, float p1y, float p2x, float p2y);
+
+/*
+ * Given two quaternions, add them together to get a third quaternion.
+ * Adding quaternions to get a compound rotation is analagous to adding
+ * translations to get a compound translation.  When incrementally
+ * adding rotations, the first argument here should be the new
+ * rotation, the second and third the total rotation (which will be
+ * over-written with the resulting new total rotation).
+ */
+void
+add_quats(float *q1, float *q2, float *dest);
+
+/*
+ * A useful function, builds a rotation matrix in Matrix based on
+ * given quaternion.
+ */
+void
+build_rotmatrix(float m[4][4], float q[4]);
+
+/*
+ * This function computes a quaternion based on an axis (defined by
+ * the given vector) and an angle about which to rotate.  The angle is
+ * expressed in radians.  The result is put into the third argument.
+ */
+void
+axis_to_quat(float a[3], float phi, float q[4]);
+
diff --git a/test/valuators.C b/test/valuators.C
new file mode 100644
index 000000000..b71c932d4
--- /dev/null
+++ b/test/valuators.C
@@ -0,0 +1,358 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include "valuators.H"
+
+static void cb_0(Fl_Slider* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_FL_VERT_FILL_SLIDER(Fl_Slider* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_FL_VERT_NICE_SLIDER(Fl_Slider* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_01(Fl_Value_Slider* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_FL_VERT_FILL_SLIDER1(Fl_Value_Slider* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_FL_VERT_NICE_SLIDER1(Fl_Value_Slider* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_FL_HORIZONTAL(Fl_Slider* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_FL_HOR_FILL_SLIDER(Fl_Slider* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_FL_HOR_NICE_SLIDER(Fl_Slider* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_FL_HOR_SLIDER(Fl_Value_Slider* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_FL_HOR_FILL_SLIDER1(Fl_Value_Slider* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_FL_HOR_NICE_SLIDER1(Fl_Value_Slider* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_w(Fl_Adjuster* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_w1(Fl_Adjuster* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_02(Fl_Counter* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_FL_SIMPLE_COUNTER(Fl_Counter* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_03(Fl_Dial* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_FL_LINE_DIAL(Fl_Dial* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_FL_FILL_DIAL(Fl_Dial* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_04(Fl_Roller* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_FL_HORIZONTAL1(Fl_Roller* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_05(Fl_Value_Input* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_06(Fl_Value_Output* o, void*) {
+  printf("%g      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_07(Fl_Scrollbar* o, void*) {
+  printf("%d      \r",o->value());
+fflush(stdout);
+}
+
+static void cb_FL_HORIZONTAL2(Fl_Scrollbar* o, void*) {
+  printf("%d      \r",o->value());
+fflush(stdout);
+}
+
+int main(int argc, char **argv) {
+  Fl_Window *w;
+  { Fl_Window* o = w = new Fl_Window(567, 506, "Valuator classes, showing values for type()");
+    o->color(43);
+    o->selection_color(43);
+    { Fl_Box* o = new Fl_Box(10, 10, 280, 210, "Fl_Slider");
+      o->box(FL_ENGRAVED_BOX);
+      o->labelfont(1);
+      o->labelsize(12);
+      o->align(17);
+    }
+    { Fl_Slider* o = new Fl_Slider(30, 45, 20, 145, "0");
+      o->selection_color(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_0);
+      o->align(1);
+    }
+    { Fl_Slider* o = new Fl_Slider(70, 55, 20, 145, "FL_VERT_FILL_SLIDER");
+      o->type(2);
+      o->selection_color(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_FL_VERT_FILL_SLIDER);
+    }
+    { Fl_Slider* o = new Fl_Slider(105, 45, 20, 145, "FL_VERT_NICE_SLIDER");
+      o->type(4);
+      o->box(FL_FLAT_BOX);
+      o->color(10);
+      o->selection_color(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_FL_VERT_NICE_SLIDER);
+      o->align(1);
+    }
+    { Fl_Box* o = new Fl_Box(10, 230, 280, 205, "Fl_Value_Slider");
+      o->box(FL_ENGRAVED_BOX);
+      o->labelfont(1);
+      o->labelsize(12);
+      o->align(17);
+    }
+    { Fl_Value_Slider* o = new Fl_Value_Slider(30, 260, 30, 145, "0");
+      o->selection_color(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_01);
+      o->align(1);
+    }
+    { Fl_Value_Slider* o = new Fl_Value_Slider(70, 275, 30, 140, "FL_VERT_FILL_SLIDER");
+      o->type(2);
+      o->selection_color(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_FL_VERT_FILL_SLIDER1);
+    }
+    { Fl_Value_Slider* o = new Fl_Value_Slider(110, 260, 20, 145, "FL_VERT_NICE_SLIDER");
+      o->type(4);
+      o->box(FL_FLAT_BOX);
+      o->color(10);
+      o->selection_color(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_FL_VERT_NICE_SLIDER1);
+      o->align(1);
+    }
+    { Fl_Slider* o = new Fl_Slider(140, 80, 130, 20, "FL_HORIZONTAL");
+      o->type(1);
+      o->selection_color(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_FL_HORIZONTAL);
+    }
+    { Fl_Slider* o = new Fl_Slider(140, 120, 130, 20, "FL_HOR_FILL_SLIDER");
+      o->type(3);
+      o->selection_color(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_FL_HOR_FILL_SLIDER);
+    }
+    { Fl_Slider* o = new Fl_Slider(140, 160, 130, 20, "FL_HOR_NICE_SLIDER");
+      o->type(5);
+      o->box(FL_FLAT_BOX);
+      o->color(10);
+      o->selection_color(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_FL_HOR_NICE_SLIDER);
+    }
+    { Fl_Value_Slider* o = new Fl_Value_Slider(140, 290, 130, 20, "FL_HOR_SLIDER");
+      o->type(1);
+      o->selection_color(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_FL_HOR_SLIDER);
+    }
+    { Fl_Value_Slider* o = new Fl_Value_Slider(140, 330, 130, 20, "FL_HOR_FILL_SLIDER");
+      o->type(3);
+      o->selection_color(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_FL_HOR_FILL_SLIDER1);
+    }
+    { Fl_Box* o = new Fl_Box(430, 10, 125, 120, "Fl_Adjuster");
+      o->box(FL_ENGRAVED_BOX);
+      o->labelfont(1);
+      o->labelsize(12);
+      o->align(17);
+    }
+    { Fl_Value_Slider* o = new Fl_Value_Slider(140, 370, 130, 20, "FL_HOR_NICE_SLIDER");
+      o->type(5);
+      o->box(FL_FLAT_BOX);
+      o->color(10);
+      o->selection_color(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_FL_HOR_NICE_SLIDER1);
+    }
+    { Fl_Adjuster* o = new Fl_Adjuster(440, 60, 75, 25, "w()>h()");
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_w);
+    }
+    { Fl_Adjuster* o = new Fl_Adjuster(520, 35, 25, 75, "w()labelsize(8);
+      o->callback((Fl_Callback*)cb_w1);
+    }
+    { Fl_Box* o = new Fl_Box(345, 135, 210, 115, "Fl_Counter");
+      o->box(FL_ENGRAVED_BOX);
+      o->labelfont(1);
+      o->labelsize(12);
+      o->align(17);
+    }
+    { Fl_Counter* o = new Fl_Counter(360, 160, 180, 30, "0");
+      o->labelsize(8);
+      o->minimum(-1e+06);
+      o->maximum(1e+06);
+      o->callback((Fl_Callback*)cb_02);
+    }
+    { Fl_Counter* o = new Fl_Counter(360, 205, 180, 30, "FL_SIMPLE_COUNTER");
+      o->type(1);
+      o->labelsize(8);
+      o->minimum(-1e+06);
+      o->maximum(1e+06);
+      o->callback((Fl_Callback*)cb_FL_SIMPLE_COUNTER);
+    }
+    { Fl_Box* o = new Fl_Box(300, 260, 255, 105, "Fl_Dial");
+      o->box(FL_ENGRAVED_BOX);
+      o->labelfont(1);
+      o->labelsize(12);
+      o->align(17);
+    }
+    { Fl_Dial* o = new Fl_Dial(315, 280, 65, 65, "0");
+      o->color(10);
+      o->selection_color(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_03);
+    }
+    { Fl_Dial* o = new Fl_Dial(395, 280, 65, 65, "FL_LINE_DIAL");
+      o->type(1);
+      o->color(10);
+      o->selection_color(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_FL_LINE_DIAL);
+    }
+    { Fl_Dial* o = new Fl_Dial(475, 280, 65, 65, "FL_FILL_DIAL");
+      o->type(2);
+      o->color(10);
+      o->selection_color(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_FL_FILL_DIAL);
+    }
+    { Fl_Box* o = new Fl_Box(300, 375, 145, 120, "Fl_Roller");
+      o->box(FL_ENGRAVED_BOX);
+      o->labelfont(1);
+      o->labelsize(12);
+      o->align(17);
+    }
+    { Fl_Roller* o = new Fl_Roller(315, 390, 20, 95, "0");
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_04);
+    }
+    { Fl_Roller* o = new Fl_Roller(340, 430, 90, 20, "FL_HORIZONTAL");
+      o->type(1);
+      o->labelsize(8);
+      o->callback((Fl_Callback*)cb_FL_HORIZONTAL1);
+    }
+    { Fl_Box* o = new Fl_Box(10, 445, 140, 50, "Fl_Value_Input");
+      o->box(FL_ENGRAVED_BOX);
+      o->labelfont(1);
+      o->labelsize(12);
+      o->align(17);
+    }
+    { Fl_Box* o = new Fl_Box(455, 375, 100, 120, "Some widgets have color(FL_GREEN) and color2(FL_RED) to show the areas the\
+se effect.");
+      o->box(FL_BORDER_FRAME);
+      o->color(0);
+      o->selection_color(0);
+      o->labelsize(10);
+      o->align(128);
+    }
+    { Fl_Box* o = new Fl_Box(155, 445, 135, 50, "Fl_Value_Output");
+      o->box(FL_ENGRAVED_BOX);
+      o->labelfont(1);
+      o->labelsize(12);
+      o->align(17);
+    }
+    { Fl_Value_Input* o = new Fl_Value_Input(30, 460, 110, 30, "0");
+      o->labelsize(8);
+      o->maximum(100);
+      o->step(0.1);
+      o->callback((Fl_Callback*)cb_05);
+      o->when(4);
+    }
+    { Fl_Value_Output* o = new Fl_Value_Output(170, 460, 110, 30, "0");
+      o->labelsize(8);
+      o->maximum(100);
+      o->step(0.1);
+      o->callback((Fl_Callback*)cb_06);
+    }
+    { Fl_Box* o = new Fl_Box(295, 10, 130, 120, "   Fl_Scrollbar");
+      o->box(FL_ENGRAVED_BOX);
+      o->labelfont(1);
+      o->labelsize(12);
+      o->align(21);
+    }
+    { Fl_Scrollbar* o = new Fl_Scrollbar(395, 20, 20, 105, "0");
+      o->labelsize(8);
+      o->maximum(100);
+      o->callback((Fl_Callback*)cb_07);
+      o->align(1);
+    }
+    { Fl_Scrollbar* o = new Fl_Scrollbar(300, 65, 95, 20, "FL_HORIZONTAL");
+      o->type(1);
+      o->labelsize(8);
+      o->maximum(100);
+      o->callback((Fl_Callback*)cb_FL_HORIZONTAL2);
+    }
+    o->end();
+  }
+  w->show(argc, argv);
+  return Fl::run();
+}
diff --git a/test/valuators.H b/test/valuators.H
new file mode 100644
index 000000000..acd872b9b
--- /dev/null
+++ b/test/valuators.H
@@ -0,0 +1,15 @@
+// generated by Fast Light User Interface Designer (fluid) version 0.99
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
diff --git a/test/valuators.fl b/test/valuators.fl
new file mode 100644
index 000000000..8aca64f4e
--- /dev/null
+++ b/test/valuators.fl
@@ -0,0 +1,206 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 0.99 
+header_name {.H} 
+code_name {.C} 
+gridx 5 
+gridy 5 
+snap 3
+Function {} {open
+} {
+  Fl_Window {} {
+    label {Valuator classes, showing values for type()} open
+    xywh {548 340 567 506} color 43 selection_color 43
+    code0 {\#include } visible
+  } {
+    Fl_Box {} {
+      label Fl_Slider
+      xywh {10 10 280 210} box ENGRAVED_BOX labelfont 1 labelsize 12 align 17
+    }
+    Fl_Slider {} {
+      label 0
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {30 45 20 145} selection_color 1 labelsize 8 align 1
+    }
+    Fl_Slider {} {
+      label FL_VERT_FILL_SLIDER
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {70 55 20 145} type {Vert Fill} selection_color 1 labelsize 8
+    }
+    Fl_Slider {} {
+      label FL_VERT_NICE_SLIDER
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {105 45 20 145} type {Vert Knob} box FLAT_BOX color 10 selection_color 1 labelsize 8 align 1
+    }
+    Fl_Box {} {
+      label Fl_Value_Slider
+      xywh {10 230 280 205} box ENGRAVED_BOX labelfont 1 labelsize 12 align 17
+    }
+    Fl_Value_Slider {} {
+      label 0
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {30 260 30 145} selection_color 1 labelsize 8 align 1
+    }
+    Fl_Value_Slider {} {
+      label FL_VERT_FILL_SLIDER
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {70 275 30 140} type {Vert Fill} selection_color 1 labelsize 8
+    }
+    Fl_Value_Slider {} {
+      label FL_VERT_NICE_SLIDER
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {110 260 20 145} type {Vert Knob} box FLAT_BOX color 10 selection_color 1 labelsize 8 align 1
+    }
+    Fl_Slider {} {
+      label FL_HORIZONTAL
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {140 80 130 20} type Horizontal selection_color 1 labelsize 8
+    }
+    Fl_Slider {} {
+      label FL_HOR_FILL_SLIDER
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {140 120 130 20} type {Horz Fill} selection_color 1 labelsize 8
+    }
+    Fl_Slider {} {
+      label FL_HOR_NICE_SLIDER
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {140 160 130 20} type {Horz Knob} box FLAT_BOX color 10 selection_color 1 labelsize 8
+    }
+    Fl_Value_Slider {} {
+      label FL_HOR_SLIDER
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {140 290 130 20} type Horizontal selection_color 1 labelsize 8
+    }
+    Fl_Value_Slider {} {
+      label FL_HOR_FILL_SLIDER
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {140 330 130 20} type {Horz Fill} selection_color 1 labelsize 8
+    }
+    Fl_Box {} {
+      label Fl_Adjuster
+      xywh {430 10 125 120} box ENGRAVED_BOX labelfont 1 labelsize 12 align 17
+    }
+    Fl_Value_Slider {} {
+      label FL_HOR_NICE_SLIDER
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {140 370 130 20} type {Horz Knob} box FLAT_BOX color 10 selection_color 1 labelsize 8
+    }
+    Fl_Adjuster {} {
+      label {w()>h()}
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {440 60 75 25} labelsize 8
+    }
+    Fl_Adjuster {} {
+      label {w()value());
+fflush(stdout);}
+      xywh {520 35 25 75} labelsize 8
+    }
+    Fl_Box {} {
+      label Fl_Counter
+      xywh {345 135 210 115} box ENGRAVED_BOX labelfont 1 labelsize 12 align 17
+    }
+    Fl_Counter {} {
+      label 0
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {360 160 180 30} labelsize 8 minimum -1e+06 maximum 1e+06
+    }
+    Fl_Counter {} {
+      label FL_SIMPLE_COUNTER
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {360 205 180 30} type Simple labelsize 8 minimum -1e+06 maximum 1e+06
+    }
+    Fl_Box {} {
+      label Fl_Dial
+      xywh {300 260 255 105} box ENGRAVED_BOX labelfont 1 labelsize 12 align 17
+    }
+    Fl_Dial {} {
+      label 0
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {315 280 65 65} color 10 selection_color 1 labelsize 8
+    }
+    Fl_Dial {} {
+      label FL_LINE_DIAL
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {395 280 65 65} type Line color 10 selection_color 1 labelsize 8
+    }
+    Fl_Dial {} {
+      label FL_FILL_DIAL
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {475 280 65 65} type Fill color 10 selection_color 1 labelsize 8
+    }
+    Fl_Box {} {
+      label Fl_Roller
+      xywh {300 375 145 120} box ENGRAVED_BOX labelfont 1 labelsize 12 align 17
+    }
+    Fl_Roller {} {
+      label 0
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {315 390 20 95} labelsize 8
+    }
+    Fl_Roller {} {
+      label FL_HORIZONTAL
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {340 430 90 20} type Horizontal labelsize 8
+    }
+    Fl_Box {} {
+      label Fl_Value_Input
+      xywh {10 445 140 50} box ENGRAVED_BOX labelfont 1 labelsize 12 align 17
+    }
+    Fl_Box {} {
+      label {Some widgets have color(FL_GREEN) and color2(FL_RED) to show the areas these effect.}
+      xywh {455 375 100 120} box BORDER_FRAME color 0 selection_color 0 labelsize 10 align 128
+    }
+    Fl_Box {} {
+      label Fl_Value_Output
+      xywh {155 445 135 50} box ENGRAVED_BOX labelfont 1 labelsize 12 align 17
+    }
+    Fl_Value_Input {} {
+      label 0
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);} selected
+      xywh {30 460 110 30} labelsize 8 maximum 100 step 0.1
+    }
+    Fl_Value_Output {} {
+      label 0
+      callback {printf("%g      \\r",o->value());
+fflush(stdout);}
+      xywh {170 460 110 30} labelsize 8 maximum 100 step 0.1
+    }
+    Fl_Box {} {
+      label {   Fl_Scrollbar}
+      xywh {295 10 130 120} box ENGRAVED_BOX labelfont 1 labelsize 12 align 21
+    }
+    Fl_Scrollbar {} {
+      label 0
+      callback {printf("%d      \\r",o->value());
+fflush(stdout);}
+      xywh {395 20 20 105} labelsize 8 align 1 maximum 100
+    }
+    Fl_Scrollbar {} {
+      label FL_HORIZONTAL
+      callback {printf("%d      \\r",o->value());
+fflush(stdout);}
+      xywh {300 65 95 20} type Horizontal labelsize 8 maximum 100
+    }
+  }
+} 
diff --git a/test/white_1.xbm b/test/white_1.xbm
new file mode 100644
index 000000000..0ade331f6
--- /dev/null
+++ b/test/white_1.xbm
@@ -0,0 +1,60 @@
+#define white_1_width 56
+#define white_1_height 56
+static unsigned char white_1_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x05, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x05, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x01, 
+0x80, 0x00, 0x00, 0x00, 0x80, 0xaa, 0x00, 
+0x00, 0x01, 0x00, 0x00, 0x40, 0x55, 0x00, 
+0x00, 0x02, 0x00, 0x00, 0xa8, 0x2a, 0x00, 
+0x00, 0x14, 0x00, 0x00, 0x54, 0x15, 0x00, 
+0x00, 0x28, 0x00, 0x80, 0xaa, 0x0a, 0x00, 
+0x00, 0x50, 0x05, 0x54, 0x55, 0x05, 0x00, 
+0x00, 0xa0, 0xaa, 0xaa, 0xaa, 0x02, 0x00, 
+0x00, 0x40, 0x55, 0x55, 0x55, 0x01, 0x00, 
+0x00, 0x00, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 
+0x00, 0x00, 0x50, 0x55, 0x15, 0x00, 0x00, 
+0x00, 0x00, 0x80, 0xaa, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
diff --git a/test/white_2.xbm b/test/white_2.xbm
new file mode 100644
index 000000000..b916d1226
--- /dev/null
+++ b/test/white_2.xbm
@@ -0,0 +1,60 @@
+#define white_2_width 56
+#define white_2_height 56
+static unsigned char white_2_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 
+0x00, 0x00, 0x04, 0x90, 0x04, 0x00, 0x00, 
+0x00, 0x20, 0x01, 0x40, 0x12, 0x00, 0x00, 
+0x00, 0x48, 0xfc, 0x0f, 0x09, 0x00, 0x00, 
+0x00, 0x10, 0x07, 0x30, 0x04, 0x00, 0x00, 
+0x40, 0xc2, 0x00, 0xc0, 0x10, 0x00, 0x00, 
+0x80, 0x24, 0x00, 0x00, 0x09, 0x00, 0x00, 
+0x20, 0x11, 0x00, 0x00, 0x42, 0x00, 0x00, 
+0x40, 0x08, 0x00, 0x00, 0x20, 0x00, 0x00, 
+0x90, 0x04, 0x00, 0x00, 0x80, 0x00, 0x00, 
+0x20, 0x02, 0x00, 0x00, 0x40, 0x04, 0x00, 
+0x48, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x10, 0x01, 0x00, 0x00, 0x80, 0x08, 0x00, 
+0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 
+0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x80, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 
+0x84, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 
+0xa0, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 
+0x00, 0x01, 0x00, 0x54, 0x01, 0x01, 0x00, 
+0x44, 0x01, 0x00, 0xaa, 0x00, 0x02, 0x00, 
+0x00, 0x02, 0x40, 0x55, 0x80, 0x04, 0x00, 
+0x88, 0x02, 0xa0, 0x0a, 0x00, 0x01, 0x00, 
+0x40, 0x04, 0x50, 0x05, 0x40, 0x02, 0x00, 
+0x00, 0x09, 0xa0, 0x00, 0x80, 0x00, 0x00, 
+0x80, 0x00, 0x50, 0x00, 0x20, 0x01, 0x00, 
+0x00, 0x04, 0x08, 0x00, 0x48, 0x00, 0x00, 
+0x00, 0x02, 0x00, 0x00, 0x90, 0x00, 0x00, 
+0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 
+0x00, 0x24, 0x00, 0x80, 0x04, 0x00, 0x00, 
+0x00, 0x92, 0x00, 0x20, 0x01, 0x00, 0x00, 
+0x00, 0x48, 0x02, 0x08, 0x00, 0x00, 0x00, 
+0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
diff --git a/test/white_3.xbm b/test/white_3.xbm
new file mode 100644
index 000000000..9b721d25b
--- /dev/null
+++ b/test/white_3.xbm
@@ -0,0 +1,60 @@
+#define white_3_width 56
+#define white_3_height 56
+static unsigned char white_3_bits[] = {
+0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00, 
+0x00, 0x40, 0x40, 0x81, 0x00, 0x00, 0x00, 
+0x00, 0x18, 0x40, 0x09, 0x00, 0x00, 0x00, 
+0x00, 0x06, 0x52, 0x09, 0x00, 0x00, 0x00, 
+0x00, 0x91, 0x52, 0x05, 0x00, 0x00, 0x00, 
+0x80, 0x94, 0x50, 0x05, 0x00, 0x00, 0x00, 
+0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x10, 0x01, 0x50, 0x05, 0x60, 0x00, 0x00, 
+0x08, 0x00, 0xaa, 0x2a, 0x00, 0x00, 0x00, 
+0x08, 0x40, 0x55, 0x55, 0x80, 0x01, 0x00, 
+0x04, 0xa0, 0xaa, 0xa0, 0x00, 0x00, 0x00, 
+0x04, 0x50, 0x55, 0x55, 0x05, 0x03, 0x00, 
+0x02, 0xa8, 0x0a, 0xa0, 0x0a, 0x00, 0x00, 
+0x02, 0x54, 0x55, 0x55, 0x15, 0x00, 0x00, 
+0x00, 0xa8, 0x00, 0x80, 0x1a, 0x03, 0x00, 
+0x00, 0x54, 0x55, 0x55, 0x35, 0x00, 0x00, 
+0x00, 0x0a, 0x00, 0x80, 0x2a, 0x06, 0x00, 
+0x0d, 0x45, 0x55, 0x55, 0x55, 0x00, 0x00, 
+0x31, 0x0a, 0x00, 0x00, 0x6a, 0x00, 0x00, 
+0x00, 0x05, 0x55, 0x55, 0x55, 0x07, 0x00, 
+0x3e, 0x02, 0x00, 0x00, 0x6a, 0x00, 0x00, 
+0x00, 0x05, 0x55, 0x55, 0x55, 0x1f, 0x00, 
+0x3e, 0x0a, 0x00, 0x00, 0x68, 0x00, 0x00, 
+0x00, 0x15, 0x54, 0x55, 0x55, 0x1f, 0x00, 
+0x38, 0x0a, 0x00, 0x00, 0x69, 0x00, 0x00, 
+0x01, 0x15, 0x54, 0x95, 0x56, 0x03, 0x00, 
+0x01, 0x2a, 0x00, 0x50, 0x69, 0x0c, 0x00, 
+0x18, 0x54, 0x50, 0xa9, 0x34, 0x00, 0x00, 
+0x00, 0x2a, 0x00, 0x55, 0x2b, 0x00, 0x00, 
+0x30, 0x54, 0x90, 0x2a, 0x15, 0x00, 0x00, 
+0x02, 0xa8, 0x40, 0xb5, 0x1a, 0x00, 0x00, 
+0x00, 0x50, 0xa1, 0x52, 0x0d, 0x00, 0x00, 
+0x30, 0xa0, 0x50, 0xab, 0x06, 0x00, 0x00, 
+0x00, 0x50, 0x29, 0x55, 0x03, 0x00, 0x00, 
+0x60, 0xa0, 0xb2, 0xaa, 0x01, 0x00, 0x00, 
+0x00, 0xc0, 0x55, 0xd5, 0x00, 0x00, 0x00, 
+0x80, 0x01, 0xab, 0x3a, 0x20, 0x00, 0x00, 
+0x00, 0x00, 0xfc, 0x0f, 0x20, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 
+0x00, 0x00, 0xa8, 0x42, 0x0a, 0x00, 0x00, 
+0x00, 0x00, 0xa8, 0x52, 0x02, 0x00, 0x00, 
+0x00, 0x00, 0xa4, 0x12, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
diff --git a/test/white_4.xbm b/test/white_4.xbm
new file mode 100644
index 000000000..189f497a8
--- /dev/null
+++ b/test/white_4.xbm
@@ -0,0 +1,60 @@
+#define white_4_width 56
+#define white_4_height 56
+static unsigned char white_4_bits[] = {
+0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 
+0x00, 0x80, 0xbf, 0x7e, 0x00, 0x00, 0x00, 
+0x00, 0xe0, 0xb6, 0xf6, 0x01, 0x00, 0x00, 
+0x00, 0xb8, 0xad, 0xb6, 0x07, 0x00, 0x00, 
+0x00, 0x6e, 0xad, 0xda, 0x1e, 0x00, 0x00, 
+0x00, 0x6b, 0xab, 0x6a, 0x3b, 0x00, 0x00, 
+0x80, 0xdb, 0xfe, 0xbf, 0x6d, 0x00, 0x00, 
+0xc0, 0xb6, 0x03, 0xf0, 0xf6, 0x00, 0x00, 
+0xe0, 0xee, 0xa8, 0xca, 0x9b, 0x01, 0x00, 
+0xb0, 0x3d, 0x55, 0x15, 0xef, 0x03, 0x00, 
+0x70, 0x9b, 0xaa, 0xaa, 0x76, 0x02, 0x00, 
+0xd8, 0x4e, 0x55, 0x5f, 0xbd, 0x07, 0x00, 
+0xb8, 0xa7, 0xaa, 0xaa, 0xda, 0x04, 0x00, 
+0x6c, 0x53, 0xf5, 0x5f, 0x75, 0x0f, 0x00, 
+0xdc, 0xa9, 0xaa, 0xaa, 0xaa, 0x0b, 0x00, 
+0xb6, 0x55, 0xff, 0x7f, 0xe5, 0x1c, 0x00, 
+0xee, 0xaa, 0xaa, 0xaa, 0x4a, 0x17, 0x00, 
+0xde, 0xf4, 0xff, 0x7f, 0xd5, 0x19, 0x00, 
+0x72, 0xba, 0xaa, 0xaa, 0xaa, 0x1e, 0x00, 
+0x4e, 0xf5, 0xff, 0xff, 0x95, 0x17, 0x00, 
+0x7f, 0xfa, 0xaa, 0xaa, 0xaa, 0x38, 0x00, 
+0x41, 0xfd, 0xff, 0xff, 0x95, 0x3f, 0x00, 
+0x7f, 0xfa, 0xaa, 0xaa, 0xaa, 0x20, 0x00, 
+0x41, 0xf5, 0xff, 0xff, 0x97, 0x3f, 0x00, 
+0x7f, 0xea, 0xab, 0xaa, 0xaa, 0x20, 0x00, 
+0x47, 0xf5, 0xff, 0xff, 0x94, 0x3f, 0x00, 
+0x7a, 0xea, 0xab, 0x2a, 0xa8, 0x1c, 0x00, 
+0x5e, 0xd5, 0xff, 0x0f, 0x94, 0x13, 0x00, 
+0xe6, 0xaa, 0xaf, 0x02, 0xca, 0x1e, 0x00, 
+0xba, 0xd4, 0xff, 0x00, 0xd4, 0x1d, 0x00, 
+0xce, 0xa9, 0x2f, 0x80, 0x6a, 0x1b, 0x00, 
+0x74, 0x55, 0x1f, 0x40, 0xe5, 0x0e, 0x00, 
+0xbc, 0xab, 0x0e, 0xa8, 0xb2, 0x0d, 0x00, 
+0xc8, 0x56, 0x0f, 0x54, 0x79, 0x07, 0x00, 
+0x78, 0xaf, 0x86, 0xaa, 0xdc, 0x06, 0x00, 
+0x90, 0x5b, 0x45, 0x55, 0xb6, 0x03, 0x00, 
+0xf0, 0x3d, 0xaa, 0x2a, 0x6f, 0x03, 0x00, 
+0x60, 0xf6, 0x54, 0xc5, 0xdd, 0x01, 0x00, 
+0xc0, 0xdb, 0x03, 0x70, 0xdb, 0x00, 0x00, 
+0x80, 0x6d, 0xff, 0xdf, 0x76, 0x00, 0x00, 
+0x00, 0xb7, 0x55, 0xb5, 0x35, 0x00, 0x00, 
+0x00, 0xde, 0x56, 0xad, 0x1d, 0x00, 0x00, 
+0x00, 0x78, 0x5b, 0x6d, 0x07, 0x00, 0x00, 
+0x00, 0xe0, 0x5b, 0xdb, 0x01, 0x00, 0x00, 
+0x00, 0x80, 0x5f, 0x7f, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
diff --git a/test/whiteking_1.xbm b/test/whiteking_1.xbm
new file mode 100644
index 000000000..2a3fd088b
--- /dev/null
+++ b/test/whiteking_1.xbm
@@ -0,0 +1,60 @@
+#define whiteking_1_width 56
+#define whiteking_1_height 56
+static unsigned char whiteking_1_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x15, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0a, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x15, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2a, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2a, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x2a, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 
+0x80, 0x00, 0x00, 0x00, 0x80, 0xaa, 0x2a, 
+0x00, 0x01, 0x00, 0x00, 0x40, 0x55, 0x55, 
+0x00, 0x02, 0x00, 0x00, 0xa8, 0xaa, 0x2a, 
+0x00, 0x14, 0x00, 0x00, 0x54, 0x55, 0x15, 
+0x00, 0x28, 0x00, 0x80, 0xaa, 0xaa, 0x2a, 
+0x00, 0x50, 0x05, 0x54, 0x55, 0x55, 0x15, 
+0x00, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 
+0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x05, 
+0x00, 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 
+0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x01, 
+0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 
+0x00, 0x00, 0x54, 0x55, 0x55, 0x55, 0x00, 
+0x00, 0x00, 0xa8, 0xaa, 0xaa, 0x2a, 0x00, 
+0x00, 0x00, 0x40, 0x55, 0x55, 0x15, 0x00, 
+0x00, 0x00, 0x00, 0xaa, 0xaa, 0x02, 0x00, 
+0x00, 0x00, 0x00, 0x50, 0x15, 0x00, 0x00, 
+};
diff --git a/test/whiteking_2.xbm b/test/whiteking_2.xbm
new file mode 100644
index 000000000..9f2e24d23
--- /dev/null
+++ b/test/whiteking_2.xbm
@@ -0,0 +1,60 @@
+#define whiteking_2_width 56
+#define whiteking_2_height 56
+static unsigned char whiteking_2_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 
+0x00, 0x00, 0x04, 0x90, 0x04, 0x00, 0x00, 
+0x00, 0x20, 0x01, 0x40, 0x12, 0x00, 0x00, 
+0x00, 0x48, 0xfc, 0x0f, 0x09, 0x00, 0x00, 
+0x00, 0x10, 0x07, 0x30, 0x04, 0x00, 0x00, 
+0x40, 0xc2, 0x00, 0xc0, 0x10, 0x00, 0x00, 
+0x80, 0x24, 0x00, 0x00, 0x09, 0x00, 0x00, 
+0x20, 0x11, 0x00, 0x00, 0x42, 0x00, 0x00, 
+0x40, 0x08, 0x80, 0x00, 0x20, 0x00, 0x00, 
+0x90, 0x04, 0xc4, 0x10, 0x80, 0x00, 0x00, 
+0x20, 0x02, 0x06, 0x18, 0x40, 0x04, 0x00, 
+0x48, 0x42, 0x00, 0x00, 0x01, 0x00, 0x00, 
+0x10, 0x61, 0x00, 0x88, 0x81, 0x08, 0x00, 
+0x20, 0x01, 0x10, 0x10, 0x00, 0x00, 0x00, 
+0x80, 0x00, 0x20, 0x08, 0x00, 0x01, 0x00, 
+0x80, 0x40, 0x40, 0x10, 0x04, 0x08, 0x00, 
+0x80, 0x80, 0x00, 0x20, 0x02, 0x00, 0x00, 
+0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 
+0x80, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 
+0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 
+0x80, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 
+0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 
+0x84, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 
+0xa0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 
+0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x00, 
+0x44, 0x01, 0x00, 0x40, 0x01, 0x02, 0x00, 
+0x00, 0x02, 0xaa, 0xaa, 0x80, 0x04, 0x00, 
+0x88, 0x02, 0x54, 0x55, 0x00, 0x01, 0x00, 
+0x40, 0x04, 0xaa, 0x2a, 0x40, 0x02, 0x00, 
+0x00, 0x09, 0x54, 0x15, 0x80, 0x00, 0x00, 
+0x80, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 
+0x00, 0x04, 0x00, 0x00, 0x48, 0x00, 0x00, 
+0x00, 0x02, 0x00, 0x00, 0x90, 0x00, 0x00, 
+0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 
+0x00, 0x24, 0x00, 0x80, 0x04, 0x00, 0x00, 
+0x00, 0x92, 0x00, 0x20, 0x01, 0x00, 0x00, 
+0x00, 0x48, 0x02, 0x08, 0x00, 0x00, 0x00, 
+0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
diff --git a/test/whiteking_3.xbm b/test/whiteking_3.xbm
new file mode 100644
index 000000000..95b017d4e
--- /dev/null
+++ b/test/whiteking_3.xbm
@@ -0,0 +1,60 @@
+#define whiteking_3_width 56
+#define whiteking_3_height 56
+static unsigned char whiteking_3_bits[] = {
+0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00, 
+0x00, 0x40, 0x40, 0x81, 0x00, 0x00, 0x00, 
+0x00, 0x18, 0x40, 0x09, 0x00, 0x00, 0x00, 
+0x00, 0x06, 0x52, 0x09, 0x00, 0x00, 0x00, 
+0x00, 0x91, 0x52, 0x05, 0x00, 0x00, 0x00, 
+0x80, 0x94, 0x50, 0x05, 0x00, 0x00, 0x00, 
+0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x10, 0x01, 0x50, 0x05, 0x60, 0x00, 0x00, 
+0x08, 0x00, 0xaa, 0x2a, 0x00, 0x00, 0x00, 
+0x08, 0x40, 0x55, 0x55, 0x80, 0x01, 0x00, 
+0x04, 0xa0, 0x0a, 0xaa, 0x00, 0x00, 0x00, 
+0x04, 0x50, 0x10, 0x41, 0x05, 0x03, 0x00, 
+0x02, 0xa8, 0x08, 0xa2, 0x0a, 0x00, 0x00, 
+0x02, 0x04, 0x50, 0x01, 0x14, 0x00, 0x00, 
+0x00, 0x88, 0xaa, 0x2a, 0x1a, 0x03, 0x00, 
+0x00, 0x04, 0x59, 0x11, 0x34, 0x00, 0x00, 
+0x01, 0xaa, 0xa8, 0xa8, 0x2a, 0x06, 0x00, 
+0x0d, 0x55, 0x51, 0x54, 0x55, 0x00, 0x00, 
+0x31, 0xa2, 0x28, 0x2a, 0x6a, 0x00, 0x00, 
+0x00, 0x45, 0x54, 0x15, 0x55, 0x07, 0x00, 
+0x3e, 0xa2, 0xa8, 0xaa, 0x6b, 0x00, 0x00, 
+0x00, 0x45, 0x55, 0x55, 0x55, 0x1f, 0x00, 
+0x3e, 0x8a, 0xaa, 0xaa, 0x6a, 0x00, 0x00, 
+0x00, 0x45, 0x55, 0xd5, 0x55, 0x1f, 0x00, 
+0x38, 0x8a, 0xaa, 0xaa, 0x6a, 0x00, 0x00, 
+0x01, 0x15, 0x55, 0x55, 0x55, 0x03, 0x00, 
+0x01, 0x2a, 0xaa, 0xea, 0x6a, 0x0c, 0x00, 
+0x19, 0x14, 0x54, 0x55, 0x35, 0x00, 0x00, 
+0x00, 0x2a, 0xaa, 0xaa, 0x2a, 0x00, 0x00, 
+0x30, 0x54, 0x54, 0x55, 0x15, 0x00, 0x00, 
+0x02, 0xa8, 0xaa, 0xaa, 0x1a, 0x00, 0x00, 
+0x00, 0x50, 0x55, 0xd5, 0x0d, 0x00, 0x00, 
+0x30, 0xa0, 0xaa, 0xea, 0x06, 0x00, 0x00, 
+0x00, 0x50, 0x55, 0x55, 0x03, 0x00, 0x00, 
+0x60, 0xa0, 0xaa, 0xaa, 0x01, 0x00, 0x00, 
+0x00, 0xc0, 0x55, 0xd5, 0x00, 0x00, 0x00, 
+0x80, 0x01, 0xab, 0x3a, 0x20, 0x00, 0x00, 
+0x00, 0x00, 0xfc, 0x0f, 0x20, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 
+0x00, 0x00, 0xa8, 0x42, 0x0a, 0x00, 0x00, 
+0x00, 0x00, 0xa8, 0x52, 0x02, 0x00, 0x00, 
+0x00, 0x00, 0xa4, 0x12, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
diff --git a/test/whiteking_4.xbm b/test/whiteking_4.xbm
new file mode 100644
index 000000000..6257a5db4
--- /dev/null
+++ b/test/whiteking_4.xbm
@@ -0,0 +1,60 @@
+#define whiteking_4_width 56
+#define whiteking_4_height 56
+static unsigned char whiteking_4_bits[] = {
+0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 
+0x00, 0x80, 0xbf, 0x7e, 0x00, 0x00, 0x00, 
+0x00, 0xe0, 0xb6, 0xf6, 0x01, 0x00, 0x00, 
+0x00, 0xb8, 0xad, 0xb6, 0x07, 0x00, 0x00, 
+0x00, 0x6e, 0xad, 0xda, 0x1e, 0x00, 0x00, 
+0x00, 0x6b, 0xab, 0x6a, 0x3b, 0x00, 0x00, 
+0x80, 0xdb, 0xfe, 0xbf, 0x6d, 0x00, 0x00, 
+0xc0, 0xb6, 0x03, 0xf0, 0xf6, 0x00, 0x00, 
+0xe0, 0xee, 0xa8, 0xca, 0x9b, 0x01, 0x00, 
+0xb0, 0x3d, 0x55, 0x15, 0xef, 0x03, 0x00, 
+0x70, 0x9b, 0xaa, 0xaa, 0x76, 0x02, 0x00, 
+0xd8, 0x4e, 0xf5, 0x55, 0xbd, 0x07, 0x00, 
+0xb8, 0xa7, 0x6f, 0xbe, 0xda, 0x04, 0x00, 
+0x6c, 0x53, 0x33, 0x4d, 0x75, 0x0f, 0x00, 
+0xdc, 0xf9, 0xa9, 0xe6, 0xab, 0x0b, 0x00, 
+0xb6, 0x35, 0x55, 0xd5, 0xe4, 0x1c, 0x00, 
+0xee, 0x9a, 0xa6, 0x66, 0x4a, 0x17, 0x00, 
+0xde, 0x54, 0x47, 0x47, 0xd5, 0x19, 0x00, 
+0x72, 0xaa, 0x8e, 0xa3, 0xaa, 0x1e, 0x00, 
+0x4e, 0x1d, 0x97, 0xc5, 0x91, 0x17, 0x00, 
+0x7f, 0x3a, 0xab, 0xca, 0xa8, 0x38, 0x00, 
+0x41, 0x5d, 0x57, 0x55, 0x90, 0x3f, 0x00, 
+0x7f, 0xba, 0xaa, 0xaa, 0xa8, 0x20, 0x00, 
+0x41, 0x75, 0x55, 0x55, 0x94, 0x3f, 0x00, 
+0x7f, 0xba, 0xaa, 0x2a, 0xa8, 0x20, 0x00, 
+0x47, 0x75, 0x55, 0x55, 0x94, 0x3f, 0x00, 
+0x7a, 0xea, 0xaa, 0x2a, 0xaa, 0x1c, 0x00, 
+0x5e, 0xd5, 0x55, 0x15, 0x94, 0x13, 0x00, 
+0xe6, 0xea, 0xab, 0x2a, 0xca, 0x1e, 0x00, 
+0xba, 0xd4, 0x55, 0x15, 0xd4, 0x1d, 0x00, 
+0xce, 0xa9, 0x01, 0x00, 0x6a, 0x1b, 0x00, 
+0x74, 0x55, 0x01, 0x00, 0xe5, 0x0e, 0x00, 
+0xbc, 0xab, 0x00, 0x00, 0xb2, 0x0d, 0x00, 
+0xc8, 0x56, 0x01, 0x00, 0x79, 0x07, 0x00, 
+0x78, 0xaf, 0xaa, 0xaa, 0xdc, 0x06, 0x00, 
+0x90, 0x5b, 0x55, 0x55, 0xb6, 0x03, 0x00, 
+0xf0, 0x3d, 0xaa, 0x2a, 0x6f, 0x03, 0x00, 
+0x60, 0xf6, 0x54, 0xc5, 0xdd, 0x01, 0x00, 
+0xc0, 0xdb, 0x03, 0x70, 0xdb, 0x00, 0x00, 
+0x80, 0x6d, 0xff, 0xdf, 0x76, 0x00, 0x00, 
+0x00, 0xb7, 0x55, 0xb5, 0x35, 0x00, 0x00, 
+0x00, 0xde, 0x56, 0xad, 0x1d, 0x00, 0x00, 
+0x00, 0x78, 0x5b, 0x6d, 0x07, 0x00, 0x00, 
+0x00, 0xe0, 0x5b, 0xdb, 0x01, 0x00, 0x00, 
+0x00, 0x80, 0x5f, 0x7f, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
diff --git a/version b/version
new file mode 100644
index 000000000..1b8671e4f
--- /dev/null
+++ b/version
@@ -0,0 +1,2 @@
+VERSION =0
+REVISION =99
diff --git a/visualc/README b/visualc/README
new file mode 100644
index 000000000..9c0bd2fc2
--- /dev/null
+++ b/visualc/README
@@ -0,0 +1,198 @@
+How to compile for Windoze:
+
+Fltk has been reported to compile with GNU GCC compilers, with
+MicroSoft Visual C++ version 4 and 5, and with Borland's C++ compiler
+(sorry no info on that here).
+
+----------------------------------------------------------------
+Using GNU C compilers (MingW32 and/or Cygnus):
+----------------------------------------------------------------
+
+Edited from mail from Carl Thompson:
+
+MINGW32 and Cygnus are both ports of the GNU compiler to win32.  The
+difference is that Cygnus will emulate a complete Unix development
+environment including nearly all of the standard Unix system calls.  This
+allows Unix programs to be ported to win32 possibly without changing a
+single line of source code.  However, the applications it generates are big,
+very slow, depend on the Cygnus DLL, and currently somewhat unstable.  For
+straight Windows applications / Libraries like FLTK that do not require Unix
+system call emulation, MINGW32 is the superior choice.  MINGW32 produces a
+plain Windows binary that is only dependent on the normal Windows DLLs.
+
+Some links for getting MINGW32:
+
+http://agnes.dida.physik.uni-essen.de/~janjaap/mingw32/download.html
+http://www.cygnus.com/misc/gnu-win32/index.html
+ftp://objectcentral.com/mingw32
+
+You will of course need GNU make for MINGW32 in addition to the regular
+MINGW32 utilities.  You also need the OpenGL header files which
+apparently are not always included with mingw32, get them from the
+above ftp site.
+
+More instructions from Rick Sayre (at Pixar):
+
+BTW, for what it's worth, here's the list of changes I have to make to get
+fltk and the examples to build under MINGW32 (which I've switched to from
+CYGWIN, since programs compiled under it use standard DLL's rather than the 
+extremely bugging cygwin.dll, and it just otherwise seems to work better):
+
+Run ./configure
+-
+In makeinclude - change the CFLAGS and CXXFLAGS to add "-O2 -DWIN32"
+change the libraries to "-lgdi32 -luser32"  (add "-mwindows" to not get
+a console)
+-
+In config.h - set HAVE_SCANDIR to 0.  ./configure seems to do this
+correctly now, but it was occasionally in the past setting it to 1
+-
+in src/Makefile:
+    change the "ar" command to use the "ar -M < ar.script" form.  This
+is needed only because I compile under Cygwin's B19 bash, which blows up in
+all sorts of bad ways (hard resets[!]) on long command lines.  More details
+if you care, but most people might not.  Just a warning.
+-
+in test/demo.menu
+    Change the paths to DOS form [blech!], don't use "&"
+[A better idea would be to replace system() with a call that knows how
+to fake a fork on Winblows]
+-
+in fluid/Makefile
+Change the make install rules to reference "fluid.exe" for installing and
+strip'ing, rather than "fluid"
+
+I suspect that it is very likely not a good idea to try "make install" under
+Windows.  Instead, copy "libfltk.a" to "C:\MINGW32\LIB" (replace
+"C:\MINGW32" with the directory in which you installed MINGW32).  Then copy
+the entire "FL" directory to "C:\MINGW32\INCLUDE".
+
+From Gustavo Hime:
+
+First, thank you for the nice piece of software, and congratulations
+on the quality source code. Fltk compiles (and runs) beautifully on
+all the systems I use (Irix 6.4,Solaris 2.5, RedHat Linux 5.0): the
+exception was Windows, where compilation was rather hard.
+
+I have just now managed to compile (satisfactorily) fltk on Win95
+using Mingw32: I do not have MSVC (I don't believe in Microsoft
+compilers :)), and we (the project I am engaged in) are going to use
+mingw32 to port unix code to windows anyway, so mingw32 was the way to
+go. Here is a list of what I had to do:
+
+Modify ar -mwindows to ar -ruv in your makeinclude.mingw32.
+
+Added -DCYGNUS to your *FLAGS variables (I am new to mingw32, I don't
+know what it defines to id itself, but they are so close I don't think
+it matters much).
+
+Disable GL overlay in win32/config.h (shouldn't this be the default?).
+
+Added dummy makedepend files to directories fluid and src.
+
+Created empty lib directory.
+
+Fixed scroll.C line 83 (implicit typecast from int to const char * in
+function call, mingw32 has a problem with this)
+
+Did not fix list_visuals.C (weird code there, where is the main
+functionfor win32?)
+
+And finally, the hardest: downloaded the OpenGL headers for mingw32
+fromftp://objectcentral.com/mingw32. These are not included in the
+mingw32 distribution, and it took me a couple of hours to find them on
+the net. It would be nice to add a note about this in the fltk
+documentation, and I'll send an e-mail asking them to add these
+headers to the mingw32 distribution.
+
+Once again, great code. With mingw32, fltk and opengl, I can
+imediatellyport all my old windows code to unix, and I no longer need
+to waste 300+ mb of hard-drive on stupid borland compilers.
+
+----------------------------------------------------------------
+Using MSVC++:
+----------------------------------------------------------------
+
+If you have MSVC++ 5.0, double click the "fltk.dsw".  Make the "fltk"
+project current, and build it.  This will create the library in
+../lib/fltkd.lib.  To build the demo programs, select the "demo"
+project and build it.  To run the demos run the demo project.
+
+I only have Pentium and Alpha NT machines running MSVC++ 5.0.  Other
+users have reported success compiling fltk on Windowe95, and using
+version 4 of MSVC++, Borland's C++ compiler, and various ports of GCC
+to windows (to use these, look at the "makeinclude" files in
+../makefiles).
+
+If you want to make non-console apps you have to do something special,
+and that differs on each compiler/linker package.  For MSVC++ the
+secret switch is:
+
+	/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup
+
+For cygwin/mingw32 and perhaps some other compilers based on gcc put
+this in the makeinclude file:
+
+	LDLIBS =-lgdi32 -luser32 -mwindows
+
+There are no makefiles, for MSVC++ or any other compiler, because I
+don't know how to write them (the ones dumped by MSVC++ are useless
+and unreadable).
+
+----------------------------------------------------------------
+Other compilers:
+----------------------------------------------------------------
+
+I have heard that Borland C++ is usable.
+
+You probably need to start with the Unix Makefiles.  There is one in
+../src, one in ../fluid, and one in ../test.  Edit these as necessary
+and compile.  You must add "-DWIN32" to your compiler switches.
+
+The biggest problem seems to be differences in the windows.h header
+files (MicroSoft copyrighted theirs?).  Some functions and macros have
+different names or are missing.
+
+The MSVC++ "makefiles" are totally useless.  Ignore that crap.
+
+Start with the Unix makefiles, which list all the necessary source
+files.  Don't try to compile the files ending in _win32.C, they are
+#included by other files if WIN32 is defined.
+
+When compiling the symbol WIN32 must be defined (most compilers do
+this?) and you have to set the include path so the file win32/config.h
+is seen when the code does #include .  You may need to use
+some sort of switch to force the compiler to compile the files with
+C++ rather than C.  On MSVC++ this is the obvious acronym "/TP" :-)
+Not doing these steps will result in lots of cryptic errors.
+
+----------------------------------------------------------------
+Known problems and ToDo list:
+----------------------------------------------------------------
+
+It does not work if you turn on full optimizations in VC++.  I have
+been told this is due to bugs in VC++, but if anybody can find a way
+around them it would be nice... (the "optimize" settings in the
+project files only do partial optimization and work ok).
+
+If program is deactivated, Fl::wait() does not return until it is
+activated again, even though things happen, like redraws.  This could
+break some programs that rely on executing code after Fl::wait().
+
+Fl_Gl_Window::can_do_overlay() returns true until the first time it
+attempts to draw an overlay, and then correctly returns whether or not
+there is overlay hardware.
+
+Cut text contains ^J rather than ^M^J to break lines.  This is a
+feature, not a bug.
+
+Fl_Window::fullscreen() not implemented (should take over the screen
+without a title bar).  Currently does maximize instead.
+
+Reports of clipping problems on '95.  Can't reproduce on NT.
+
+Need to import .bmp files into fluid. Wonko has the specs.
+
+Can't set icon of windows.
+
+Transparent parts of pixmaps do not really work.
diff --git a/visualc/adjuster.dsp b/visualc/adjuster.dsp
new file mode 100644
index 000000000..8d07a0c3a
--- /dev/null
+++ b/visualc/adjuster.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="adjuster" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=adjuster - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "adjuster.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "adjuster.mak" CFG="adjuster - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "adjuster - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "adjuster - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "adjuster - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/adjuster.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "adjuster - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "adjuster_"
+# PROP BASE Intermediate_Dir "adjuster_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "adjuster_"
+# PROP Intermediate_Dir "adjuster_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/adjuster.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "adjuster - Win32 Release"
+# Name "adjuster - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\adjuster.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/arc.dsp b/visualc/arc.dsp
new file mode 100644
index 000000000..c278178e6
--- /dev/null
+++ b/visualc/arc.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="arc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=arc - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "arc.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "arc.mak" CFG="arc - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "arc - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "arc - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "arc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/arc.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "arc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "arc_"
+# PROP BASE Intermediate_Dir "arc_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "arc_"
+# PROP Intermediate_Dir "arc_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/arc.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "arc - Win32 Release"
+# Name "arc - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\arc.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/ask.dsp b/visualc/ask.dsp
new file mode 100644
index 000000000..356b857a5
--- /dev/null
+++ b/visualc/ask.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="ask" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=ask - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "ask.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "ask.mak" CFG="ask - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "ask - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "ask - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "ask - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/ask.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "ask - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "ask_"
+# PROP BASE Intermediate_Dir "ask_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "ask_"
+# PROP Intermediate_Dir "ask_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/ask.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "ask - Win32 Release"
+# Name "ask - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\ask.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/bitmap.dsp b/visualc/bitmap.dsp
new file mode 100644
index 000000000..1513b2caa
--- /dev/null
+++ b/visualc/bitmap.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="bitmap" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=bitmap - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "bitmap.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "bitmap.mak" CFG="bitmap - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "bitmap - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "bitmap - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "bitmap - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/bitmap.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "bitmap - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "bitmap_"
+# PROP BASE Intermediate_Dir "bitmap_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "bitmap_"
+# PROP Intermediate_Dir "bitmap_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/bitmap.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "bitmap - Win32 Release"
+# Name "bitmap - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\bitmap.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/boxtype.dsp b/visualc/boxtype.dsp
new file mode 100644
index 000000000..e6272cfac
--- /dev/null
+++ b/visualc/boxtype.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="boxtype" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=boxtype - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "boxtype.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "boxtype.mak" CFG="boxtype - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "boxtype - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "boxtype - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "boxtype - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/boxtype.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "boxtype - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "boxtype_"
+# PROP BASE Intermediate_Dir "boxtype_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "boxtype_"
+# PROP Intermediate_Dir "boxtype_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/boxtype.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "boxtype - Win32 Release"
+# Name "boxtype - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\boxtype.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/browser.dsp b/visualc/browser.dsp
new file mode 100644
index 000000000..5367a0594
--- /dev/null
+++ b/visualc/browser.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="browser" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=browser - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "browser.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "browser.mak" CFG="browser - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "browser - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "browser - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "browser - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/browser.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "browser - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "browser_"
+# PROP BASE Intermediate_Dir "browser_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "browser_"
+# PROP Intermediate_Dir "browser_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/browser.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "browser - Win32 Release"
+# Name "browser - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\browser.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/button.dsp b/visualc/button.dsp
new file mode 100644
index 000000000..d38bc6f71
--- /dev/null
+++ b/visualc/button.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="button" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=button - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "button.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "button.mak" CFG="button - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "button - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "button - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "button - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/button.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "button - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "button_"
+# PROP BASE Intermediate_Dir "button_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "button_"
+# PROP Intermediate_Dir "button_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/button.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "button - Win32 Release"
+# Name "button - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\button.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/buttons.dsp b/visualc/buttons.dsp
new file mode 100644
index 000000000..b91b8abe8
--- /dev/null
+++ b/visualc/buttons.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="buttons" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=buttons - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "buttons.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "buttons.mak" CFG="buttons - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "buttons - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "buttons - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "buttons - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/buttons.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "buttons - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "buttons_"
+# PROP BASE Intermediate_Dir "buttons_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "buttons_"
+# PROP Intermediate_Dir "buttons_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/buttons.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "buttons - Win32 Release"
+# Name "buttons - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\buttons.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/checkers.dsp b/visualc/checkers.dsp
new file mode 100644
index 000000000..fe9e63e04
--- /dev/null
+++ b/visualc/checkers.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="checkers" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=checkers - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "checkers.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "checkers.mak" CFG="checkers - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "checkers - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "checkers - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "checkers - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/checkers.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "checkers - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "checkers_"
+# PROP BASE Intermediate_Dir "checkers_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "checkers_"
+# PROP Intermediate_Dir "checkers_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/checkers.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "checkers - Win32 Release"
+# Name "checkers - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\checkers.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/clock.dsp b/visualc/clock.dsp
new file mode 100644
index 000000000..a36c39e7f
--- /dev/null
+++ b/visualc/clock.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="clock" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=clock - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "clock.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "clock.mak" CFG="clock - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "clock - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "clock - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "clock - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/clock.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "clock - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "clock_"
+# PROP BASE Intermediate_Dir "clock_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "clock_"
+# PROP Intermediate_Dir "clock_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/clock.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "clock - Win32 Release"
+# Name "clock - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\clock.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/colbrowser.dsp b/visualc/colbrowser.dsp
new file mode 100644
index 000000000..e3e4c957c
--- /dev/null
+++ b/visualc/colbrowser.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="colbrowser" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=colbrowser - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "colbrowser.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "colbrowser.mak" CFG="colbrowser - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "colbrowser - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "colbrowser - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "colbrowser - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/colbrowser.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "colbrowser - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "colbrowser_"
+# PROP BASE Intermediate_Dir "colbrowser_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "colbrowser_"
+# PROP Intermediate_Dir "colbrowser_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/colbrowser.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "colbrowser - Win32 Release"
+# Name "colbrowser - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\colbrowser.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/color_chooser.dsp b/visualc/color_chooser.dsp
new file mode 100644
index 000000000..91d089702
--- /dev/null
+++ b/visualc/color_chooser.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="color_chooser" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=color_chooser - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "color_chooser.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "color_chooser.mak" CFG="color_chooser - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "color_chooser - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "color_chooser - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "color_chooser - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/color_chooser.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "color_chooser - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "color_chooser_"
+# PROP BASE Intermediate_Dir "color_chooser_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "color_chooser_"
+# PROP Intermediate_Dir "color_chooser_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/color_chooser.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "color_chooser - Win32 Release"
+# Name "color_chooser - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\color_chooser.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/config.h b/visualc/config.h
new file mode 100644
index 000000000..fa8d6db76
--- /dev/null
+++ b/visualc/config.h
@@ -0,0 +1,52 @@
+/* config.h
+   This is a replacement for the file ../config.h which is produced by
+   the GNU configure script on Unix systems.  Most of these symbols
+   cannot be turned on as they will turn on X-specific code.  Some
+   should work, however. */
+
+/* Thickness of FL_UP_BOX and FL_DOWN_BOX.  Current 1,2, and 3 are
+   supported.  3 is the historic fltk look.  2 looks more like windoze
+   (and KDE and Qt).  1 is a plausible future evolution...  Notice
+   that this may be simulated at runtime by redefining the boxtypes
+   using Fl::set_boxtype() */
+#define BORDER_WIDTH 3
+
+/* Do you have OpenGL?
+   Set this to 0 if you don't plan to use OpenGL, and fltk will be smaller */
+#define HAVE_GL 1
+/* Turn this on if your GL card has overlay hardware: */
+#define HAVE_GL_OVERLAY 1
+
+/* Turning this on causes fltk to use it's own palette on 8-bit displays.
+   Currently the result is similar to the X version with Fl::own_colormap,
+   in that it may produce colormap flashing if only one palette is
+   supported at a time (I could not test this because my driver supports
+   a very large number of palettes!).
+   Current bugs:
+    Fl::set_color() does not work after first window shown()
+    Probably causes colormap flashing.
+   Turning this off will save a chunk of code, and it will still "sort of"
+   work on an 8-bit display (you get dithering) */
+#define USE_COLORMAP 1
+
+/* X specific, leave off: */
+#define HAVE_XDBE 0
+#define USE_XDBE 0
+
+/* X specific, leave off: */
+#define HAVE_OVERLAY 0
+
+/* Byte order of your machine: (not used by win32 code) */
+#define WORDS_BIGENDIAN 0
+
+/* Types that are 32 bits and 16 bits long.  Used by fl_draw_image only: */
+#define U16 unsigned short
+#define U32 unsigned
+/* #undef U64 */
+
+/* Where is  (used only by fl_file_chooser and scandir): */
+#define HAVE_DIRENT_H 1
+#define HAVE_SYS_NDIR_H 0
+#define HAVE_SYS_DIR_H 0
+#define HAVE_NDIR_H 0
+#define HAVE_SCANDIR 0
diff --git a/visualc/cube.dsp b/visualc/cube.dsp
new file mode 100644
index 000000000..1ecd444b1
--- /dev/null
+++ b/visualc/cube.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="cube" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=cube - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "cube.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "cube.mak" CFG="cube - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "cube - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "cube - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "cube - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/cube.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "cube - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "cube_"
+# PROP BASE Intermediate_Dir "cube_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "cube_"
+# PROP Intermediate_Dir "cube_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 opengl32.lib ..\lib\fltkd.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/cube.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "cube - Win32 Release"
+# Name "cube - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\cube.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/cursor.dsp b/visualc/cursor.dsp
new file mode 100644
index 000000000..a9da2a91c
--- /dev/null
+++ b/visualc/cursor.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="cursor" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=cursor - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "cursor.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "cursor.mak" CFG="cursor - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "cursor - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "cursor - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "cursor - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/cursor.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "cursor - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "cursor_"
+# PROP BASE Intermediate_Dir "cursor_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "cursor_"
+# PROP Intermediate_Dir "cursor_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/cursor.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "cursor - Win32 Release"
+# Name "cursor - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\cursor.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/curve.dsp b/visualc/curve.dsp
new file mode 100644
index 000000000..f26b07f7d
--- /dev/null
+++ b/visualc/curve.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="curve" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=curve - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "curve.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "curve.mak" CFG="curve - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "curve - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "curve - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "curve - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/curve.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "curve - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "curve_"
+# PROP BASE Intermediate_Dir "curve_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "curve_"
+# PROP Intermediate_Dir "curve_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/curve.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "curve - Win32 Release"
+# Name "curve - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\curve.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/demo.dsp b/visualc/demo.dsp
new file mode 100644
index 000000000..daa5dfdaa
--- /dev/null
+++ b/visualc/demo.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="demo" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=demo - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "demo.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "demo.mak" CFG="demo - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "demo - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "demo - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "demo - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/demo.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "demo - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "demo_"
+# PROP BASE Intermediate_Dir "demo_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "demo_"
+# PROP Intermediate_Dir "demo_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/demo.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "demo - Win32 Release"
+# Name "demo - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\demo.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/doublebuffer.dsp b/visualc/doublebuffer.dsp
new file mode 100644
index 000000000..54794442b
--- /dev/null
+++ b/visualc/doublebuffer.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="doublebuffer" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=doublebuffer - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "doublebuffer.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "doublebuffer.mak" CFG="doublebuffer - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "doublebuffer - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "doublebuffer - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "doublebuffer - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/doublebuffer.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "doublebuffer - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "doublebuffer_"
+# PROP BASE Intermediate_Dir "doublebuffer_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "doublebuffer_"
+# PROP Intermediate_Dir "doublebuffer_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/doublebuffer.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "doublebuffer - Win32 Release"
+# Name "doublebuffer - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\doublebuffer.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/fast_slow.dsp b/visualc/fast_slow.dsp
new file mode 100644
index 000000000..85f969095
--- /dev/null
+++ b/visualc/fast_slow.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="fast_slow" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=fast_slow - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "fast_slow.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "fast_slow.mak" CFG="fast_slow - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "fast_slow - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "fast_slow - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "fast_slow - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/fast_slow.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "fast_slow - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "fast_slow_"
+# PROP BASE Intermediate_Dir "fast_slow_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "fast_slow_"
+# PROP Intermediate_Dir "fast_slow_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/fast_slow.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "fast_slow - Win32 Release"
+# Name "fast_slow - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\fast_slow.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/file_chooser.dsp b/visualc/file_chooser.dsp
new file mode 100644
index 000000000..ea47fe127
--- /dev/null
+++ b/visualc/file_chooser.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="file_chooser" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=file_chooser - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "file_chooser.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "file_chooser.mak" CFG="file_chooser - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "file_chooser - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "file_chooser - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "file_chooser - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/file_chooser.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "file_chooser - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "file_chooser_"
+# PROP BASE Intermediate_Dir "file_chooser_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "file_chooser_"
+# PROP Intermediate_Dir "file_chooser_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/file_chooser.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "file_chooser - Win32 Release"
+# Name "file_chooser - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\file_chooser.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/fltk.dsw b/visualc/fltk.dsw
new file mode 100644
index 000000000..c9bfed2b3
--- /dev/null
+++ b/visualc/fltk.dsw
@@ -0,0 +1,1013 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "adjuster"=".\adjuster.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "arc"=".\arc.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "ask"=".\ask.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "bitmap"=".\bitmap.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "boxtype"=".\boxtype.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "browser"=".\browser.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "button"=".\button.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "buttons"=".\buttons.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "checkers"=".\checkers.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "clock"=".\clock.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "colbrowser"=".\colbrowser.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "color_chooser"=".\color_chooser.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "cube"=".\cube.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "cursor"=".\cursor.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "curve"=".\curve.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "demo"=".\demo.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name adjuster
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name arc
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name ask
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name bitmap
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name boxtype
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name browser
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name button
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name buttons
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name checkers
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name clock
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name colbrowser
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name color_chooser
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name cube
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name cursor
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name curve
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name doublebuffer
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name fast_slow
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name file_chooser
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name fluid
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name fonts
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name forms
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name fractals
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name fullscreen
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name gl_overlay
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name glpuzzle
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name hello
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name iconize
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name image
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name input
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name keyboard
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name label
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name mandelbrot
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name menubar
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name message
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name minimum
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name navigation
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name output
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name overlay
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name pixmap
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name pixmap_browser
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name radio
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name resize
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name resizebox
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name scroll
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name shape
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name shiny
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name subwindow
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name symbols
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name tabs
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name tile
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name valuators
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name pack
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name style
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name inactive
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "doublebuffer"=".\doublebuffer.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "fast_slow"=".\fast_slow.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "file_chooser"=".\file_chooser.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "fltk"=".\fltk.lib.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "fluid"=".\fluid.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "fonts"=".\fonts.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "forms"=".\forms.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "fractals"=".\fractals.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "fullscreen"=".\fullscreen.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "gl_overlay"=".\gl_overlay.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "glpuzzle"=".\glpuzzle.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "hello"=".\hello.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "iconize"=".\iconize.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "image"=".\image.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "inactive"=".\inactive.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "input"=".\input.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "keyboard"=".\keyboard.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "label"=".\label.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "mandelbrot"=".\mandelbrot.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "menubar"=".\menubar.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "message"=".\message.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "minimum"=".\minimum.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "navigation"=".\navigation.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "output"=".\output.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "overlay"=".\overlay.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "pack"=".\pack.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "pixmap"=".\pixmap.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "pixmap_browser"=".\pixmap_browser.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "radio"=".\radio.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "resize"=".\resize.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "resizebox"=".\resizebox.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "scroll"=".\scroll.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "shape"=".\shape.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "shiny"=".\shiny.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "style"=".\style.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "subwindow"=".\subwindow.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "symbols"=".\symbols.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "tabs"=".\tabs.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "tile"=".\tile.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "valuators"=".\valuators.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name fltk
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/visualc/fltk.lib.dsp b/visualc/fltk.lib.dsp
new file mode 100644
index 000000000..fdd50d21f
--- /dev/null
+++ b/visualc/fltk.lib.dsp
@@ -0,0 +1,534 @@
+# Microsoft Developer Studio Project File - Name="fltk" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=fltk - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "fltk.lib.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "fltk.lib.mak" CFG="fltk - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "fltk - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "fltk - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+
+!IF  "$(CFG)" == "fltk - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /Os /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\fltk.lib"
+
+!ELSEIF  "$(CFG)" == "fltk - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /TP /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\fltkd.lib"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "fltk - Win32 Release"
+# Name "fltk - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\src\filename_absolute.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\filename_expand.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\filename_ext.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\filename_isdir.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\filename_list.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\filename_match.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\filename_setext.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_abort.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Adjuster.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_arc.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_arci.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_arg.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_ask.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Bitmap.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Box.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_boxtype.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Browser.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Browser_.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Browser_load.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Button.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Chart.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Check_Button.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Choice.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Clock.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_color.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Color_Chooser.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Counter.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_cursor.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_curve.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_cutpaste.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Dial.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_diamond_box.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_display.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Double_Window.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_draw.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_draw_image.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_draw_pixmap.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_engraved_label.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_file_chooser.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_font.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_get_key.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_get_system_colors.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Gl_Choice.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Gl_Choice.H
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Gl_Overlay.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Gl_Window.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Group.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Image.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Input.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Input_.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_labeltype.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Light_Button.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Menu.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Menu_.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Menu_add.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Menu_Bar.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Menu_Button.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Menu_global.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Menu_Window.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Multi_Label.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Output.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_oval_box.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_overlay.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_overlay_visual.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Overlay_Window.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_own_colormap.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Pack.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Pixmap.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Positioner.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_rect.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Repeat_Button.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Return_Button.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Roller.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_round_box.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Round_Button.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_rounded_box.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Scroll.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_scroll_area.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Scrollbar.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_set_font.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_set_fonts.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_shadow_box.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_shortcut.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_show_colormap.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Single_Window.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Slider.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_symbols.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Tabs.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Tile.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Valuator.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Value_Input.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Value_Output.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Value_Slider.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\fl_vertex.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_visual.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Widget.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Window.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Window_fullscreen.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Window_hotspot.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_Window_iconize.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Fl_x.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\forms_bitmap.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\forms_compatability.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\forms_free.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\forms_fselect.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\forms_pixmap.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\forms_timer.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\gl_draw.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\gl_start.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\glut_compatability.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\glut_font.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\numericsort.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\scandir.c
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/fluid.dsp b/visualc/fluid.dsp
new file mode 100644
index 000000000..386047ad2
--- /dev/null
+++ b/visualc/fluid.dsp
@@ -0,0 +1,156 @@
+# Microsoft Developer Studio Project File - Name="fluid" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=fluid - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "fluid.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "fluid.mak" CFG="fluid - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "fluid - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "fluid - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "fluid - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "fluid___"
+# PROP BASE Intermediate_Dir "fluid___"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "fluid___"
+# PROP Intermediate_Dir "fluid___"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /Os /Ob2 /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../fluid/fluid.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "fluid - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "fluid__0"
+# PROP BASE Intermediate_Dir "fluid__0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "fluid__0"
+# PROP Intermediate_Dir "fluid__0"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../fluid/fluid.exe" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "fluid - Win32 Release"
+# Name "fluid - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\fluid\about_panel.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\fluid\alignment_panel.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\fluid\code.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\fluid\factory.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\fluid\file.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\fluid\Fl_Function_Type.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\fluid\Fl_Group_Type.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\fluid\Fl_Menu_Type.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\fluid\Fl_Type.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\fluid\Fl_Widget_Type.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\fluid\Fl_Window_Type.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\fluid\fluid.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\fluid\Fluid_Image.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\fluid\function_panel.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\fluid\gif.C
+# End Source File
+# Begin Source File
+
+SOURCE=..\fluid\widget_panel.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/fonts.dsp b/visualc/fonts.dsp
new file mode 100644
index 000000000..b64c50209
--- /dev/null
+++ b/visualc/fonts.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="fonts" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=fonts - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "fonts.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "fonts.mak" CFG="fonts - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "fonts - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "fonts - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "fonts - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/fonts.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "fonts - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "fonts_"
+# PROP BASE Intermediate_Dir "fonts_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "fonts_"
+# PROP Intermediate_Dir "fonts_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/fonts.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "fonts - Win32 Release"
+# Name "fonts - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\fonts.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/forms.dsp b/visualc/forms.dsp
new file mode 100644
index 000000000..58206ba2d
--- /dev/null
+++ b/visualc/forms.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="forms" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=forms - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "forms.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "forms.mak" CFG="forms - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "forms - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "forms - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "forms - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/forms.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "forms - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "forms_"
+# PROP BASE Intermediate_Dir "forms_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "forms_"
+# PROP Intermediate_Dir "forms_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/forms.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "forms - Win32 Release"
+# Name "forms - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\forms.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/fractals.dsp b/visualc/fractals.dsp
new file mode 100644
index 000000000..0d35ed605
--- /dev/null
+++ b/visualc/fractals.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="fractals" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=fractals - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "fractals.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "fractals.mak" CFG="fractals - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "fractals - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "fractals - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "fractals - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 glu32.lib opengl32.lib ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/fractals.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "fractals - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "fractals_"
+# PROP BASE Intermediate_Dir "fractals_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "fractals_"
+# PROP Intermediate_Dir "fractals_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 glu32.lib opengl32.lib ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/fractals.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "fractals - Win32 Release"
+# Name "fractals - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\fractals.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/fullscreen.dsp b/visualc/fullscreen.dsp
new file mode 100644
index 000000000..d2948bcba
--- /dev/null
+++ b/visualc/fullscreen.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="fullscreen" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=fullscreen - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "fullscreen.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "fullscreen.mak" CFG="fullscreen - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "fullscreen - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "fullscreen - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "fullscreen - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 opengl32.lib ..\lib\fltk.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/fullscreen.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "fullscreen - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "fullscreen_"
+# PROP BASE Intermediate_Dir "fullscreen_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "fullscreen_"
+# PROP Intermediate_Dir "fullscreen_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 opengl32.lib ..\lib\fltkd.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/fullscreen.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "fullscreen - Win32 Release"
+# Name "fullscreen - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\fullscreen.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/gl_overlay.dsp b/visualc/gl_overlay.dsp
new file mode 100644
index 000000000..38ed3579c
--- /dev/null
+++ b/visualc/gl_overlay.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="gl_overlay" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=gl_overlay - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "gl_overlay.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "gl_overlay.mak" CFG="gl_overlay - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "gl_overlay - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "gl_overlay - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "gl_overlay - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/gl_overlay.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "gl_overlay - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "gl_overlay_"
+# PROP BASE Intermediate_Dir "gl_overlay_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "gl_overlay_"
+# PROP Intermediate_Dir "gl_overlay_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 opengl32.lib ..\lib\fltkd.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/gl_overlay.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "gl_overlay - Win32 Release"
+# Name "gl_overlay - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\gl_overlay.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/glpuzzle.dsp b/visualc/glpuzzle.dsp
new file mode 100644
index 000000000..3b08be277
--- /dev/null
+++ b/visualc/glpuzzle.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="glpuzzle" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=glpuzzle - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "glpuzzle.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "glpuzzle.mak" CFG="glpuzzle - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "glpuzzle - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "glpuzzle - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "glpuzzle - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 opengl32.lib ..\lib\fltk.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/glpuzzle.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "glpuzzle - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "glpuzzle_"
+# PROP BASE Intermediate_Dir "glpuzzle_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "glpuzzle_"
+# PROP Intermediate_Dir "glpuzzle_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 opengl32.lib glu32.lib ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/glpuzzle.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "glpuzzle - Win32 Release"
+# Name "glpuzzle - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\glpuzzle.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/hello.dsp b/visualc/hello.dsp
new file mode 100644
index 000000000..69503f922
--- /dev/null
+++ b/visualc/hello.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="hello" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=hello - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "hello.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "hello.mak" CFG="hello - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "hello - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "hello - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "hello - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/hello.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "hello - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "hello_"
+# PROP BASE Intermediate_Dir "hello_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "hello_"
+# PROP Intermediate_Dir "hello_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/hello.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "hello - Win32 Release"
+# Name "hello - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\hello.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/iconize.dsp b/visualc/iconize.dsp
new file mode 100644
index 000000000..f9db4c909
--- /dev/null
+++ b/visualc/iconize.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="iconize" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=iconize - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "iconize.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "iconize.mak" CFG="iconize - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "iconize - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "iconize - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "iconize - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/iconize.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "iconize - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "iconize_"
+# PROP BASE Intermediate_Dir "iconize_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "iconize_"
+# PROP Intermediate_Dir "iconize_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/iconize.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "iconize - Win32 Release"
+# Name "iconize - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\iconize.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/image.dsp b/visualc/image.dsp
new file mode 100644
index 000000000..864354510
--- /dev/null
+++ b/visualc/image.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="image" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=image - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "image.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "image.mak" CFG="image - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "image - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "image - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "image - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/image.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "image - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "image_"
+# PROP BASE Intermediate_Dir "image_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "image_"
+# PROP Intermediate_Dir "image_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/image.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "image - Win32 Release"
+# Name "image - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\image.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/inactive.dsp b/visualc/inactive.dsp
new file mode 100755
index 000000000..3cb067bce
--- /dev/null
+++ b/visualc/inactive.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="inactive" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=inactive - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "inactive.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "inactive.mak" CFG="inactive - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "inactive - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "inactive - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "inactive - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/inactive.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "inactive - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "inactive_"
+# PROP BASE Intermediate_Dir "inactive_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "inactive_"
+# PROP Intermediate_Dir "inactive_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/inactive.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "inactive - Win32 Release"
+# Name "inactive - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\inactive.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/input.dsp b/visualc/input.dsp
new file mode 100644
index 000000000..ea895d102
--- /dev/null
+++ b/visualc/input.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="input" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=input - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "input.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "input.mak" CFG="input - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "input - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "input - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "input - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/input.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "input - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "input_"
+# PROP BASE Intermediate_Dir "input_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "input_"
+# PROP Intermediate_Dir "input_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/input.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "input - Win32 Release"
+# Name "input - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\input.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/keyboard.dsp b/visualc/keyboard.dsp
new file mode 100644
index 000000000..ef5a68b00
--- /dev/null
+++ b/visualc/keyboard.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="keyboard" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=keyboard - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "keyboard.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "keyboard.mak" CFG="keyboard - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "keyboard - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "keyboard - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "keyboard - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/keyboard.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "keyboard - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "keyboard_"
+# PROP BASE Intermediate_Dir "keyboard_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "keyboard_"
+# PROP Intermediate_Dir "keyboard_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/keyboard.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "keyboard - Win32 Release"
+# Name "keyboard - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\keyboard.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/label.dsp b/visualc/label.dsp
new file mode 100644
index 000000000..1a1e22e26
--- /dev/null
+++ b/visualc/label.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="label" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=label - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "label.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "label.mak" CFG="label - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "label - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "label - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "label - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/label.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "label - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "label_"
+# PROP BASE Intermediate_Dir "label_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "label_"
+# PROP Intermediate_Dir "label_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/label.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "label - Win32 Release"
+# Name "label - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\label.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/mandelbrot.dsp b/visualc/mandelbrot.dsp
new file mode 100644
index 000000000..e7e5ee19d
--- /dev/null
+++ b/visualc/mandelbrot.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="mandelbrot" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=mandelbrot - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "mandelbrot.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "mandelbrot.mak" CFG="mandelbrot - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "mandelbrot - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "mandelbrot - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "mandelbrot - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/mandelbrot.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "mandelbrot - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "mandelbrot_"
+# PROP BASE Intermediate_Dir "mandelbrot_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "mandelbrot_"
+# PROP Intermediate_Dir "mandelbrot_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/mandelbrot.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "mandelbrot - Win32 Release"
+# Name "mandelbrot - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\mandelbrot.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/menubar.dsp b/visualc/menubar.dsp
new file mode 100644
index 000000000..4c495e6c0
--- /dev/null
+++ b/visualc/menubar.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="menubar" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=menubar - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "menubar.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "menubar.mak" CFG="menubar - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "menubar - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "menubar - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "menubar - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/menubar.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "menubar - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "menubar_"
+# PROP BASE Intermediate_Dir "menubar_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "menubar_"
+# PROP Intermediate_Dir "menubar_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/menubar.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "menubar - Win32 Release"
+# Name "menubar - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\menubar.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/message.dsp b/visualc/message.dsp
new file mode 100644
index 000000000..145a13ebf
--- /dev/null
+++ b/visualc/message.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="message" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=message - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "message.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "message.mak" CFG="message - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "message - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "message - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "message - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/message.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "message - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "message_"
+# PROP BASE Intermediate_Dir "message_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "message_"
+# PROP Intermediate_Dir "message_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/message.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "message - Win32 Release"
+# Name "message - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\message.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/minimum.dsp b/visualc/minimum.dsp
new file mode 100644
index 000000000..efae55c22
--- /dev/null
+++ b/visualc/minimum.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="minimum" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=minimum - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "minimum.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "minimum.mak" CFG="minimum - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "minimum - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "minimum - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "minimum - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/minimum.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "minimum - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "minimum_"
+# PROP BASE Intermediate_Dir "minimum_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "minimum_"
+# PROP Intermediate_Dir "minimum_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/minimum.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "minimum - Win32 Release"
+# Name "minimum - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\minimum.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/navigation.dsp b/visualc/navigation.dsp
new file mode 100644
index 000000000..8e868bf83
--- /dev/null
+++ b/visualc/navigation.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="navigation" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=navigation - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "navigation.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "navigation.mak" CFG="navigation - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "navigation - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "navigation - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "navigation - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/navigation.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "navigation - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "navigation_"
+# PROP BASE Intermediate_Dir "navigation_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "navigation_"
+# PROP Intermediate_Dir "navigation_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/navigation.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "navigation - Win32 Release"
+# Name "navigation - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\navigation.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/output.dsp b/visualc/output.dsp
new file mode 100644
index 000000000..693eb0236
--- /dev/null
+++ b/visualc/output.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="output" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=output - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "output.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "output.mak" CFG="output - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "output - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "output - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "output - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/output.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "output - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "output_"
+# PROP BASE Intermediate_Dir "output_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "output_"
+# PROP Intermediate_Dir "output_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/output.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "output - Win32 Release"
+# Name "output - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\output.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/overlay.dsp b/visualc/overlay.dsp
new file mode 100644
index 000000000..b6662c64a
--- /dev/null
+++ b/visualc/overlay.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="overlay" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=overlay - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "overlay.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "overlay.mak" CFG="overlay - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "overlay - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "overlay - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "overlay - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/overlay.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "overlay - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "overlay_"
+# PROP BASE Intermediate_Dir "overlay_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "overlay_"
+# PROP Intermediate_Dir "overlay_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/overlay.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "overlay - Win32 Release"
+# Name "overlay - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\overlay.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/pack.dsp b/visualc/pack.dsp
new file mode 100755
index 000000000..d2d9dbb38
--- /dev/null
+++ b/visualc/pack.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="pack" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=pack - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "pack.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "pack.mak" CFG="pack - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "pack - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "pack - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "pack - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/pack.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "pack - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "pack_"
+# PROP BASE Intermediate_Dir "pack_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "pack_"
+# PROP Intermediate_Dir "pack_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/pack.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "pack - Win32 Release"
+# Name "pack - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\pack.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/pixmap.dsp b/visualc/pixmap.dsp
new file mode 100644
index 000000000..6c4d7e603
--- /dev/null
+++ b/visualc/pixmap.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="pixmap" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=pixmap - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "pixmap.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "pixmap.mak" CFG="pixmap - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "pixmap - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "pixmap - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "pixmap - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/pixmap.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "pixmap - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "pixmap_"
+# PROP BASE Intermediate_Dir "pixmap_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "pixmap_"
+# PROP Intermediate_Dir "pixmap_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/pixmap.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "pixmap - Win32 Release"
+# Name "pixmap - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\pixmap.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/pixmap_browser.dsp b/visualc/pixmap_browser.dsp
new file mode 100644
index 000000000..96e1224c7
--- /dev/null
+++ b/visualc/pixmap_browser.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="pixmap_browser" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=pixmap_browser - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "pixmap_browser.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "pixmap_browser.mak" CFG="pixmap_browser - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "pixmap_browser - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "pixmap_browser - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "pixmap_browser - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/pixmap_browser.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "pixmap_browser - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "pixmap_browser_"
+# PROP BASE Intermediate_Dir "pixmap_browser_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "pixmap_browser_"
+# PROP Intermediate_Dir "pixmap_browser_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/pixmap_browser.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "pixmap_browser - Win32 Release"
+# Name "pixmap_browser - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\pixmap_browser.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/radio.dsp b/visualc/radio.dsp
new file mode 100644
index 000000000..b5f86032a
--- /dev/null
+++ b/visualc/radio.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="radio" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=radio - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "radio.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "radio.mak" CFG="radio - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "radio - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "radio - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "radio - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/radio.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "radio - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "radio_"
+# PROP BASE Intermediate_Dir "radio_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "radio_"
+# PROP Intermediate_Dir "radio_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/radio.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "radio - Win32 Release"
+# Name "radio - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\radio.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/resize.dsp b/visualc/resize.dsp
new file mode 100644
index 000000000..4b4305a7b
--- /dev/null
+++ b/visualc/resize.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="resize" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=resize - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "resize.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "resize.mak" CFG="resize - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "resize - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "resize - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "resize - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/resize.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "resize - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "resize_"
+# PROP BASE Intermediate_Dir "resize_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "resize_"
+# PROP Intermediate_Dir "resize_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/resize.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "resize - Win32 Release"
+# Name "resize - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\resize.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/resizebox.dsp b/visualc/resizebox.dsp
new file mode 100644
index 000000000..b464684d3
--- /dev/null
+++ b/visualc/resizebox.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="resizebox" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=resizebox - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "resizebox.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "resizebox.mak" CFG="resizebox - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "resizebox - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "resizebox - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "resizebox - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/resizebox.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "resizebox - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "resizebox_"
+# PROP BASE Intermediate_Dir "resizebox_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "resizebox_"
+# PROP Intermediate_Dir "resizebox_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/resizebox.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "resizebox - Win32 Release"
+# Name "resizebox - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\resizebox.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/scroll.dsp b/visualc/scroll.dsp
new file mode 100644
index 000000000..7970793dd
--- /dev/null
+++ b/visualc/scroll.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="scroll" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=scroll - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "scroll.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "scroll.mak" CFG="scroll - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "scroll - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "scroll - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "scroll - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/scroll.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "scroll - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "scroll_"
+# PROP BASE Intermediate_Dir "scroll_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "scroll_"
+# PROP Intermediate_Dir "scroll_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/scroll.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "scroll - Win32 Release"
+# Name "scroll - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\scroll.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/shape.dsp b/visualc/shape.dsp
new file mode 100644
index 000000000..65cacca35
--- /dev/null
+++ b/visualc/shape.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="shape" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=shape - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "shape.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "shape.mak" CFG="shape - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "shape - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "shape - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "shape - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 opengl32.lib ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/shape.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "shape - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "shape_"
+# PROP BASE Intermediate_Dir "shape_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "shape_"
+# PROP Intermediate_Dir "shape_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 opengl32.lib ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/shape.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "shape - Win32 Release"
+# Name "shape - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\shape.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/shiny.dsp b/visualc/shiny.dsp
new file mode 100644
index 000000000..3da8adce5
--- /dev/null
+++ b/visualc/shiny.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="shiny" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=shiny - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "shiny.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "shiny.mak" CFG="shiny - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "shiny - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "shiny - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "shiny - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/shiny.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "shiny - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "shiny_"
+# PROP BASE Intermediate_Dir "shiny_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "shiny_"
+# PROP Intermediate_Dir "shiny_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 opengl32.lib ..\lib\fltkd.lib glu32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/shiny.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "shiny - Win32 Release"
+# Name "shiny - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\shiny.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/style.dsp b/visualc/style.dsp
new file mode 100755
index 000000000..bd3d1688d
--- /dev/null
+++ b/visualc/style.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="style" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=style - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "style.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "style.mak" CFG="style - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "style - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "style - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "style - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/style.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "style - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "style_"
+# PROP BASE Intermediate_Dir "style_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "style_"
+# PROP Intermediate_Dir "style_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/style.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "style - Win32 Release"
+# Name "style - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\style.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/subwindow.dsp b/visualc/subwindow.dsp
new file mode 100644
index 000000000..d97b30a64
--- /dev/null
+++ b/visualc/subwindow.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="subwindow" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=subwindow - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "subwindow.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "subwindow.mak" CFG="subwindow - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "subwindow - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "subwindow - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "subwindow - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/subwindow.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "subwindow - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "subwindow_"
+# PROP BASE Intermediate_Dir "subwindow_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "subwindow_"
+# PROP Intermediate_Dir "subwindow_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/subwindow.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "subwindow - Win32 Release"
+# Name "subwindow - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\subwindow.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/symbols.dsp b/visualc/symbols.dsp
new file mode 100644
index 000000000..c6f7f5c6c
--- /dev/null
+++ b/visualc/symbols.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="symbols" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=symbols - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "symbols.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "symbols.mak" CFG="symbols - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "symbols - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "symbols - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "symbols - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/symbols.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "symbols - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "symbols_"
+# PROP BASE Intermediate_Dir "symbols_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "symbols_"
+# PROP Intermediate_Dir "symbols_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/symbols.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "symbols - Win32 Release"
+# Name "symbols - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\symbols.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/tabs.dsp b/visualc/tabs.dsp
new file mode 100644
index 000000000..f88f68f32
--- /dev/null
+++ b/visualc/tabs.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="tabs" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=tabs - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "tabs.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "tabs.mak" CFG="tabs - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "tabs - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "tabs - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "tabs - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/tabs.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "tabs - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "tabs_"
+# PROP BASE Intermediate_Dir "tabs_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "tabs_"
+# PROP Intermediate_Dir "tabs_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/tabs.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "tabs - Win32 Release"
+# Name "tabs - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\tabs.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/tile.dsp b/visualc/tile.dsp
new file mode 100644
index 000000000..42c7c23fc
--- /dev/null
+++ b/visualc/tile.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="tile" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=tile - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "tile.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "tile.mak" CFG="tile - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "tile - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "tile - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "tile - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/tile.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "tile - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "tile_"
+# PROP BASE Intermediate_Dir "tile_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "tile_"
+# PROP Intermediate_Dir "tile_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/tile.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "tile - Win32 Release"
+# Name "tile - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\tile.C
+# End Source File
+# End Target
+# End Project
diff --git a/visualc/valuators.dsp b/visualc/valuators.dsp
new file mode 100644
index 000000000..8949d1eca
--- /dev/null
+++ b/visualc/valuators.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="valuators" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=valuators - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "valuators.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "valuators.mak" CFG="valuators - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "valuators - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "valuators - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "valuators - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ..\lib\fltk.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /incremental:yes /machine:I386 /nodefaultlib:"libcd" /out:"../test/valuators.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "valuators - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "valuators_"
+# PROP BASE Intermediate_Dir "valuators_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "valuators_"
+# PROP Intermediate_Dir "valuators_"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /TP /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\fltkd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"mainCRTStartup" /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd" /out:"../test/valuators.exe" /pdbtype:sept /libpath:"../win32/Debug"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "valuators - Win32 Release"
+# Name "valuators - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\test\valuators.C
+# End Source File
+# End Target
+# End Project