diff --git a/contrib/MathEval/CMakeLists.txt b/contrib/Fl_Tree/CMakeLists.txt
similarity index 57%
rename from contrib/MathEval/CMakeLists.txt
rename to contrib/Fl_Tree/CMakeLists.txt
index dab5df3e8f776d669e417dce2c6bed6cc0c828e5..253dc069ebd6a8cb1a480455e16f6aaae0677e06 100644
--- a/contrib/MathEval/CMakeLists.txt
+++ b/contrib/Fl_Tree/CMakeLists.txt
@@ -4,12 +4,10 @@
 # bugs and problems to <gmsh@geuz.org>.
 
 set(SRC
-  matheval.cpp
-  node.cpp
-  scanner.yy.cpp
-  parser.tab.cpp
-  symbol_table.cpp
-  xmath.cpp
+  Fl_Tree.cxx
+  Fl_Tree_Item.cxx
+  Fl_Tree_Item_Array.cxx
+  Fl_Tree_Prefs.cxx
 )
 
-append_gmsh_src(contrib/MathEval "${SRC}")
+append_gmsh_src(contrib/Fl_Tree "${SRC}")
diff --git a/contrib/TreeBrowser/LICENSE b/contrib/Fl_Tree/COPYING
similarity index 90%
rename from contrib/TreeBrowser/LICENSE
rename to contrib/Fl_Tree/COPYING
index 273fc091dbaeab7c3c7941971d865deeb784a48d..94ee154c676fe47a849c1f04e3732285b91707fb 100644
--- a/contrib/TreeBrowser/LICENSE
+++ b/contrib/Fl_Tree/COPYING
@@ -1,87 +1,46 @@
-/***************************************************************
- *                FLU - FLTK Utility Widgets 
- *  Copyright (C) 2002 Jason Bryan, Ohio Supercomputer Center, Ohio State University
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * To contribute, advise, suggest, berate, recommend, criticise,
- * or otherwise communicate with me:    jbryan@osc.edu
- *                                      Ohio Supercomputer Center
- *                                      1224 Kinnear Rd
- *                                      Columbus, Ohio 43212
- ***************************************************************/
+                           Fl_Tree License
+                           May 29, 2005
 
-
------------------------------------------------------------------------
-
- This library depends on the following GPL free libraries:
-    FLTK
-
- This library also uses OpenGL, which is a registered trademark of Silicon
-  Graphics, Inc. (SGI), and Doxygen, a free HTML page generator for documentation
-  of C++ classes.
-
-
- This library is hereby distributed under the same LGPL license as FLTK.
- Have fun with it!
-
------------------------------------------------------------------------
-
-                             FLTK License
-                           December 11, 2001
-
-The FLTK library and included programs are provided under the terms
+The Fl_Tree library and included programs are provided under the terms
 of the GNU Library General Public License (LGPL) with the following
 exceptions:
 
-    1. Modifications to the FLTK configure script, config
+    1. Modifications to the Fl_Tree configure script, config
        header file, and makefiles by themselves to support
        a specific platform do not constitute a modified or
        derivative work.
 
        The authors do request that such modifications be
-       contributed to the FLTK project - send all
-       contributions to "fltk-bugs@fltk.org".
+       contributed to the Fl_Tree project - send all
+       contributions to "erco at seriss dot com".
 
-    2. Widgets that are subclassed from FLTK widgets do not
+    2. Widgets that are subclassed from Fl_Tree widgets do not
        constitute a derivative work.
 
     3. Static linking of applications and widgets to the
-       FLTK library does not constitute a derivative work
+       Fl_Tree library does not constitute a derivative work
        and does not require the author to provide source
        code for the application or widget, use the shared
-       FLTK libraries, or link their applications or
-       widgets against a user-supplied version of FLTK.
+       Fl_Tree libraries, or link their applications or
+       widgets against a user-supplied version of Fl_Tree.
 
        If you link the application or widget to a modified
-       version of FLTK, then the changes to FLTK must be
+       version of Fl_Tree, then the changes to Fl_Tree must be
        provided under the terms of the LGPL in sections
        1, 2, and 4.
 
-    4. You do not have to provide a copy of the FLTK license
-       with programs that are linked to the FLTK library, nor
-       do you have to identify the FLTK license in your
+    4. You do not have to provide a copy of the Fl_Tree license
+       with programs that are linked to the Fl_Tree library, nor
+       do you have to identify the Fl_Tree license in your
        program or documentation as required by section 6
        of the LGPL.
 
-       However, programs must still identify their use of FLTK.
+       However, programs must still identify their use of Fl_Tree.
        The following example statement can be included in user
        documentation to satisfy this requirement:
 
            [program/widget] is based in part on the work of
-           the FLTK project (http://www.fltk.org).
+           the Fl_Tree project http://seriss.com/people/erco/fltk/Fl_Tree/
 
 -----------------------------------------------------------------------
 
@@ -139,7 +98,7 @@ 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
@@ -186,7 +145,7 @@ 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
 
@@ -233,7 +192,7 @@ 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
@@ -291,7 +250,7 @@ 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.
@@ -342,7 +301,7 @@ Library will still fall under Section 6.)
 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
@@ -396,7 +355,7 @@ 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
@@ -437,7 +396,7 @@ 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
@@ -489,7 +448,7 @@ 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
@@ -523,7 +482,7 @@ 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
diff --git a/contrib/Fl_Tree/FL/Fl_Tree.H b/contrib/Fl_Tree/FL/Fl_Tree.H
new file mode 100644
index 0000000000000000000000000000000000000000..1e3ad8a8eedf4d7a194eefb37074de39c887a3d5
--- /dev/null
+++ b/contrib/Fl_Tree/FL/Fl_Tree.H
@@ -0,0 +1,634 @@
+#ifndef FL_TREE_H
+#define FL_TREE_H
+
+#include <FL/Fl.H>
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Scrollbar.H>
+#include <FL/fl_draw.H>
+
+#include <FL/Fl_Tree_Item.H>
+#include <FL/Fl_Tree_Prefs.H>
+
+//////////////////////
+// FL/Fl_Tree.H
+//////////////////////
+//
+// Fl_Tree -- This file is part of the Fl_Tree widget for FLTK
+// Copyright (C) 2009 by Greg Ercolano.
+//
+// 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.
+//
+
+///
+/// \file
+/// \brief This file contains the definitions of the Fl_Tree class
+///
+
+/// \class Fl_Tree
+///
+/// \brief Tree widget.
+///
+/// \code
+///     Fl_Tree                                         // Top level widget
+///        |--- Fl_Tree_Item                            // Items in the tree
+///        |--- Fl_Tree_Prefs                           // Preferences for the tree
+///                  |--- Fl_Tree_Connector (enum)      // Connection modes
+///                  |--- Fl_Tree_Select (enum)         // Selection modes
+///                  |--- Fl_Tree_Sort (enum)           // Sort behavior
+/// \endcode
+///
+///     An expandable tree widget.
+///
+///     Similar to Fl_Browser, Fl_Tree is browser of Fl_Tree_Item's, which can be
+///     in a parented hierarchy. Subtrees can be expanded or closed. Items can be
+///     added, deleted, inserted, sorted and re-ordered.
+///
+///     The tree items may also contain other FLTK widgets, like buttons, input fields,
+///     or even "custom" widgets.
+///
+///     The simple way to define a tree:
+/// \code
+///    Fl_Tree tree(X,Y,W,H);
+///    tree.begin();
+///      tree.add("Flintstones/Fred");
+///      tree.add("Flintstones/Wilma");
+///      tree.add("Flintstones/Pebbles");
+///      tree.add("Simpsons/Homer");
+///      tree.add("Simpsons/Marge");
+///      tree.add("Simpsons/Bart");
+///      tree.add("Simpsons/Lisa");
+///    tree.end();
+/// \endcode
+///     
+///     Items can be added with Fl_Tree::add(),
+///     removed with Fl_Tree::remove(),
+///     inserted with Fl_Tree::insert_above(),
+///     selected/deselected with Fl_Tree::select() and Fl_Tree::deselect().
+///     Items can be swapped with Fl_Tree_Item::swap_children(), sorting control via
+///     Fl_Tree::sortorder().
+///
+///     The tree can have different selection behaviors controlled by Fl_Tree::selectmode().
+///
+///     FLTK and custom FLTK widgets can be assigned to tree items via Fl_Tree_Item::widget().
+///
+///     Parent nodes can be open/closed with open() and close(), icons can be assigned
+///     or redefined with some or all items via 
+///     Fl_Tree_Item::openicon(), 
+///     Fl_Tree_Item::closeicon(),
+///     Fl_Tree_Item::usericon().
+///
+///     Various default preferences can be manipulated vi Fl_Tree_Prefs, including
+///     colors, margins, connection lines. 
+///
+///     \image html tree-elements.png
+///
+
+class Fl_Tree : public Fl_Group {
+    Fl_Tree_Item  *_root;		// can be null!
+    Fl_Tree_Item  *_item_clicked;
+    Fl_Tree_Prefs  _prefs;		// all the tree's settings
+    Fl_Scrollbar  *_vscroll;
+
+protected:
+    /// Find the item that was clicked.
+    /// You probably want to use item_clicked() instead, which is fast.
+    ///
+    /// This method walks the entire tree looking for the first item that is
+    /// under the mouse (ie. at Fl::event_x()/Fl:event_y().
+    ///
+    /// Use this method /only/ if you've subclassed Fl_Tree, and are receiving
+    /// events before Fl_Tree has been able to process and update item_clicked().
+    /// 
+    /// \returns the item clicked, or 0 if no item was under the current event.
+    ///
+    const Fl_Tree_Item *find_clicked() const {
+        if ( ! _root ) return(0);
+        return(_root->find_clicked());
+    }
+    /// Set the item that was last clicked.
+    /// Should only be used by subclasses needing to change this value.
+    /// Normally Fl_Tree manages this value.
+    ///
+    void item_clicked(Fl_Tree_Item* val) {
+        _item_clicked = val;
+    }
+
+public:
+    Fl_Tree(int X, int Y, int W, int H, const char *L=0);
+    ~Fl_Tree();
+    int handle(int e);
+    void draw();
+
+    ///////////////////////
+    // root methods
+    ///////////////////////
+
+    /// Set the label for the root item. 
+    ///
+    /// Makes an internally managed copy of 'new_label'.
+    ///
+    void root_label(const char *new_label) {
+        if ( ! _root ) return;
+        _root->label(new_label);
+    }
+    /// Returns the root item.
+    Fl_Tree_Item* root() {
+        return(_root);
+    }
+
+    ////////////////////////////////
+    // Item creation/removal methods
+    ////////////////////////////////
+    Fl_Tree_Item *add(const char *path);
+    Fl_Tree_Item *insert_above(Fl_Tree_Item *above, const char *name);
+
+    /// Remove the specified 'item' from the tree.
+    /// If it has children, all those are removed too.
+    /// \returns 0 if done, -1 if 'item' not found.
+    ///
+    int remove(Fl_Tree_Item *item) {
+        if ( !item ) return(0);
+        if ( item == _root ) {
+	    clear();
+	} else {
+	    Fl_Tree_Item *parent = item->parent();	// find item's parent
+	    if ( ! parent ) return(-1);
+	    parent->remove_child(item);			// remove child + children
+	}
+	return(0);
+    } 
+    /// Clear all children from the tree.
+    /// The tree will be left completely empty.
+    ///
+    void clear() {
+        if ( ! _root ) return;
+	_root->clear_children();
+	delete _root; _root = 0;
+    } 
+    /// Clear all the children of a particular node in the tree.
+    void clear_children(Fl_Tree_Item *item) {
+        if ( item->has_children() ) {
+	    item->clear_children();
+	    redraw();			// redraw only if there were children to clear
+	}
+    } 
+
+    ////////////////////////
+    // Item lookup methods
+    ////////////////////////
+    Fl_Tree_Item *find_item(const char *path);
+    const Fl_Tree_Item *find_item(const char *path) const;
+
+    /// Return the parent for specified 'item'.
+    ///
+    /// \returns item's parent, or 0 if none (root).
+    ///
+    Fl_Tree_Item *parent(Fl_Tree_Item *item) {
+        return(item->parent());
+    }
+    /// Return the item that was last clicked.
+    ///
+    /// Valid only from within an Fl_Tree::callback().
+    ///
+    /// \returns the item clicked, or 0 if none.
+    ///
+    Fl_Tree_Item *item_clicked() {
+        return(_item_clicked);
+    }
+    /// Returns the first item in the tree.
+    ///
+    /// Use this to walk the tree in the forward direction, eg:
+    /// \code
+    /// for ( Fl_Tree_Item *item = tree->first(); item; item = item->next() ) {
+    ///     printf("Item: %s\n", item->label());
+    /// }
+    /// \endcode
+    ///
+    /// \returns first item in tree, or 0 if none (tree empty).
+    ///
+    Fl_Tree_Item *first() {
+        return(_root);					// first item always root
+    }
+    /// Returns the last item in the tree.
+    ///
+    /// Use this to walk the tree in reverse, eg:
+    ///
+    /// \code
+    /// for ( Fl_Tree_Item *item = tree->last(); item; item = item->prev() ) {
+    ///     printf("Item: %s\n", item->label());
+    /// }
+    /// \endcode
+    ///
+    /// \returns last item in the tree, or 0 if none (tree empty).
+    ///
+    Fl_Tree_Item *last() {
+        if ( ! _root ) return(0);
+        Fl_Tree_Item *item = _root;
+        while ( item->has_children() ) {
+	    item = item->child(item->children()-1);
+	}
+	return(item);
+    }
+
+    //////////////////////////
+    // Item open/close methods
+    //////////////////////////
+
+    /// Open the specified 'item'.
+    /// This causes the item's children (if any) to be shown.
+    /// Handles redrawing if anything was actually changed.
+    ///
+    void open(Fl_Tree_Item *item) {
+        if ( ! item->is_open() ) {
+	    item->open();
+	    redraw();
+	}
+    }
+    /// Opens the item specified by a 'menu item' style pathname (eg: "Parent/child/item").
+    /// This causes the item's children (if any) to be shown.
+    /// Handles redrawing if anything was actually changed.
+    ///
+    /// \returns
+    ///     -   0 : OK
+    ///     -  -1 : item was not found
+    ///         
+    int open(const char *path) {
+        Fl_Tree_Item *item = find_item(path);
+        if ( item ) {
+	    open(item);
+	    return(0);
+	}
+	return(-1);
+    }
+    /// Closes the 'item'.
+    /// Handles redrawing if anything was actually changed.
+    ///
+    void close(Fl_Tree_Item *item) {
+        if ( ! item->is_close() ) {
+	    item->close();
+	    redraw();
+	}
+    }
+    /// Closes the item specified by 'path', eg: "Parent/child/item".
+    ///
+    /// Handles redrawing if anything was actually changed.
+    ///
+    /// \returns
+    ///     -   0 -- OK
+    ///     -  -1 -- item was not found
+    ///         
+    int close(const char *path) {
+        Fl_Tree_Item *item = find_item(path);
+        if ( item ) {
+	    close(item);
+	    return(0);
+	}
+	return(-1);
+    }
+    /// See if item is open.
+    ///
+    /// Items that are 'open' are themselves not necessarily visible;
+    /// one of the item's parents might be closed.
+    ///
+    /// \returns
+    ///     -  1 : item is open
+    ///     -  0 : item is closed
+    ///
+    int is_open(Fl_Tree_Item *item) const {
+        return(item->is_open()?1:0);
+    }
+    /// See if item specified by 'path' (eg: "Parent/child/item") is open.
+    ///
+    /// Items that are 'open' are themselves not necessarily visible;
+    /// one of the item's parents might be closed.
+    ///
+    /// \returns
+    ///     -    1 : item is open
+    ///     -    0 : item is closed
+    ///     -   -1 : item was not found
+    ///
+    int is_open(const char *path) const {
+        const Fl_Tree_Item *item = find_item(path);
+        if ( item ) return(item->is_open()?1:0);
+	return(-1);
+    }
+    /// See if item is closed.
+    /// \returns
+    ///     -   1 : item is open
+    ///     -   0 : item is closed
+    ///
+    int is_close(Fl_Tree_Item *item) const {
+        return(item->is_close());
+    }
+    /// See if item specified by 'path' (eg: "Parent/child/item") is closed.
+    ///
+    /// \returns
+    ///     -   1 : item is closed
+    ///     -   0 : item is open
+    ///     -  -1 : item was not found
+    ///
+    int is_close(const char *path) const {
+        const Fl_Tree_Item *item = find_item(path);
+        if ( item ) return(item->is_close()?1:0);
+	return(-1);
+    }
+
+    /////////////////////////
+    // Item selection methods
+    /////////////////////////
+
+    /// Select the specified item. Use 'deselect()' to de-select it.
+    /// Handles redrawing if anything was actually changed.
+    ///
+    void select(Fl_Tree_Item *item) {
+        if ( ! item->is_selected() ) {
+	    item->select();
+	    redraw();
+	}
+    }
+    /// Select an item specified by 'path' (eg: "Parent/child/item").
+    /// Handles redrawing if anything was actually changed.
+    ///
+    /// \returns
+    ///     -   0 : OK
+    ///     -  -1 : item was not found
+    ///
+    int select(const char *path) {
+        Fl_Tree_Item *item = find_item(path);
+        if ( item ) {
+	    select(item);
+	    return(0);
+	}
+	return(-1);
+    }
+    /// Toggle item's select state.
+    /// Handles redrawing.
+    ///
+    void select_toggle(Fl_Tree_Item *item) {
+        item->select_toggle();
+	redraw();
+    }
+    /// De-select the specified item.
+    /// Handles redrawing if anything was actually changed.
+    ///
+    void deselect(Fl_Tree_Item *item) {
+        if ( item->is_selected() ) {
+	    item->deselect();
+	    redraw();
+	}
+    }
+    /// De-select an item specified by 'path' (eg: "Parent/child/item").
+    /// Handles redrawing if anything was actually changed.
+    ///
+    ///  \returns
+    ///     -   0 : OK
+    ///     -  -1 : item was not found
+    ///
+    int deselect(const char *path) {
+        Fl_Tree_Item *item = find_item(path);
+        if ( item ) {
+	    deselect(item);
+	    return(0);
+	}
+	return(-1);
+    }
+
+    int deselect_all(Fl_Tree_Item *item=0);
+    int select_only(Fl_Tree_Item *selitem);
+
+    /// See if the specified item is selected.
+    /// \return
+    ///     -   1 : item selected
+    ///     -   0 : item deselected
+    ///
+    int is_selected(Fl_Tree_Item *item) const {
+        return(item->is_selected()?1:0);
+    }
+    /// See if item specified by 'path' (eg: "Parent/child/item") is selected.
+    ///
+    /// \returns
+    ///     -   1 : item selected
+    ///     -   0 : item deselected
+    ///     -  -1 : item was not found
+    ///
+    int is_selected(const char *path) {
+        Fl_Tree_Item *item = find_item(path);
+        if ( item ) return(is_selected(item));
+	return(-1);
+    }
+    /// Print the tree as 'ascii art' to stdout.
+    /// Used mainly for debugging.
+    ///
+    void show_self() {
+        if ( ! _root ) return;
+        _root->show_self();
+    }
+
+    /////////////////////////////////
+    // Item attribute related methods
+    /////////////////////////////////
+
+    /// Get the default label fontsize used for creating new items.
+    int labelsize() const {
+        return(_prefs.labelsize());
+    }
+    /// Set the default label font size used for creating new items.
+    /// To change the font size on a per-item basis, use Fl_Tree_Item::labelsize(int)
+    ///
+    void labelsize(int val) {
+        _prefs.labelsize(val);
+    }
+
+    /// Get the default font face used for item's labels when new items are created.
+    ///
+    /// Don't use this if you want to change an existing label() size; use
+    /// item->labelfont() instead.
+    ///
+    int labelfont() const {
+        return(_prefs.labelfont());
+    }
+    /// Set the default font face used for item's labels when new items are created.
+    ///
+    /// Don't use this if you want to change an existing label() size; use
+    /// item->labelfont(int) instead.
+    ///
+    void labelfont(int val) {
+        _prefs.labelfont(val);
+    }
+    /// Get the amount of white space (in pixels) that should appear
+    /// between the widget's left border and the tree's contents.
+    ///
+    int  marginleft() const {
+        return(_prefs.marginleft());
+    }
+    /// Set the amount of white space (in pixels) that should appear
+    /// between the widget's left border and the left side of the tree's contents.
+    ///
+    void marginleft(int val) {
+        _prefs.marginleft(val);
+	redraw();
+    }
+    /// Get the amount of white space (in pixels) that should appear
+    /// between the widget's top border and the top of the tree's contents.
+    ///
+    int  margintop() const {
+        return(_prefs.margintop());
+    }
+    /// Sets the amount of white space (in pixels) that should appear
+    /// between the widget's top border and the top of the tree's contents.
+    ///
+    void margintop(int val) {
+        _prefs.margintop(val);
+	redraw();
+    }
+    /// Gets the width of the horizontal connection lines (in pixels) 
+    /// that appear to the left of each tree item's label.
+    ///
+    int  connectorwidth() const {
+        return(_prefs.connectorwidth());
+    }
+    /// Sets the width of the horizontal connection lines (in pixels) 
+    /// that appear to the left of each tree item's label.
+    ///
+    void connectorwidth(int val) {
+        _prefs.connectorwidth(val);
+	redraw();
+    }
+    /// Returns the Fl_Pixmap being used as the default user icon for newly created items.
+    /// Returns zero if no icon has been set, which is the default.
+    ///
+    Fl_Pixmap *usericon() const {
+        return(_prefs.usericon());
+    }
+    /// Sets the Fl_Pixmap to be used as the default user icon for all
+    /// newly created items.
+    ///
+    /// If you want to specify user icons on a per-item basis,
+    /// use Fl_Tree_Item::usericon() instead.
+    ///
+    /// \param[in] val -- The new pixmap to be used, or
+    ///                   zero to disable user icons.
+    ///
+    void usericon(Fl_Pixmap *val) {
+        _prefs.usericon(val);
+	redraw();
+    }
+    /// Returns the icon to be used as the 'open' icon.
+    /// If none was set, the internal default is returned,
+    /// a simple '[+]' icon.
+    ///
+    Fl_Pixmap *openicon() const {
+        return(_prefs.openicon());
+    }
+    /// Sets the icon to be used as the 'open' icon.
+    /// This overrides the built in default '[+]' icon.
+    ///
+    /// \param[in] val -- The new pixmap, or zero to use the default [+] icon.
+    ///
+    void openicon(Fl_Pixmap *val) {
+        _prefs.openicon(val);
+	redraw();
+    }
+    /// Returns the icon to be used as the 'close' icon.
+    /// If none was set, the internal default is returned,
+    /// a simple '[-]' icon.
+    ///
+    Fl_Pixmap *closeicon() const {
+        return(_prefs.closeicon());
+    }
+    /// Sets the icon to be used as the 'close' icon.
+    /// This overrides the built in default '[-]' icon.
+    ///
+    /// \param[in] val -- The new pixmap, or zero to use the default [-] icon.
+    ///
+    void closeicon(Fl_Pixmap *val) {
+        _prefs.closeicon(val);
+	redraw();
+    }
+    /// Returns 1 if the collapse icon is enabled, 0 if not.
+    int showcollapse() const {
+        return(_prefs.showcollapse());
+    }
+    /// Set if we should show the collapse icon or not.
+    /// If collapse icons are disabled, the user will not be able
+    /// to interactively collapse items in the tree, unless the application
+    /// provides some other means via open() and close().
+    ///
+    /// \param[in] val 1: shows collapse icons (default),\n
+    ///                0: hides collapse icons.
+    ///
+    void showcollapse(int val) {
+        _prefs.showcollapse(val);
+	redraw();
+    }
+    /// Returns 1 if the root item is to be shown, or 0 if not.
+    int showroot() const {
+        return(_prefs.showroot());
+    }
+    /// Set if the root item should be shown or not.
+    /// \param[in] val 1 -- show the root item (default)\n
+    ///                0 -- hide the root item.
+    ///
+    void showroot(int val) {
+        _prefs.showroot(val);
+	redraw();
+    }
+    /// Returns the line drawing style for inter-connecting items.
+    Fl_Tree_Connector connectorstyle() const {
+        return(_prefs.connectorstyle());
+    }
+    /// Sets the line drawing style for inter-connecting items.
+    void connectorstyle(Fl_Tree_Connector val) {
+        _prefs.connectorstyle(val);
+	redraw();
+    }
+    /// Set the default sort order used when items are added to the tree.
+    ///     See Fl_Tree_Sort for possible values.
+    ///
+    Fl_Tree_Sort sortorder() const {
+        return(_prefs.sortorder());
+    }
+    /// Gets the sort order used to add items to the tree.
+    void sortorder(Fl_Tree_Sort val) {
+        _prefs.sortorder(val);
+	// no redraw().. only affects new add()itions
+    }
+    /// Sets the style of box used to draw selected items.
+    /// This is an fltk Fl_Boxtype.
+    /// The default is influenced by FLTK's current Fl::scheme()
+    ///
+    Fl_Boxtype selectbox() const {
+        return(_prefs.selectbox());
+    }
+    /// Gets the style of box used to draw selected items.
+    /// This is an fltk Fl_Boxtype.
+    /// The default is influenced by FLTK's current Fl::scheme()
+    ///
+    void selectbox(Fl_Boxtype val) {
+        _prefs.selectbox(val);
+	redraw();
+    }
+    /// Gets the tree's current selection mode.
+    Fl_Tree_Select selectmode() const {
+        return(_prefs.selectmode());
+    }
+    /// Sets the tree's selection mode.
+    void selectmode(Fl_Tree_Select val) {
+        _prefs.selectmode(val);
+    }
+};
+
+#endif /*FL_TREE_H*/
diff --git a/contrib/Fl_Tree/FL/Fl_Tree_Item.H b/contrib/Fl_Tree/FL/Fl_Tree_Item.H
new file mode 100644
index 0000000000000000000000000000000000000000..1274c62601894190516005672ef5a35f83db4d29
--- /dev/null
+++ b/contrib/Fl_Tree/FL/Fl_Tree_Item.H
@@ -0,0 +1,301 @@
+#ifndef FL_TREE_ITEM_H
+#define FL_TREE_ITEM_H
+
+#include <FL/Fl.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Pixmap.H>
+#include <FL/fl_draw.H>
+
+#include <FL/Fl_Tree_Item_Array.H>
+#include <FL/Fl_Tree_Prefs.H>
+
+//////////////////////
+// FL/Fl_Tree_Item.H
+//////////////////////
+//
+// Fl_Tree -- This file is part of the Fl_Tree widget for FLTK
+// Copyright (C) 2009 by Greg Ercolano.
+//
+// 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.
+//
+
+///
+/// \file
+/// \brief This file contains the definitions for Fl_Tree_Item
+///
+
+/// \brief Tree item
+///
+/// This class is a single tree item, and manages all of the item's attributes.
+/// Fl_Tree_Item is used by Fl_Tree, which is comprised of many instances of Fl_Tree_Item.
+///
+/// Fl_Tree_Item is hierarchical; it dynamically manages an Fl_Tree_Item_Array of children
+/// that are themselves instances of Fl_Tree_Item. Each item can have zero or more children.
+/// When an item has children, close() and open() can be used to hide or show them.
+///
+/// Items have their own attributes; font size, face, color.
+/// Items maintain their own hierarchy of children.
+///
+/// When you make changes to items, you'll need to tell the tree to redraw()
+/// for the changes to show up.
+///
+///
+class Fl_Tree_Item {
+    const char    *_label;			// label (memory managed)
+    int            _labelfont;			// label's font face
+    int            _labelsize;			// label's font size
+    Fl_Color       _labelfgcolor;		// label's fg color
+    Fl_Color       _labelbgcolor;		// label's bg color
+    char           _open;			// item is open?
+    char           _visible;			// item is visible?
+    char           _active;			// item activated?
+    char           _selected;			// item selected?
+    int            _xywh[4];			// xywh of this widget (if visible)
+    int            _collapse_xywh[4];		// xywh of collapse icon (if any)
+    int            _label_xywh[4];		// xywh of label
+    Fl_Widget     *_widget;			// item's label widget (optional)
+    Fl_Pixmap     *_usericon;			// item's user-specific icon (optional)
+    void          *_userdata;			// item's user-specific data (optional) GMSH
+    Fl_Tree_Item_Array _children;		// array of child items
+    Fl_Tree_Item  *_parent;			// parent item (=0 if root)
+protected:
+    void show_widgets();
+    void hide_widgets();
+    void draw_vertical_connector(int x, int y1, int y2, const Fl_Tree_Prefs &prefs);
+    void draw_horizontal_connector(int x1, int x2, int y, const Fl_Tree_Prefs &prefs);
+public:
+    Fl_Tree_Item(const Fl_Tree_Prefs &prefs);	// CTOR
+    ~Fl_Tree_Item();				// DTOR
+    Fl_Tree_Item(const Fl_Tree_Item *o);	// COPY CTOR
+    void draw(int X, int &Y, int W, Fl_Widget *tree, const Fl_Tree_Prefs &prefs, int lastchild=1);
+    void show_self(const char *indent = "") const;
+    void label(const char *val);
+    const char *label() const;
+
+    /// Set item's label font face.
+    void labelfont(int val) {
+        _labelfont = val; 
+    }
+    /// Get item's label font face.
+    int labelfont() const {
+        return(_labelfont);
+    }
+    /// Set item's label font size.
+    void labelsize(int val) {
+        _labelsize = val; 
+    }
+    /// Get item's label font size.
+    int labelsize() const {
+        return(_labelsize);
+    }
+    /// Set item's label foreground text color.
+    void labelfgcolor(Fl_Color val) {
+        _labelfgcolor = val; 
+    }
+    /// Set item's label text color.
+    void labelcolor(Fl_Color val) {
+        _labelfgcolor = val; 
+    }
+    /// Return item's label text color.
+    Fl_Color labelcolor() const {
+        return(_labelfgcolor); 
+    }
+    /// Return item's label foreground text color.
+    Fl_Color labelfgcolor() const {
+        return(_labelfgcolor); 
+    }
+    /// Set item's label background color.
+    void labelbgcolor(Fl_Color val) {
+        _labelbgcolor = val; 
+    }
+    /// Return item's background text color.
+    Fl_Color labelbgcolor() const {
+        return(_labelbgcolor); 
+    }
+    /// Assign an FLTK widget to this item.
+    void widget(Fl_Widget *val) {
+        _widget = val; 
+    }
+    /// Return FLTK widget assigned to this item.
+    Fl_Widget *widget() const {
+        return(_widget); 
+    }
+    /// Return the number of children this item has.
+    int children() const {
+        return(_children.total()); 
+    }
+    /// Return the child item for the given 'index'.
+    Fl_Tree_Item *child(int index) {
+        return(_children[index]); 
+    }
+    /// Return the const child item for the given 'index'.
+    const Fl_Tree_Item *child(int t) const;
+    /// See if this item has children.
+    int has_children() const {
+        return(children()); 
+    }
+    int find_child(const char *name);
+    int find_child(Fl_Tree_Item *item);
+    int remove_child(Fl_Tree_Item *item);
+    int remove_child(const char *new_label);
+    void clear_children();
+    void swap_children(int ax, int bx);
+    int swap_children(Fl_Tree_Item *a, Fl_Tree_Item *b);
+    const Fl_Tree_Item *find_item(char **arr) const;
+    Fl_Tree_Item *find_item(char **arr);
+    //////////////////
+    // Adding items
+    //////////////////
+    Fl_Tree_Item *add(const Fl_Tree_Prefs &prefs, const char *new_label);
+    Fl_Tree_Item *add(const Fl_Tree_Prefs &prefs, char **arr);
+    Fl_Tree_Item *insert(const Fl_Tree_Prefs &prefs, const char *new_label, int pos=0);
+    Fl_Tree_Item *insert_above(const Fl_Tree_Prefs &prefs, const char *new_label);
+    int depth() const;
+    Fl_Tree_Item *prev();
+    Fl_Tree_Item *next();
+
+    /// Return the parent for this item.
+    Fl_Tree_Item *parent() {
+        return(_parent);
+    }
+    /// Return the const parent for this item.
+    const Fl_Tree_Item *parent() const {
+        return(_parent);
+    }
+    /// Set the parent for this item.
+    /// Should only be used by Fl_Tree's internals.
+    ///
+    void parent(Fl_Tree_Item *val) {
+        _parent = val;
+    }
+    //////////////////
+    // State
+    //////////////////
+    void open();
+    void close();
+    /// See if the item is 'open'.
+    int is_open() const {
+        return(_open?1:0);
+    }
+    /// See if the item is 'closed'.
+    int is_close() const {
+        return(_open?0:1);
+    }
+    /// Toggle the item's open/closed state.
+    void open_toggle() {
+        _open?close():open();
+    }
+    /// Change the item's selection state to the optionally specified 'val'.
+    /// If 'val' is not specified, the item will be selected.
+    ///
+    void select(int val=1) {
+        _selected = val;
+    }
+    /// Toggle the item's selection state.
+    void select_toggle() {
+        if ( is_selected() ) {
+	    deselect();		// deselect if selected
+	} else {
+	    select();		// select if deselected
+	}
+    }
+    /// Disable the item's selection state.
+    void deselect() {
+        _selected = 0;
+    }
+    /// Deselect self and all children
+    ///     Returns count of how many items were in the 'selected' state,
+    ///     ie. how many items were "changed".
+    ///
+    int deselect_all() {
+        int count = 0;
+        if ( is_selected() ) {
+	    deselect();
+	    ++count;
+	}
+	for ( int t=0; t<children(); t++ ) {
+	    count += child(t)->deselect_all();
+	}
+	return(count);
+    }
+    /// See if the item is selected.
+    char is_selected() const {
+        return(_selected);
+    }
+    /// Change the item's activation state to the optionally specified 'val'.
+    ///
+    /// When deactivated, the item will be 'grayed out'; the callback() 
+    /// won't be invoked if the user clicks on the label. If the item
+    /// has a widget() associated with the item, its activation state
+    /// will be changed as well.
+    ///
+    /// If 'val' is not specified, the item will be activated.
+    ///
+    void activate(int val=1) {
+        _active = val;
+	if ( _widget && val != _widget->active() ) {
+	    if ( val ) {
+	        _widget->activate();
+	    } else {
+	        _widget->deactivate();
+	    }
+	    _widget->redraw();
+	}
+    }
+    /// Deactivate the item; the callback() won't be invoked when clicked.
+    /// Same as activate(0)
+    ///
+    void deactivate() {
+        activate(0);
+    }
+    /// See if the item is activated.
+    char is_activated() const {
+        return(_active);
+    }
+    /// See if the item is activated.
+    char is_active() const {
+        return(_active);
+    }
+    /// Set the user icon's pixmap. '0' will disable.
+    void usericon(Fl_Pixmap *val) {
+        _usericon = val;
+    }
+    /// Get the user icon. Returns '0' if disabled.
+    Fl_Pixmap *usericon() const {
+        return(_usericon);
+    }
+    /// Set the user data.
+    void userdata(void *val) {
+        _userdata = val;
+    }
+    /// Get the user data.
+    void *userdata() const {
+        return(_userdata);
+    }
+    //////////////////
+    // Events
+    //////////////////
+    const Fl_Tree_Item *find_clicked() const;
+    Fl_Tree_Item *find_clicked();
+    int event_on_collapse_icon(const Fl_Tree_Prefs &prefs) const;
+    int event_on_label(const Fl_Tree_Prefs &prefs) const;
+    /// Is this item the root of the tree?
+    int is_root() const {
+        return(_parent==0?1:0);
+    }
+};
+
+#endif /*FL_TREE_ITEM_H*/
diff --git a/contrib/Fl_Tree/FL/Fl_Tree_Item_Array.H b/contrib/Fl_Tree/FL/Fl_Tree_Item_Array.H
new file mode 100644
index 0000000000000000000000000000000000000000..2bb233e3534f0accab5c1efd782e0bddd69abd54
--- /dev/null
+++ b/contrib/Fl_Tree/FL/Fl_Tree_Item_Array.H
@@ -0,0 +1,80 @@
+#ifndef _FL_TREE_ITEM_ARRAY_H
+#define _FL_TREE_ITEM_ARRAY_H
+
+class Fl_Tree_Item;		// forward decl must *precede* first doxygen comment block
+				// or doxygen will not document our class..
+
+//////////////////////
+// FL/Fl_Tree_Item_Array.H
+//////////////////////
+//
+// Fl_Tree -- This file is part of the Fl_Tree widget for FLTK
+// Copyright (C) 2009 by Greg Ercolano.
+//
+// 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.
+//
+
+///
+/// \file
+/// \brief This file defines a class that manages an array of Fl_Tree_Item pointers.
+///
+
+/// \brief Manages an array of Fl_Tree_Item pointers.
+///
+/// Because FLTK 1.x.x. has mandated that templates and STL not be used,
+/// we use this class to dynamically manage the arrays.
+///
+/// None of the methods do range checking on index values; the caller
+/// must be sure that index values are within the range 0<index<total()
+/// (unless otherwise noted).
+///
+
+class Fl_Tree_Item_Array {
+    Fl_Tree_Item **_items;	// items array
+    int _total;			// #items in array
+    int _size;			// #items *allocated* for array
+    int _chunksize;		// #items to enlarge mem allocation
+    void enlarge(int count);
+public:
+    Fl_Tree_Item_Array(int new_chunksize = 10);		// CTOR
+    ~Fl_Tree_Item_Array();				// DTOR
+    Fl_Tree_Item_Array(const Fl_Tree_Item_Array *o);	// COPY CTOR
+    /// Return the item and index \p i.
+    Fl_Tree_Item *operator[](int i) {
+        return(_items[i]);
+    }
+    /// Const version of operator[](int i)
+    const Fl_Tree_Item *operator[](int i) const {
+        return(_items[i]);
+    }
+    /// Return the total items in the array, or 0 if empty.
+    int total() const {
+        return(_total);
+    }
+    /// Swap the two items at index positions \p ax and \p bx.
+    void swap(int ax, int bx) {
+        Fl_Tree_Item *asave = _items[ax];
+	_items[ax] = _items[bx];
+	_items[bx] = asave;
+    }
+    void clear();
+    void add(Fl_Tree_Item *val);
+    void insert(int pos, Fl_Tree_Item *new_item);
+    void remove(int index);
+    int  remove(Fl_Tree_Item *item);
+};
+
+#endif /*_FL_TREE_ITEM_ARRAY_H*/
diff --git a/contrib/Fl_Tree/FL/Fl_Tree_Prefs.H b/contrib/Fl_Tree/FL/Fl_Tree_Prefs.H
new file mode 100644
index 0000000000000000000000000000000000000000..dcf375bea4f225b39355285956e7fe491896fb4a
--- /dev/null
+++ b/contrib/Fl_Tree/FL/Fl_Tree_Prefs.H
@@ -0,0 +1,340 @@
+#ifndef FL_TREE_PREFS_H
+#define FL_TREE_PREFS_H
+
+//////////////////////
+// FL/Fl_Tree_Prefs.H
+//////////////////////
+//
+// Fl_Tree -- This file is part of the Fl_Tree widget for FLTK
+// Copyright (C) 2009 by Greg Ercolano.
+//
+// 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.
+//
+
+///
+/// \file
+/// \brief This file contains the definitions for Fl_Tree's preferences.
+///
+/// \code
+///                  Fl_Tree_Prefs
+///                       :
+///                  .....:.......
+///                  :           :
+///               Fl_Tree        :
+///                  |_____ Fl_Tree_Item
+///
+/// \endcode
+///
+
+/// \class Fl_Tree_Prefs
+/// \brief Tree widget's preferences.
+
+/// \enum Fl_Tree_Sort
+/// Sort order options for items added to the tree
+///
+enum Fl_Tree_Sort {
+    FL_TREE_SORT_NONE=0,	///< No sorting; items are added in the order defined (default).
+    FL_TREE_SORT_ASCENDING=1,	///< Add items in ascending sort order.
+    FL_TREE_SORT_DESCENDING=2	///< Add items in descending sort order.
+};
+
+/// \enum Fl_Tree_Connector
+/// Defines the style of connection lines between items.
+///
+enum Fl_Tree_Connector {
+    FL_TREE_CONNECTOR_NONE=0,	///< Use no lines connecting items
+    FL_TREE_CONNECTOR_DOTTED=1,	///< Use dotted lines connecting items (default)
+    FL_TREE_CONNECTOR_SOLID=2	///< Use solid lines connecting items
+};
+
+/// \enum Fl_Tree_Select
+/// Tree selection style.
+///
+enum Fl_Tree_Select {
+    FL_TREE_SELECT_NONE=0,	///< Nothing selected when items are clicked
+    FL_TREE_SELECT_SINGLE,	///< Single item selected when item is clicked (default)
+    FL_TREE_SELECT_MULTI	///< Multiple items can be selected by clicking with
+                                ///< SHIFT or CTRL or mouse drags.
+};
+
+/// \class Fl_Tree_Prefs
+///
+/// \brief Fl_Tree's Preferences class.
+///
+/// This class manages the Fl_Tree's defaults.
+/// You should probably be using the methods in Fl_Tree
+/// instead of trying to accessing tree's preferences settings directly.
+///
+class Fl_Tree_Prefs {
+    int _labelfont;			// label's font face
+    int _labelsize;			// label's font size
+    int _margintop;			// -- 
+    int _marginleft;			//   |- tree's margins
+    //int _marginright;			//   |
+    //int _marginbottom;		// --
+    int _usericonmarginleft;		// space to left of user icon (if any)
+    int _labelmarginleft;		// space to left of label
+    int _connectorwidth;		// connector width (right of open/close icon)
+    int _linespacing;			// vertical space between lines
+    // Colors
+    Fl_Color _fgcolor;			// label's foreground color
+    Fl_Color _bgcolor;			// background color
+    Fl_Color _selectcolor;		// selection color
+    Fl_Color _inactivecolor;		// inactive color
+    Fl_Color _connectorcolor;		// connector dotted line color
+    Fl_Tree_Connector _connectorstyle;	// connector line style
+    Fl_Pixmap *_openpixmap;		// the 'open' icon [+]
+    Fl_Pixmap *_closepixmap;		// the 'close' icon [-]
+    Fl_Pixmap *_userpixmap;		// user's own icon
+    char _showcollapse;			// 1=show collapse icons, 0=don't
+    char _showroot;			// show the root item as part of the tree
+    Fl_Tree_Sort   _sortorder;		// none, ascening, descending, etc.
+    Fl_Boxtype     _selectbox;		// selection box type
+    Fl_Tree_Select _selectmode;		// selection mode
+public:
+    Fl_Tree_Prefs();
+
+    ////////////////////////////
+    // Labels
+    ////////////////////////////
+    /// Return the label's font.
+    inline int labelfont() const {
+        return(_labelfont);
+    }
+    /// Set the label's font to \p val.
+    inline void labelfont(int val) {
+        _labelfont = val;
+    }
+    /// Return the label's size in pixels.
+    inline int labelsize() const {
+        return(_labelsize);
+    }
+    /// Set the label's size in pixels to \p val.
+    inline void labelsize(int val) {
+        _labelsize = val;
+    }
+
+    ////////////////////////////
+    // Margins
+    ////////////////////////////
+    /// Get the left margin's value in pixels
+    inline int marginleft() const {
+        return(_marginleft);
+    }
+    /// Set the left margin's value in pixels
+    inline void marginleft(int val) {
+        _marginleft = val;
+    }
+    /// Get the top margin's value in pixels
+    inline int margintop() const {
+        return(_margintop);
+    }
+    /// Set the top margin's value in pixels
+    inline void margintop(int val) {
+        _margintop = val;
+    }
+
+/****** NOT IMPLEMENTED
+    inline int marginright() const {
+        return(_marginright);
+    }
+    inline void marginright(int val) {
+        _marginright = val;
+    }
+    inline int marginbottom() const {
+        return(_marginbottom);
+    }
+    inline void marginbottom(int val) {
+        _marginbottom = val;
+    }
+*******/
+
+    /// Get the user icon's left margin value in pixels
+    inline int usericonmarginleft() const {
+        return(_usericonmarginleft);
+    }
+    /// Set the user icon's left margin value in pixels
+    inline void usericonmarginleft(int val) {
+        _usericonmarginleft = val;
+    }
+    /// Get the label's left margin value in pixels
+    inline int labelmarginleft() const {
+        return(_labelmarginleft);
+    }
+    /// Set the label's left margin value in pixels
+    inline void labelmarginleft(int val) {
+        _labelmarginleft = val;
+    }
+    /// Get the line spacing value in pixels
+    inline int linespacing() const {
+        return(_linespacing);
+    }
+    /// Set the line spacing value in pixels
+    inline void linespacing(int val) {
+        _linespacing = val;
+    }
+
+    ////////////////////////////
+    // Colors and Styles
+    ////////////////////////////
+    /// Get the default label foreground color
+    inline Fl_Color fgcolor() const {
+        return(_fgcolor);
+    }
+    /// Set the default label foreground color
+    inline void fgcolor(Fl_Color val) {
+        _fgcolor = val;
+    }
+    /// Get the default label background color
+    inline Fl_Color bgcolor() const {
+        return(_bgcolor);
+    }
+    /// Set the default label background color
+    inline void bgcolor(Fl_Color val) {
+        _bgcolor = val;
+    }
+    /// Get the default selection color
+    inline Fl_Color selectcolor() const {
+        return(_selectcolor);
+    }
+    /// Set the default selection color
+    inline void selectcolor(Fl_Color val) {
+        _selectcolor = val;
+    }
+    /// Get the default inactive color
+    inline Fl_Color inactivecolor() const {
+        return(_inactivecolor);
+    }
+    /// Set the default inactive color
+    inline void inactivecolor(Fl_Color val) {
+        _inactivecolor = val;
+    }
+    /// Get the connector color; the color used for tree connection lines
+    inline Fl_Color connectorcolor() const {
+        return(_connectorcolor);
+    }
+    /// Set the connector color; the color used for tree connection lines
+    inline void connectorcolor(Fl_Color val) {
+        _connectorcolor = val;
+    }
+    /// Get the connector style
+    inline Fl_Tree_Connector connectorstyle() const {
+        return(_connectorstyle);
+    }
+    /// Set the connector style
+    inline void connectorstyle(Fl_Tree_Connector val) {
+        _connectorstyle = val;
+    }
+    /// Get the tree connection line's width
+    inline int connectorwidth() const {
+        return(_connectorwidth);
+    }
+    /// Set the tree connection line's width
+    inline void connectorwidth(int val) {
+        _connectorwidth = val;
+    }
+
+    ////////////////////////////
+    // Icons
+    ////////////////////////////
+    /// Get the current default 'open' icon.
+    ///     Returns the Fl_Pixmap* of the icon, or 0 if none.
+    ///
+    inline Fl_Pixmap *openicon() const {
+        return(_openpixmap);
+    }
+    void openicon(Fl_Pixmap *val);
+    /// Gets the default 'close' icon
+    ///     Returns the Fl_Pixmap* of the icon, or 0 if none.
+    ///
+    inline Fl_Pixmap *closeicon() const {
+        return(_closepixmap);
+    }
+    void closeicon(Fl_Pixmap *val);
+    /// Gets the default 'user icon' (default is 0)
+    inline Fl_Pixmap *usericon() const {
+        return(_userpixmap);
+    }
+    /// Sets the default 'user icon'
+    ///     Returns the Fl_Pixmap* of the icon, or 0 if none (default).
+    ///
+    inline void usericon(Fl_Pixmap *val) {
+        _userpixmap = val;
+    }
+
+    ////////////////////////////
+    // Options
+    ////////////////////////////
+    /// Returns 1 if the collapse icon is enabled, 0 if not.
+    inline char showcollapse() const {
+        return(_showcollapse);
+    }
+    /// Set if we should show the collapse icon or not.
+    /// If collapse icons are disabled, the user will not be able
+    /// to interactively collapse items in the tree, unless the application
+    /// provides some other means via open() and close().
+    ///
+    /// \param[in] val 1: shows collapse icons (default),\n
+    ///                0: hides collapse icons.
+    ///
+    inline void showcollapse(int val) {
+        _showcollapse = val;
+    }
+    /// Get the default sort order value
+    inline Fl_Tree_Sort sortorder() const {
+        return(_sortorder);
+    }
+    /// Set the default sort order value.
+    ///     Defines the order new items appear when add()ed to the tree.
+    ///     See Fl_Tree_Sort for possible values.
+    ///
+    inline void sortorder(Fl_Tree_Sort val) {
+        _sortorder = val;
+    }
+    /// Get the default selection box's box drawing style as an Fl_Boxtype.
+    inline Fl_Boxtype selectbox() const {
+        return(_selectbox);
+    }
+    /// Set the default selection box's box drawing style to \p val.
+    inline void selectbox(Fl_Boxtype val) {
+        _selectbox = val;
+    }
+    /// Returns 1 if the root item is to be shown, or 0 if not.
+    inline int showroot() const {
+        return(int(_showroot));
+    }
+    /// Set if the root item should be shown or not.
+    /// \param[in] val 1 -- show the root item (default)\n
+    ///                0 -- hide the root item.
+    ///
+    inline void showroot(int val) {
+        _showroot = char(val);
+    }
+    /// Get the selection mode used for the tree
+    inline Fl_Tree_Select selectmode() const {
+        return(_selectmode);
+    }
+    /// Set the selection mode used for the tree to \p val.
+    ///     This affects how items in the tree are selected
+    ///     when clicked on and dragged over by the mouse.
+    ///     See Fl_Tree_Select for possible values.
+    ///
+    inline void selectmode(Fl_Tree_Select val) {
+        _selectmode = val;
+    }
+};
+
+#endif /*FL_TREE_PREFS_H*/
diff --git a/contrib/Fl_Tree/Fl_Tree.cxx b/contrib/Fl_Tree/Fl_Tree.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..567a97f1e53af357c3544729fe74b404212d2b35
--- /dev/null
+++ b/contrib/Fl_Tree/Fl_Tree.cxx
@@ -0,0 +1,407 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <FL/Fl_Tree.H>
+
+#define SCROLL_W 15
+
+//////////////////////
+// Fl_Tree.cxx
+//////////////////////
+//
+// Fl_Tree -- This file is part of the Fl_Tree widget for FLTK
+// Copyright (C) 2009 by Greg Ercolano.
+//
+// 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.
+//
+
+/// \mainpage Fl_Tree Widget
+///
+/// \image html tree-simple-screenshot.png
+///
+/// \code
+///     Fl_Tree                                         // Top level widget
+///        |--- Fl_Tree_Item                            // Items in the tree
+///        |--- Fl_Tree_Prefs                           // Preferences for the tree
+///                  |--- Fl_Tree_Connector (enum)      // Connection modes
+///                  |--- Fl_Tree_Select (enum)         // Selection modes
+///                  |--- Fl_Tree_Sort (enum)           // Sort behavior
+///
+/// \endcode
+///
+/// \b Overview
+/// <P>
+/// This is a hierarchical 'tree' browser widget that presents its data
+/// in a hierarchy. Nodes can optionally be open/closed, and items can
+/// be individually created, deleted, sorted, and attributes customized
+/// for different fonts and colors.
+///
+/// The simple way to define a tree:
+/// \code
+///    Fl_Tree tree(X,Y,W,H);
+///    tree.begin();
+///      tree.add("Flintstones/Fred");
+///      tree.add("Flintstones/Wilma");
+///      tree.add("Flintstones/Pebbles");
+///      tree.add("Simpsons/Homer");
+///      tree.add("Simpsons/Marge");
+///      tree.add("Simpsons/Bart");
+///      tree.add("Simpsons/Lisa");
+///    tree.end();
+/// \endcode
+///
+/// Items can also be FLTK widgets, instead of just simple labels (default).
+///
+/// Fl_Tree derives from FLTK's Fl_Group, so that if FLTK widgets are added
+/// to the tree, they become children of the group.
+///
+/// Each item in the tree is an Fl_Tree_Item, which has customizable
+/// values for setting the font, color, and other attributes on a per-item
+/// basis.
+///
+/// Each tree contains an instance of the Fl_Tree_Prefs class, which handles
+/// global preferences for the tree, and the default values used for newly
+/// created items in the tree.
+///
+/// By default, when items are added to the tree, they're added in the order created.
+/// Sorting can be specified with the Fl_Tree::sortorder() method.
+///
+///     \image html tree-elements.png
+///
+
+// INTERNAL: scroller callback
+static void scroll_cb(Fl_Widget*,void *data) {
+    ((Fl_Tree*)data)->redraw();
+}
+
+// INTERNAL: Parse elements from path
+//    Path="/aa/bb"
+//    Return: arr[0]="aa", arr[1]="bb", arr[2]=0
+//    Caller must: free(arr[0]); free(arr);
+//
+static char **parse_path(const char *path) {
+    while ( *path == '/' ) path++;	// skip leading '/' 
+    // First pass: identify, null terminate, and count separators
+    int seps = 1;			// separator count (1: first item)
+    int arrsize = 1;			// array size (1: first item)
+    char *save = strdup(path);		// make copy we can modify
+    char *s = save;
+    while ( ( s = strchr(s, '/') ) ) {
+	while ( *s == '/' ) { *s++ = 0; seps++; }
+	if ( *s ) { arrsize++; }
+    }
+    arrsize++;				// (room for terminating NULL) 
+    // Second pass: create array, save nonblank elements
+    char **arr = (char**)malloc(sizeof(char*) * arrsize);
+    int t = 0;
+    s = save;
+    while ( seps-- > 0 ) {
+        if ( *s ) { arr[t++] = s; }	// skips empty fields, eg. '//'
+        s += (strlen(s) + 1);
+    }
+    arr[t] = 0;
+    return(arr);
+}
+
+// INTERNAL: Recursively descend tree hierarchy, accumulating total child count
+static int find_total_children(Fl_Tree_Item *item, int count=0) {
+    count++;
+    for ( int t=0; t<item->children(); t++ ) {
+	count = find_total_children(item->child(t), count);
+    }
+    return(count);
+}
+
+/// Constructor.
+Fl_Tree::Fl_Tree(int X, int Y, int W, int H, const char *L) : Fl_Group(X,Y,W,H,L) { 
+    _root = new Fl_Tree_Item(_prefs);
+    _root->parent(0);				// we are root of tree
+    _root->label("ROOT");
+    _item_clicked = 0;
+    box(FL_DOWN_BOX);
+    color(FL_WHITE);
+    when(FL_WHEN_CHANGED);
+    _vscroll = new Fl_Scrollbar(0,0,0,0);	// will be resized by draw()
+    _vscroll->hide();
+    _vscroll->type(FL_VERTICAL);
+    _vscroll->step(1);
+    _vscroll->callback(scroll_cb, (void*)this);
+    end();
+}
+
+/// Destructor.
+Fl_Tree::~Fl_Tree() {
+    if ( _root ) { delete _root; _root = 0; }
+}
+
+/// Adds a new item, given a 'menu style' path, eg: "/Parent/Child/item".
+/// Any parent nodes that don't already exist are created automatically.
+/// Adds the item based on the value of sortorder().
+/// \returns the child item created, or 0 on error.
+///
+Fl_Tree_Item* Fl_Tree::add(const char *path) {
+    if ( ! _root ) {					// Create root if none
+	_root = new Fl_Tree_Item(_prefs);
+	_root->parent(0);
+	_root->label("ROOT");
+    }
+    char **arr = parse_path(path);
+    Fl_Tree_Item *item = _root->add(_prefs, arr);
+    free((void*)arr[0]);
+    free((void*)arr);
+    return(item);
+}
+
+/// Inserts a new item above the specified Fl_Tree_Item, with the label set to 'name'.
+/// \returns the item that was added, or 0 if 'above' could not be found.
+/// 
+Fl_Tree_Item* Fl_Tree::insert_above(Fl_Tree_Item *above, const char *name) {
+    return(above->insert_above(_prefs, name));
+}
+
+/// Find the item, given a menu style path, eg: "/Parent/Child/item".
+///
+/// There is both a const and non-const version of this method.
+/// Const version allows pure const methods to use this method 
+/// to do lookups without causing compiler errors.
+/// \returns the item, or 0 if not found.
+///
+Fl_Tree_Item *Fl_Tree::find_item(const char *path) {
+    if ( ! _root ) return(0);
+    char **arr = parse_path(path);
+    Fl_Tree_Item *item = _root->find_item(arr);
+    free((void*)arr[0]);
+    free((void*)arr);
+    return(item);
+}
+
+/// A const version of Fl_Tree::find_item(const char *path)
+const Fl_Tree_Item *Fl_Tree::find_item(const char *path) const {
+    if ( ! _root ) return(0);
+    char **arr = parse_path(path);
+    const Fl_Tree_Item *item = _root->find_item(arr);
+    free((void*)arr[0]);
+    free((void*)arr);
+    return(item);
+}
+
+/// Standard FLTK draw() method, handles draws the tree widget.
+void Fl_Tree::draw() {
+    // Let group draw box+label but *NOT* children.
+    // *We* handle drawing children ourselves by calling each item's draw()
+    //
+    Fl_Group::draw_box();
+    Fl_Group::draw_label();
+    if ( ! _root ) return;
+    int cx = x() + Fl::box_dx(box());
+    int cy = y() + Fl::box_dy(box());
+    int cw = w() - Fl::box_dw(box());
+    int ch = h() - Fl::box_dh(box());
+    // These valued changed during drawing
+    // 'Y' will be the lowest point on the tree
+    int X = cx + _prefs.marginleft();
+    int Y = cy + _prefs.margintop() - (_vscroll->visible() ? _vscroll->value() : 0);
+    int W = cw - _prefs.marginleft();		// - _prefs.marginright();
+    int Ysave = Y;
+    fl_push_clip(cx,cy,cw,ch);
+    {
+        fl_font(_prefs.labelfont(), _prefs.labelsize());
+        _root->draw(X, Y, W, this, _prefs);
+    }
+    fl_pop_clip();
+    // Should we show vertical scrollbar?
+    int ydiff = (Y+_prefs.margintop())-Ysave;		// ydiff=size of tree
+    int ytoofar = (cy+ch) - Y;				// ytoofar -- scrolled beyond bottom (eg. stow)
+
+    //printf("ydiff=%d ch=%d Ysave=%d ytoofar=%d value=%d\n",
+    //int(ydiff),int(ch),int(Ysave),int(ytoofar), int(_vscroll->value()));
+
+    if ( ytoofar > 0 ) ydiff += ytoofar;
+    if ( Ysave<cy || ydiff > ch || int(_vscroll->value()) > 1 ) {
+        _vscroll->visible();
+	int sx = x()+w()-Fl::box_dx(box())-SCROLL_W;
+	int sy = y()+Fl::box_dy(box());
+	int sw = SCROLL_W;
+	int sh = h()-Fl::box_dh(box());
+	_vscroll->show();
+	_vscroll->range(0.0,ydiff-ch);
+	_vscroll->resize(sx,sy,sw,sh);
+	_vscroll->slider_size(float(ch)/float(ydiff));
+    } else {
+        _vscroll->Fl_Slider::value(0);
+        _vscroll->hide();
+    }
+    fl_push_clip(cx,cy,cw,ch);
+        Fl_Group::draw_children();
+    fl_pop_clip();
+}
+
+/// Standard FLTK event handler for this widget.
+int Fl_Tree::handle(int e) {
+    static Fl_Tree_Item *lastselect = 0;
+    int changed = 0;
+    int ret = Fl_Group::handle(e);
+    if ( ! _root ) return(ret);
+    switch ( e ) {
+	case FL_PUSH: {
+	    lastselect = 0;
+	    item_clicked(0);	// assume no item was clicked
+	    Fl_Tree_Item *o = _root->find_clicked();
+	    if ( o ) {
+		ret |= 1;					// handled
+	        if ( Fl::event_button() == FL_LEFT_MOUSE ) {
+		    // Was collapse icon clicked?
+		    if ( o->event_on_collapse_icon(_prefs) ) {
+			o->open_toggle();
+			redraw();
+		    }
+		    // Item's label clicked?
+		    else if ( o->event_on_label(_prefs) && 
+			      (!o->widget() || !Fl::event_inside(o->widget())) &&
+			      callback() &&
+			      (!_vscroll->visible() || !Fl::event_inside(_vscroll)) ) {
+			item_clicked(o);			// save item clicked
+			// Handle selection behavior
+			switch ( _prefs.selectmode() ) {
+			    case FL_TREE_SELECT_NONE: {		// no selection changes
+			        break;
+			    }
+			    case FL_TREE_SELECT_SINGLE: {
+				changed = select_only(o);
+			        break;
+			    }
+			    case FL_TREE_SELECT_MULTI: {
+			        int state = Fl::event_state();
+			        if ( state & FL_SHIFT ) {
+				    if ( ! o->is_selected() ) {
+					o->select();		// add to selection
+					changed = 1;		// changed
+				    }
+				} else if ( state & FL_CTRL ) {
+				    changed = 1;		// changed
+				    o->select_toggle();		// toggle selection state
+				    lastselect = o;		// save we toggled it (prevents oscillation)
+				} else {
+				    changed = select_only(o);
+				}
+			        break;
+			    }
+			}
+			if ( changed ) {
+			    redraw();				// make change(s) visible
+			    if ( when() & FL_WHEN_CHANGED ) {
+				set_changed();
+				do_callback((Fl_Widget*)this, user_data());	// item callback
+			    }
+			}
+		    }
+		}
+	    }
+	    break;
+	}
+	case FL_DRAG: {
+	    Fl_Tree_Item *o = _root->find_clicked();
+	    if ( o ) {
+		ret |= 1;				// handled
+		// Item's label clicked?
+		if ( o->event_on_label(_prefs) && 
+			  (!o->widget() || !Fl::event_inside(o->widget())) &&
+			  callback() &&
+			  (!_vscroll->visible() || !Fl::event_inside(_vscroll)) ) {
+		    item_clicked(o);			// save item clicked
+		    // Handle selection behavior
+		    switch ( _prefs.selectmode() ) {
+			case FL_TREE_SELECT_NONE: {	// no selection changes
+			    break;
+			}
+			case FL_TREE_SELECT_SINGLE: {
+			    changed = select_only(o);
+			    break;
+			}
+			case FL_TREE_SELECT_MULTI: {
+			    int state = Fl::event_state();
+			    if ( state & FL_CTRL ) {
+				if ( lastselect != o ) {// not already toggled from last microdrag?
+				    changed = 1;	// changed
+				    o->select_toggle();	// toggle selection
+				    lastselect = o;	// save we toggled it (prevents oscillation)
+				    redraw();		// make change(s) visible
+				}
+			    } else {
+				changed = 1;		// changed
+				o->select();		// select this
+				redraw();		// make change(s) visible
+			    }
+			    break;
+			}
+		    }
+		    if ( changed ) {
+			redraw();				// make change(s) visible
+			if ( when() & FL_WHEN_CHANGED ) {
+			    set_changed();
+			    do_callback((Fl_Widget*)this, user_data());	// item callback
+			}
+		    }
+		}
+	    }
+	}
+	case FL_RELEASE: {
+	    if ( Fl::event_button() == FL_LEFT_MOUSE ) {
+		ret |= 1;
+	    }
+	    break;
+	}
+    }
+    return(ret);
+}
+
+/// Deselect item and all its children.
+///     If item is NULL, root() is used.
+///     Handles calling redraw() if anything was changed.
+///     Returns count of how many items were in the 'selected' state,
+///     ie. how many items were "changed".
+///
+int Fl_Tree::deselect_all(Fl_Tree_Item *item) {
+    item = item ? item : root();		// NULL? use root()
+    int count = item->deselect_all();
+    if ( count ) redraw();			// anything changed? cause redraw
+    return(count);
+}
+
+/// Select only this item.
+///     If item is NULL, root() is used.
+///     Handles calling redraw() if anything was changed.
+///     Returns how many items were changed, if any.
+///
+int Fl_Tree::select_only(Fl_Tree_Item *selitem) {
+    selitem = selitem ? selitem : root();		// NULL? use root()
+    int changed = 0;
+    for ( Fl_Tree_Item *item = first(); item; item = item->next() ) {
+        if ( item == selitem ) {
+	    if ( item->is_selected() ) continue;	// don't count if already selected
+	    item->select();
+	    ++changed;
+	} else {
+	    if ( item->is_selected() ) {
+	       item->deselect();
+	       ++changed;
+	    }
+        }
+    }
+    if ( changed ) redraw();				// anything changed? redraw
+    return(changed);
+}
diff --git a/contrib/Fl_Tree/Fl_Tree_Item.cxx b/contrib/Fl_Tree/Fl_Tree_Item.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..9f72fcadf1361086ce6fc2876d2aa8e35b927f64
--- /dev/null
+++ b/contrib/Fl_Tree/Fl_Tree_Item.cxx
@@ -0,0 +1,693 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Tree_Item.H>
+#include <FL/Fl_Tree_Prefs.H>
+
+//////////////////////
+// Fl_Tree_Item.cxx
+//////////////////////
+//
+// Fl_Tree -- This file is part of the Fl_Tree widget for FLTK
+// Copyright (C) 2009 by Greg Ercolano.
+//
+// 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.
+//
+
+// Was the last event inside the specified xywh?
+static int event_inside(const int xywh[4]) {
+    return(Fl::event_inside(xywh[0],xywh[1],xywh[2],xywh[3]));
+}
+
+/// Constructor.
+///     Makes a new instance of Fl_Tree_Item using defaults from 'prefs'.
+///
+Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Prefs &prefs) {
+    _label        = 0;
+    _labelfont    = prefs.labelfont();
+    _labelsize    = prefs.labelsize();
+    _labelfgcolor = prefs.fgcolor();
+    _labelbgcolor = prefs.bgcolor();
+    _widget       = 0;
+    _open         = 1;
+    _visible      = 1;
+    _active       = 1;
+    _selected     = 0;
+    _xywh[0]      = 0;
+    _xywh[1]      = 0;
+    _xywh[2]      = 0;
+    _xywh[3]      = 0;
+    _collapse_xywh[0] = 0;
+    _collapse_xywh[1] = 0;
+    _collapse_xywh[2] = 0;
+    _collapse_xywh[3] = 0;
+    _label_xywh[0]    = 0;
+    _label_xywh[1]    = 0;
+    _label_xywh[2]    = 0;
+    _label_xywh[3]    = 0;
+    _usericon         = 0;
+    _userdata         = 0; // GMSH
+    _parent           = 0;
+}
+
+// DTOR
+Fl_Tree_Item::~Fl_Tree_Item() {
+    if ( _label ) { 
+        free((void*)_label);
+	_label = 0;
+    }
+    _widget = 0;			// Fl_Group will handle destruction
+    _usericon = 0;			// user handled allocation
+    //_children.clear();		// array's destructor handles itself
+}
+
+/// Copy constructor.
+Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Item *o) {
+    _label        = o->label() ? strdup(o->label()) : 0;
+    _labelfont    = o->labelfont();
+    _labelsize    = o->labelsize();
+    _labelfgcolor = o->labelfgcolor();
+    _labelbgcolor = o->labelbgcolor();
+    _widget       = o->widget();
+    _open         = o->_open;
+    _visible      = o->_visible;
+    _active       = o->_active;
+    _selected     = o->_selected;
+    _xywh[0]      = o->_xywh[0];
+    _xywh[1]      = o->_xywh[1];
+    _xywh[2]      = o->_xywh[2];
+    _xywh[3]      = o->_xywh[3];
+    _collapse_xywh[0] = o->_collapse_xywh[0];
+    _collapse_xywh[1] = o->_collapse_xywh[1];
+    _collapse_xywh[2] = o->_collapse_xywh[2];
+    _collapse_xywh[3] = o->_collapse_xywh[3];
+    _label_xywh[0]    = o->_label_xywh[0];
+    _label_xywh[1]    = o->_label_xywh[1];
+    _label_xywh[2]    = o->_label_xywh[2];
+    _label_xywh[3]    = o->_label_xywh[3];
+    _usericon         = o->usericon();
+    _parent           = o->_parent;
+}
+
+/// Print the tree as 'ascii art' to stdout.
+/// Used mainly for debugging.
+///
+void Fl_Tree_Item::show_self(const char *indent) const {
+    if ( label() ) {
+        printf("%s-%s (%d children, this=%p, parent=%p depth=%d)\n",
+	    indent,label(),children(),(void*)this, (void*)_parent, depth());
+    }
+    if ( children() ) {
+	char *i2 = (char*)malloc(strlen(indent) + 2);
+	strcpy(i2, indent);
+	strcat(i2, " |");
+	for ( int t=0; t<children(); t++ ) {
+	    child(t)->show_self(i2);
+	}
+    }
+    fflush(stdout);
+}
+
+/// Set the label. Makes a copy of the name.
+void Fl_Tree_Item::label(const char *name) {
+    if ( _label ) { free((void*)_label); _label = 0; }
+    _label = name ? strdup(name) : 0;
+}
+
+/// Return the label.
+const char *Fl_Tree_Item::label() const {
+    return(_label);
+}
+
+/// Return child item for the specified 'index'.
+const Fl_Tree_Item *Fl_Tree_Item::child(int index) const {
+    return(_children[index]);
+}
+
+/// Clear all the children for this item.
+void Fl_Tree_Item::clear_children() {
+    _children.clear();
+}
+
+/// Return the index of the immediate child of this item that has the label 'name'.
+///
+/// \returns index of found item, or -1 if not found.
+///
+int Fl_Tree_Item::find_child(const char *name) {
+    for ( int t=0; t<children(); t++ ) {
+        if ( child(t)->label() ) {
+	    if ( strcmp(child(t)->label(), name) == 0 ) {
+		return(t);
+	    }
+	}
+    }
+    return(-1);
+}
+
+/// Find item by descending array of names.
+/// Only Fl_Tree should need this method.
+///
+/// \returns item, or 0 if not found
+///
+const Fl_Tree_Item *Fl_Tree_Item::find_item(char **arr) const {
+    for ( int t=0; t<children(); t++ ) {
+        if ( child(t)->label() ) {
+	    if ( strcmp(child(t)->label(), *arr) == 0 ) {	// match?
+	        if ( *(arr+1) ) {				// more in arr? descend
+		    return(_children[t]->find_item(arr+1));
+		} else {					// end of arr? done
+		    return(_children[t]);
+		}
+	    }
+	}
+    }
+    return(0);
+}
+
+/// Find item by by descending array of names.
+/// Only Fl_Tree should need this method.
+///
+/// \returns item, or 0 if not found
+///
+Fl_Tree_Item *Fl_Tree_Item::find_item(char **arr) {
+    for ( int t=0; t<children(); t++ ) {
+        if ( child(t)->label() ) {
+	    if ( strcmp(child(t)->label(), *arr) == 0 ) {	// match?
+	        if ( *(arr+1) ) {				// more in arr? descend
+		    return(_children[t]->find_item(arr+1));
+		} else {					// end of arr? done
+		    return(_children[t]);
+		}
+	    }
+	}
+    }
+    return(0);
+}
+
+/// Find the index number for the specified 'item'
+/// in the current item's list of children.
+///
+/// \returns the index, or -1 if not found.
+///
+int Fl_Tree_Item::find_child(Fl_Tree_Item *item) {
+    for ( int t=0; t<children(); t++ ) {
+	if ( item == child(t) ) {
+	    return(t);
+	}
+    }
+    return(-1);
+}
+
+/// Add a new child to this item with the name 'new_label', with defaults from 'prefs'.
+/// An internally managed copy is made of the label string.
+/// Adds the item based on the value of prefs.sortorder().
+///
+Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, const char *new_label) {
+    Fl_Tree_Item *item = new Fl_Tree_Item(prefs);
+    item->label(new_label);
+    item->_parent = this;
+    switch ( prefs.sortorder() ) {
+        case FL_TREE_SORT_NONE: {
+	    _children.add(item);
+	    return(item);
+	}
+        case FL_TREE_SORT_ASCENDING: {
+	    for ( int t=0; t<_children.total(); t++ ) {
+	        Fl_Tree_Item *c = _children[t];
+	        if ( c->label() && strcmp(c->label(), new_label) > 0 ) {
+		    _children.insert(t, item);
+		    return(item);
+		}
+	    }
+	    _children.add(item);
+	    return(item);
+	}
+        case FL_TREE_SORT_DESCENDING: {
+	    for ( int t=0; t<_children.total(); t++ ) {
+	        Fl_Tree_Item *c = _children[t];
+	        if ( c->label() && strcmp(c->label(), new_label) < 0 ) {
+		    _children.insert(t, item);
+		    return(item);
+		}
+	    }
+	    _children.add(item);
+	    return(item);
+	}
+    }
+    return(item);
+}
+
+/// Add a child recursively into tree.
+/// Should be used only by Fl_Tree's internals.
+/// Adds the item based on the value of prefs.sortorder().
+///
+Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, char **arr) {
+    int t = find_child(*arr);
+    Fl_Tree_Item *item;
+    if ( t == -1 ) {
+        item = (Fl_Tree_Item*)add(prefs, *arr);
+    } else {
+        item = (Fl_Tree_Item*)child(t);
+    }
+    if ( *(arr+1) ) {		// descend?
+        return(item->add(prefs, arr+1));
+    } else {
+        return(item);		// end? done
+    }
+}
+
+/// Insert a new item into current item's children at a specified position.
+Fl_Tree_Item *Fl_Tree_Item::insert(const Fl_Tree_Prefs &prefs, const char *new_label, int pos) {
+    Fl_Tree_Item *item = new Fl_Tree_Item(prefs);
+    item->label(new_label);
+    item->_parent = this;
+    _children.insert(pos, item);
+    return(item);
+}
+
+/// Insert a new item above this item.
+Fl_Tree_Item *Fl_Tree_Item::insert_above(const Fl_Tree_Prefs &prefs, const char *new_label) {
+    Fl_Tree_Item *p = _parent;
+    if ( ! p ) return(0);
+    // Walk our parent's children to find ourself
+    for ( int t=0; t<p->children(); t++ ) {
+        Fl_Tree_Item *c = p->child(t);
+	if ( this == c ) {
+	    return(p->insert(prefs, new_label, t));
+	}
+    }
+    return(0);
+}
+
+/// Remove child by item.
+///    Returns 0 if removed, -1 if item not an immediate child.
+///
+int Fl_Tree_Item::remove_child(Fl_Tree_Item *item) {
+    for ( int t=0; t<children(); t++ ) {
+        if ( child(t) == item ) {
+	    item->clear_children();
+	    _children.remove(t);
+	    return(0);
+	}
+    }
+    return(-1);
+}
+
+/// Remove immediate child (and its children) by its label 'name'.
+///    Returns 0 if removed, -1 if not found.
+///
+int Fl_Tree_Item::remove_child(const char *name) {
+    for ( int t=0; t<children(); t++ ) {
+        if ( child(t)->label() ) {
+	    if ( strcmp(child(t)->label(), name) == 0 ) {
+	        _children.remove(t);
+		return(0);
+	    }
+	}
+    }
+    return(-1);
+}
+
+/// Swap two of our children, given two child index values.
+/// Use this eg. for sorting.
+///
+/// This method is FAST, and does not involve lookups.
+///
+/// No range checking is done on either index value.
+///
+/// \returns
+///    -    0 : OK
+///    -   -1 : failed: 'a' or 'b' is not our immediate child
+///
+void Fl_Tree_Item::swap_children(int ax, int bx) {
+    _children.swap(ax, bx);
+}
+
+/// Swap two of our children, given item pointers.
+/// Use this eg. for sorting. 
+///
+/// This method is SLOW because it involves linear lookups.
+/// For speed, use swap_children(int,int) instead.
+///
+/// \returns
+///    -    0 : OK
+///    -   -1 : failed: 'a' or 'b' is not our immediate child
+///
+int Fl_Tree_Item::swap_children(Fl_Tree_Item *a, Fl_Tree_Item *b) {
+    int ax = -1, bx = -1;
+    for ( int t=0; t<children(); t++ ) {	// find index for a and b
+        if ( _children[t] == a ) { ax = t; if ( bx != -1 ) break; else continue; }
+	if ( _children[t] == b ) { bx = t; if ( ax != -1 ) break; else continue; }
+    }
+    if ( ax == -1 || bx == -1 ) return(-1);	// not found? fail
+    swap_children(ax,bx);
+    return(0);
+}
+
+/// Internal: Horizontal connector line based on preference settings.
+void Fl_Tree_Item::draw_horizontal_connector(int x1, int x2, int y, const Fl_Tree_Prefs &prefs) {
+    fl_color(prefs.connectorcolor());
+    switch ( prefs.connectorstyle() ) {
+        case FL_TREE_CONNECTOR_SOLID:
+	    y |= 1;				// force alignment w/dot pattern
+	    fl_line(x1,y,x2,y);
+	    return;
+        case FL_TREE_CONNECTOR_DOTTED:
+	    y |= 1;				// force alignment w/dot pattern
+	    for ( int xx=x1; xx<=x2; xx++ ) {
+		if ( !(xx & 1) ) fl_point(xx, y);
+	    }
+	    return;
+        case FL_TREE_CONNECTOR_NONE:
+	    return;
+    }
+}
+
+/// Internal: Vertical connector line based on preference settings.
+void Fl_Tree_Item::draw_vertical_connector(int x, int y1, int y2, const Fl_Tree_Prefs &prefs) {
+    fl_color(prefs.connectorcolor());
+    switch ( prefs.connectorstyle() ) {
+        case FL_TREE_CONNECTOR_SOLID:
+	    y1 |= 1;				// force alignment w/dot pattern
+	    y2 |= 1;				// force alignment w/dot pattern
+	    fl_line(x,y1,x,y2);
+	    return;
+        case FL_TREE_CONNECTOR_DOTTED:
+	    y1 |= 1;				// force alignment w/dot pattern
+	    y2 |= 1;				// force alignment w/dot pattern
+	    for ( int yy=y1; yy<=y2; yy++ ) {
+		if ( yy & 1 ) fl_point(x, yy);
+	    }
+	    return;
+        case FL_TREE_CONNECTOR_NONE:
+	    return;
+    }
+}
+
+/// Find the item that the last event was over.
+///
+///    Returns the item if its visible, and mouse is over it.
+///    Works even if widget deactivated.
+///    Use event_on_collapse_icon() to determine if collapse button was pressed.
+///
+///    \returns const visible item under the event if found, or 0 if none.
+///
+const Fl_Tree_Item *Fl_Tree_Item::find_clicked() const {
+    if ( ! _visible ) return(0);
+    if ( event_inside(_xywh) ) {		// event within this item?
+	return(this);				// found
+    }
+    if ( is_open() ) {				// open? check children of this item
+	for ( int t=0; t<children(); t++ ) {
+	    const Fl_Tree_Item *item;
+	    if ( ( item = _children[t]->find_clicked() ) != NULL) {	// check child and its descendents
+	        return(item);						// found?
+	    }
+	}
+    }
+    return(0);
+}
+
+/// Non-const version of the above.
+/// Find the item that the last event was over.
+///
+///    Returns the item if its visible, and mouse is over it.
+///    Works even if widget deactivated.
+///    Use event_on_collapse_icon() to determine if collapse button was pressed.
+///
+///    \returns the visible item under the event if found, or 0 if none.
+///
+Fl_Tree_Item *Fl_Tree_Item::find_clicked() {
+    if ( ! _visible ) return(0);
+    if ( event_inside(_xywh) ) {		// event within this item?
+	return(this);				// found
+    }
+    if ( is_open() ) {				// open? check children of this item
+	for ( int t=0; t<children(); t++ ) {
+	    Fl_Tree_Item *item;
+	    if ( ( item = _children[t]->find_clicked() ) != NULL ) {	// check child and its descendents
+	        return(item);						// found?
+	    }
+	}
+    }
+    return(0);
+}
+
+/// Draw this item and its children.
+void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree, 
+                        const Fl_Tree_Prefs &prefs, int lastchild) {
+    if ( ! _visible ) return; 
+    fl_font(_labelfont, _labelsize);
+    int H = _labelsize + fl_descent() + prefs.linespacing();
+    // Colors, fonts
+    Fl_Color fg = _selected ? prefs.bgcolor()     : _labelfgcolor;
+    Fl_Color bg = _selected ? prefs.selectcolor() : _labelbgcolor;
+    if ( ! _active ) {
+	fg = fl_inactive(fg);
+	if ( _selected ) bg = fl_inactive(bg);
+    }
+    // Update the xywh of this item
+    _xywh[0] = X;
+    _xywh[1] = Y;
+    _xywh[2] = W;
+    _xywh[3] = H;
+    // Text size
+    int textw=0, texth=0;
+    fl_measure(_label, textw, texth, 0);
+    int textycenter = Y+(H/2);
+    int &icon_x = _collapse_xywh[0] = X-1;
+    int &icon_y = _collapse_xywh[1] = textycenter - (prefs.openicon()->h()/2);
+    int &icon_w = _collapse_xywh[2] = prefs.openicon()->w();
+    _collapse_xywh[3] = prefs.openicon()->h();
+    // Horizontal connector values
+    int hstartx  = X+icon_w/2-1;
+    int hendx    = hstartx + prefs.connectorwidth();
+    int hcenterx = X + icon_w + ((hendx - (X + icon_w)) / 2);
+
+    // See if we should draw this item
+    //    If this item is root, and showroot() is disabled, don't draw.
+    //
+    char drawthis = ( is_root() && prefs.showroot() == 0 ) ? 0 : 1;
+    if ( drawthis ) {
+	// Draw connectors
+	if ( prefs.connectorstyle() != FL_TREE_CONNECTOR_NONE ) {
+	    // Horiz connector between center of icon and text
+	    draw_horizontal_connector(hstartx, hendx, textycenter, prefs);
+	    if ( has_children() && is_open() ) {
+		// Small vertical line down to children
+		draw_vertical_connector(hcenterx, textycenter, Y+H, prefs);
+	    }
+	    // Connectors for last child
+	    if ( ! is_root() ) {
+		if ( lastchild ) {
+		    draw_vertical_connector(hstartx, Y, textycenter, prefs);
+		} else {
+		    draw_vertical_connector(hstartx, Y, Y+H, prefs);
+		}
+	    }
+	} 
+	// Draw collapse icon
+	if ( has_children() && prefs.showcollapse() ) {
+	    // Draw icon image
+	    if ( is_open() ) {
+		prefs.closeicon()->draw(icon_x,icon_y);
+	    } else {
+		prefs.openicon()->draw(icon_x,icon_y);
+	    }
+	}
+	// Background for this item
+	int &bx = _label_xywh[0] = X+(icon_w/2-1+prefs.connectorwidth());
+	int &by = _label_xywh[1] = Y;
+	int &bw = _label_xywh[2] = W-(icon_w/2-1+prefs.connectorwidth());
+	int &bh = _label_xywh[3] = texth;
+	// Draw bg only if different from tree's bg
+	if ( bg != tree->color() || is_selected() ) {
+	    if ( is_selected() ) {
+		// Selected? Use selectbox() style
+		fl_draw_box(prefs.selectbox(), bx, by, bw, bh, bg);
+	    } else {
+		// Not Selected? use plain filled rectangle
+		fl_color(bg);
+		fl_rectf(bx, by, bw, bh);
+	    }
+	}
+	// Draw user icon (if any)
+	int useroff = (icon_w/2-1+prefs.connectorwidth());
+	if ( usericon() ) {
+	    // Item has user icon? Use it
+	    useroff += prefs.usericonmarginleft();
+	    usericon()->draw(X+useroff,icon_y);
+	    useroff += usericon()->w();
+	} else if ( prefs.usericon() ) {
+	    // Prefs has user icon? Use it
+	    useroff += prefs.usericonmarginleft();
+	    prefs.usericon()->draw(X+useroff,icon_y);
+	    useroff += prefs.usericon()->w();
+	}
+	useroff += prefs.labelmarginleft();
+	// Draw label
+	if ( widget() ) {
+	    // Widget? Draw it
+	    int lx = X+useroff;
+	    int ly = by;
+	    int lw = widget()->w();
+	    int lh = bh;
+	    if ( widget()->x() != lx || widget()->y() != ly ||
+		 widget()->w() != lw || widget()->h() != lh ) {
+		widget()->resize(lx, ly, lw, lh);		// fltk will handle drawing this
+	    }
+	} else {
+	    // No label widget? Draw text label
+	    if ( _label ) {
+		fl_color(fg);
+		fl_draw(_label, X+useroff, Y+H-fl_descent()-1);
+	    }
+	}
+	Y += H;
+    }			// end drawthis
+    // Draw children
+    if ( has_children() && is_open() ) {
+	int child_x = drawthis ? 			// offset children to right,
+	              (hcenterx - (icon_w/2) + 1) : X;	// unless didn't drawthis
+	int child_w = W - (child_x-X);
+	int child_y_start = Y;
+	for ( int t=0; t<children(); t++ ) {
+	    int lastchild = ((t+1)==children()) ? 1 : 0;
+	    _children[t]->draw(child_x, Y, child_w, tree, prefs, lastchild);
+	}
+	if ( ! lastchild ) {
+	    draw_vertical_connector(hstartx, child_y_start, Y, prefs);
+	}
+    }
+}
+
+/// Was the event on the 'collapse' button?
+///
+int Fl_Tree_Item::event_on_collapse_icon(const Fl_Tree_Prefs &prefs) const {
+    if ( _visible && _active && has_children() && prefs.showcollapse() ) {
+        return(event_inside(_collapse_xywh) ? 1 : 0);
+    } else {
+	return(0);
+    }
+}
+
+/// Was event on the label()?
+///
+int Fl_Tree_Item::event_on_label(const Fl_Tree_Prefs &prefs) const {
+    if ( _visible && _active ) {
+        return(event_inside(_label_xywh) ? 1 : 0);
+    } else {
+	return(0);
+    }
+}
+
+/// Internal: Show the FLTK widget() for this item and all children.
+/// Used by open() to re-show widgets that were hidden by a previous close()
+///
+void Fl_Tree_Item::show_widgets() {
+    if ( _widget ) _widget->show();
+    if ( is_open() ) {
+	for ( int t=0; t<_children.total(); t++ ) {
+	    _children[t]->show_widgets();
+	}
+    }
+}
+
+/// Internal: Hide the FLTK widget() for this item and all children.
+/// Used by close() to hide widgets.
+///
+void Fl_Tree_Item::hide_widgets() {
+    if ( _widget ) _widget->hide();
+    for ( int t=0; t<_children.total(); t++ ) {
+	_children[t]->hide_widgets();
+    }
+}
+
+/// Open this item and all its children.
+void Fl_Tree_Item::open() {
+    _open = 1;
+    // Tell children to show() their widgets
+    for ( int t=0; t<_children.total(); t++ ) {
+        _children[t]->show_widgets();
+    }
+}
+
+/// Close this item and all its children.
+void Fl_Tree_Item::close() {
+    _open = 0;
+    // Tell children to hide() their widgets
+    for ( int t=0; t<_children.total(); t++ ) {
+        _children[t]->hide_widgets();
+    }
+}
+
+/// Returns how many levels deep this item is in the hierarchy.
+///
+/// For instance; root has a depth of zero, and its immediate children
+/// would have a depth of 1, and so on.
+///
+int Fl_Tree_Item::depth() const {
+    int count = 0;
+    const Fl_Tree_Item *item = parent();
+    while ( item ) {
+	++count;
+	item = item->parent();
+    }
+    return(count);
+}
+
+/// Return the next item in the tree.
+///
+/// This method can be used to walk the tree forward.
+/// For an example of how to use this method, see Fl_Tree::first().
+/// 
+/// \returns the next item in the tree, or 0 if there's no more items.
+///
+Fl_Tree_Item *Fl_Tree_Item::next() {
+    Fl_Tree_Item *p, *c = this;
+    if ( c->has_children() ) {
+	return(c->child(0));
+    }
+    while ( ( p = c->parent() ) != NULL ) {	// loop upwards through parents
+	int t = p->find_child(c);		// find our position in parent's children[] array
+	if ( ++t < p->children() )		// not last child?
+	    return(p->child(t));		// return next child
+	c = p;					// child becomes parent to move up generation
+    }						// loop: moves up to next parent
+    return(0);					// hit root? done
+}
+
+/// Return the previous item in the tree.
+///
+/// This method can be used to walk the tree backwards.
+/// For an example of how to use this method, see Fl_Tree::last().
+/// 
+/// \returns the previous item in the tree, or 0 if there's no item above this one (hit the root).
+///
+Fl_Tree_Item *Fl_Tree_Item::prev() {
+    Fl_Tree_Item *p=parent();		// start with parent
+    if ( ! p ) return(0);		// hit root? done
+    int t = p->find_child(this);	// find our position in parent's children[] array
+    if ( --t == -1 ) {	 		// are we first child?
+	return(p);			// return immediate parent
+    }
+    p = p->child(t);			// take parent's previous child
+    while ( p->has_children() ) {	// has children?
+	p = p->child(p->children()-1);	// take last child
+    }
+    return(p);
+}
diff --git a/contrib/Fl_Tree/Fl_Tree_Item_Array.cxx b/contrib/Fl_Tree/Fl_Tree_Item_Array.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..eacc3abe59129f80428f468fa31b5868329fe566
--- /dev/null
+++ b/contrib/Fl_Tree/Fl_Tree_Item_Array.cxx
@@ -0,0 +1,149 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <FL/Fl_Tree_Item_Array.H>
+#include <FL/Fl_Tree_Item.H>
+
+//////////////////////
+// Fl_Tree_Item_Array.cxx
+//////////////////////
+//
+// Fl_Tree -- This file is part of the Fl_Tree widget for FLTK
+// Copyright (C) 2009 by Greg Ercolano.
+//
+// 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.
+//
+
+/// Constructor; creates an empty array.
+///
+///     The optional 'chunksize' can be specified to optimize
+///     memory allocation for potentially large arrays. Default chunksize is 10.
+/// 
+Fl_Tree_Item_Array::Fl_Tree_Item_Array(int new_chunksize) {
+    _items     = 0;
+    _total     = 0;
+    _size      = 0;
+    _chunksize = new_chunksize;
+}
+
+/// Destructor. Calls each item's destructor, destroys internal _items array.
+Fl_Tree_Item_Array::~Fl_Tree_Item_Array() {
+    clear();
+}
+
+/// Copy constructor. Makes new copy of array, with new instances of each item.
+Fl_Tree_Item_Array::Fl_Tree_Item_Array(const Fl_Tree_Item_Array* o) {
+    _items = (Fl_Tree_Item**)malloc(o->_size * sizeof(Fl_Tree_Item*));
+    _total     = o->_total;
+    _size      = o->_size;
+    _chunksize = o->_chunksize;
+    for ( int t=0; t<o->_total; t++ ) {
+        _items[t] = new Fl_Tree_Item(o->_items[t]);
+    }
+}
+
+/// Clear the entire array.
+///
+///     Each item will be deleted (destructors will be called),
+///     and the array will be cleared. total() will return 0.
+///
+void Fl_Tree_Item_Array::clear() {
+    if ( _items ) {
+	for ( int t=0; t<_total; t++ ) {
+	    delete _items[t];
+	    _items[t] = 0;
+	}
+	free((void*)_items); _items = 0;
+    }
+    _total = _size = 0;
+}
+
+// Internal: Enlarge the items array.
+//
+//    Adjusts size/items memory allocation as needed.
+//    Does NOT change total.
+//
+void Fl_Tree_Item_Array::enlarge(int count) {
+    int newtotal = _total + count;	// new total
+    if ( newtotal >= _size ) {		// more than we have allocated?
+	// Increase size of array
+	int newsize = _size + _chunksize;
+	Fl_Tree_Item **newitems = (Fl_Tree_Item**)malloc(newsize * sizeof(Fl_Tree_Item*));
+	if ( _items ) { 
+	    // Copy old array -> new, delete old
+	    memmove(newitems, _items, _size * sizeof(Fl_Tree_Item*));
+	    free((void*)_items); _items = 0;
+	}
+	// Adjust items/sizeitems
+	_items = newitems;
+	_size = newsize;
+    }
+}
+
+/// Insert an item at index position \p pos.
+///
+///     Handles enlarging array if needed, total increased by 1.
+///     If \p pos == total(), an empty item is appended to the array.
+///
+void Fl_Tree_Item_Array::insert(int pos, Fl_Tree_Item *new_item) {
+    enlarge(1);
+    // printf("*** POS=%d TOTAL-1=%d NITEMS=%d\n", pos, _total-1, (_total-pos));
+    if ( pos <= (_total - 1) ) {	// need to move memory around?
+	int nitems = _total - pos;
+	memmove(&_items[pos+1], &_items[pos], sizeof(Fl_Tree_Item*) * nitems);
+    } 
+    _items[pos] = new_item;
+    _total++;
+}
+
+/// Add an item* to the end of the array.
+///
+///     Assumes the item was created with 'new', and will remain
+///     allocated.. Fl_Tree_Item_Array will handle calling the
+///     item's destructor when the array is cleared or the item remove()'ed.
+///
+void Fl_Tree_Item_Array::add(Fl_Tree_Item *val) {
+    insert(_total, val);
+}
+
+/// Remove the item at \param[in] index from the array.
+///
+///     The item will be delete'd (if non-NULL), so its destructor will be called.
+///
+void Fl_Tree_Item_Array::remove(int index) {
+    if ( _items[index] ) {		// delete if non-zero
+        delete _items[index];
+    }
+    _items[index] = 0;
+    for ( _total--; index<_total; index++ ) {
+        _items[index] = _items[index+1];
+    }
+}
+
+/// Remove the item from the array.
+///
+///     \returns 0 if removed, or -1 if the item was not in the array.
+///
+int Fl_Tree_Item_Array::remove(Fl_Tree_Item *item) {
+    for ( int t=0; t<_total; t++ ) {
+        if ( item == _items[t] ) {
+	    remove(t);
+	    return(0);
+	}
+    }
+    return(-1);
+}
diff --git a/contrib/Fl_Tree/Fl_Tree_Prefs.cxx b/contrib/Fl_Tree/Fl_Tree_Prefs.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..04b39f645e647cd815dbea845093a26af7fe3bfb
--- /dev/null
+++ b/contrib/Fl_Tree/Fl_Tree_Prefs.cxx
@@ -0,0 +1,121 @@
+#include <string.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Pixmap.H>
+#include <FL/Fl_Tree_Prefs.H>
+
+//////////////////////
+// Fl_Tree_Prefs.cxx
+//////////////////////
+//
+// Fl_Tree -- This file is part of the Fl_Tree widget for FLTK
+// Copyright (C) 2009 by Greg Ercolano.
+//
+// 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.
+//
+
+// INTERNAL: BUILT IN OPEN/STOW XPMS
+//    These can be replaced via prefs.openicon()/closeicon()
+//
+static const char *L_open_xpm[] = {
+    "11 11 3 1",
+    ".	c #fefefe",
+    "#	c #444444",
+    "@	c #000000",
+    "###########",
+    "#.........#",
+    "#.........#",
+    "#....@....#",
+    "#....@....#",
+    "#..@@@@@..#",
+    "#....@....#",
+    "#....@....#",
+    "#.........#",
+    "#.........#",
+    "###########"};
+static Fl_Pixmap L_openpixmap(L_open_xpm);
+
+static const char *L_close_xpm[] = {
+    "11 11 3 1",
+    ".	c #fefefe",
+    "#	c #444444",
+    "@	c #000000",
+    "###########",
+    "#.........#",
+    "#.........#",
+    "#.........#",
+    "#.........#",
+    "#..@@@@@..#",
+    "#.........#",
+    "#.........#",
+    "#.........#",
+    "#.........#",
+    "###########"};
+static Fl_Pixmap L_closepixmap(L_close_xpm);
+
+/// Sets the default icon to be used as the 'open' icon
+/// when items are add()ed to the tree.
+/// This overrides the built in default '[+]' icon.
+///
+/// \param[in] val -- The new pixmap, or zero to use the default [+] icon.
+///
+void Fl_Tree_Prefs::openicon(Fl_Pixmap *val) {
+    _openpixmap = val ? val : &L_openpixmap;
+}
+
+/// Sets the icon to be used as the 'close' icon.
+/// This overrides the built in default '[-]' icon.
+///
+/// \param[in] val -- The new pixmap, or zero to use the default [-] icon.
+///
+void Fl_Tree_Prefs::closeicon(Fl_Pixmap *val) {
+    _closepixmap = val ? val : &L_closepixmap;
+}
+
+/// Fl_Tree_Prefs constructor
+Fl_Tree_Prefs::Fl_Tree_Prefs() {
+    _labelfont          = FL_HELVETICA;
+    _labelsize          = FL_NORMAL_SIZE;
+    _marginleft         = 6;
+    _margintop          = 3;
+    //_marginright      = 3;
+    //_marginbottom     = 3;
+    _usericonmarginleft = 3;
+    _labelmarginleft    = 3;
+    _linespacing        = 0;
+    _fgcolor            = FL_BLACK;
+    _bgcolor            = FL_WHITE;
+    _selectcolor        = FL_DARK_BLUE;
+    _inactivecolor      = FL_GRAY;
+    _connectorcolor     = Fl_Color(43);
+    _connectorstyle     = FL_TREE_CONNECTOR_DOTTED;
+    _openpixmap         = &L_openpixmap;
+    _closepixmap        = &L_closepixmap;
+    _userpixmap         = 0;
+    _showcollapse       = 1;
+    _showroot           = 1;
+    _connectorwidth     = 17;
+    _sortorder          = FL_TREE_SORT_NONE;
+    _selectbox          = FL_FLAT_BOX;
+    _selectmode         = FL_TREE_SELECT_SINGLE;
+    // Let fltk's current 'scheme' affect defaults
+    if ( Fl::scheme() ) {
+	if ( strcmp(Fl::scheme(), "gtk+") == 0 ) {
+	    _selectbox = _FL_GTK_THIN_UP_BOX;
+	} else if ( strcmp(Fl::scheme(), "plastic") == 0 ) {
+	    _selectbox = _FL_PLASTIC_THIN_UP_BOX;
+	}
+    }
+}
diff --git a/contrib/Fl_Tree/README.txt b/contrib/Fl_Tree/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..11e93a406035ccede01fc868b7649be87c3d344a
--- /dev/null
+++ b/contrib/Fl_Tree/README.txt
@@ -0,0 +1,56 @@
+
+This is a slightly modified version of the Fl_Tree widget for
+Gmsh. The following modifications (marked with "GMSH" in the source
+code) were applied:
+
+  - added userdata() membre to Fl_Tree_Item so we can store user data
+    in each node
+
+
+Fl_Tree -- FLTK 'Tree' Widget
+------------------------------------
+
+WHAT IS "Fl_Tree"?
+
+    Fl_Tree is a 'tree' widget aimed at becoming part of the FLTK's core,
+    or fltk extensions library.
+
+LICENSING
+
+    Fl_Tree comes with complete free source code. 
+    Fl_Tree is available under the terms of the GNU Library 
+    General Public License. See COPYING for more info.
+
+    Contrary to popular belief, it can be used in commercial
+    software!
+
+BUILD INSTRUCTIONS
+
+    Tested under Linux and Mac OSX with fltk 1.1.9.
+    (TBD: Windows, though will probably compile+run OK)
+
+    To build the test programs and related Fl_Tree object files:
+
+	make
+
+   These test programs are created:
+
+       	test-simple   -- Simple example of how to use the Fl_Tree widget
+	test-Fl_Tree  -- Exerciser app to test Fl_Tree's features
+
+WHERE'S THE DOCUMENTATION?
+
+    See documentation/html/index.html
+
+    The docs are in ./documentation/html and are doxyen based
+    (comments in code), and can be re-generated by running 
+    'make docs' or by simply running 'doxygen' while in ./documentation.
+
+
+RELEASE NOTES/VERSION INFORMATION
+    
+    See ./CHANGES
+
+BUGS?
+    
+    Send them to erco at seriss dot com
diff --git a/contrib/MathEval/README.txt b/contrib/MathEval/README.txt
deleted file mode 100644
index df2d15a954d1895147854aca7f57e85ea9f20cec..0000000000000000000000000000000000000000
--- a/contrib/MathEval/README.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-This directory contains a (heavily) modified version of GNU
-libmatheval.
-
-GNU libmatheval is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2, or (at
-your option) any later version.
-
-The original libmatheval is Copyright (C) 1999, 2002, 2003 Aleksandar
-B. Samardzic
-
-Copying and distribution of this file, with or without modification, are
-permitted in any medium without royalty provided the copyright notice
-and this notice are preserved.
-
-WHAT IS IT?
-
-GNU libmatheval is a library which contains several procedures that make
-it possible to create an in-memory tree from the string representation
-of a mathematical function over single or multiple variables. This tree
-can be used later to evaluate a function for specified variable values,
-to create a corresponding tree for the function derivative over a
-specified variable, or to write a textual tree representation to a
-specified string. 
-
-BUGS
-
-Please report bugs and eventually send patches to
-<bug-libmatheval@gnu.org> mailing list.
diff --git a/contrib/MathEval/common.h b/contrib/MathEval/common.h
deleted file mode 100644
index e7755a0db2aed4c44a888ba7993c8bec231dcd0c..0000000000000000000000000000000000000000
--- a/contrib/MathEval/common.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 1999, 2002, 2003  Free Software Foundation, Inc.
- * 
- * This file is part of GNU libmatheval
- * 
- * GNU libmatheval is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2, or (at your option) any later
- * version.
- * 
- * GNU libmatheval is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef COMMON_H
-#define COMMON_H
-
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "MallocUtils.h"
-
-/* Macro definitions to simplify corresponding function calls.  */
-#define XMALLOC(type, num) ((type *) Malloc ((num) * sizeof(type)))
-#define XREALLOC(type, p, num) ((type *) Realloc ((p), (num) * sizeof(type)))
-#define XCALLOC(type, num) ((type *) Calloc ((num), sizeof(type)))
-#define XFREE(stale) Free (stale);
-
-#endif
diff --git a/contrib/MathEval/matheval.cpp b/contrib/MathEval/matheval.cpp
deleted file mode 100644
index ef14c6d451d52e21417158dc95c23a9ad145e980..0000000000000000000000000000000000000000
--- a/contrib/MathEval/matheval.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright (C) 1999, 2002, 2003  Free Software Foundation, Inc.
- *
- * This file is part of GNU libmatheval
- *
- * GNU libmatheval is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2, or (at your option) any later
- * version.
- *
- * GNU libmatheval is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* This file was modified for inclusion in Gmsh */
-
-#include "common.h"
-#include "matheval.h"
-#include "node.h"
-#include "symbol_table.h"
-
-/* Minimal length of evaluator symbol table.  */
-#define MIN_TABLE_LENGTH 211
-
-/*
- * Function used to parse string representing function (this function is
- * generated by parser generator).
- */
-extern int meparse();
-
-/*
- * Following variables are needed for parsing (parser is able to communicate
- * with program from which it is used through global variables only).
- */
-char           *matheval_input_string;	/* String representing function.  */
-Node           *matheval_root;		/* Root of tree representation of
-					 * function.  */
-SymbolTable    *matheval_symbol_table;	/* Evaluator symbol table.  */
-int             matheval_ok;		/* Flag determining if parsing went OK.  */
-
-/* Data structure representing evaluator.  */
-typedef struct {
-  Node           *root;	/* Root of tree representation of
-			 * function.  */
-  SymbolTable    *symbol_table;	/* Evalutor symbol table.  */
-	char **names;
-	int count;
-} Evaluator;
-
-void *
-evaluator_create(char *string)
-{
-  Evaluator      *evaluator;	/* Evaluator representing function given
-				 * by string.  */
-  char           *stringn;	/* Copy of string terminated by newline
-				 * character.  */
-  
-  /*
-   * Copy string representing function and terminate it with newline
-   * (this is necessary because parser expect newline character to
-   * terminate its input).
-   */
-  stringn = XMALLOC(char, strlen(string) + 2);
-  
-  strcpy(stringn, string);
-  strcat(stringn, "\n");
-  
-  /*
-   * Initialize global variables used by parser.
-   */
-  matheval_input_string = stringn;
-  matheval_root = NULL;
-  matheval_symbol_table = symbol_table_create(MIN_TABLE_LENGTH);
-  matheval_ok = 1;
-  
-  /*
-   * Do parsing.
-   */
-  meparse();
-  
-  /*
-   * Free copy of string representing function.
-   */
-  XFREE(stringn);
-  
-  /*
-   * Return null pointer as error indicator if parsing error occured.
-   */
-  if (!matheval_ok || !matheval_root){
-    node_destroy(matheval_root);
-    symbol_table_destroy(matheval_symbol_table);
-    return NULL;
-  }
-  
-  /*
-   * Simplify tree represention of function.
-   */
-  matheval_root = node_simplify(matheval_root);
-  
-  /*
-   * Allocate memory for and initialize evaluator data structure.
-   */
-  evaluator = XMALLOC(Evaluator, 1);
-  evaluator->root = matheval_root;
-  evaluator->symbol_table = matheval_symbol_table;
-	evaluator->count=0;
-	evaluator->names=NULL;
-  
-  return evaluator;
-}
-
-void
-evaluator_destroy(void *evaluator)
-{
-  /*
-   * Destroy tree represention of function, symbol table, as well as
-   * data structure representing evaluator.
-   */
-  node_destroy(((Evaluator *) evaluator)->root);
-  symbol_table_destroy(((Evaluator *) evaluator)->symbol_table);
-	XFREE(((Evaluator *) evaluator)->names);
-  XFREE(evaluator);
-}
-
-double
-evaluator_evaluate(void *evaluator, int count, char **names, double *values)
-{
-  Record         *record;	/* Symbol table record corresponding to
-				 * give variable name.  */
-  int             i;		/* Loop counter.  */
-  
-  /*
-   * Assign values to symbol table records corresponding to variable
-   * names.
-   */
-  for (i = 0; i < count; i++) {
-    record = symbol_table_lookup(((Evaluator *) evaluator)->symbol_table, names[i]);
-    if (record && record->type == 'v')
-      record->data.value = values[i];
-  }
-  
-  /*
-   * Evaluate function value using tree represention of function.
-   */
-  return node_evaluate(((Evaluator *) evaluator)->root);
-}
-
-int
-evaluator_calculate_length(void *evaluator)
-{
-  /*
-   * Calculate length of evaluator textual representation.
-   */
-  return node_calculate_length(((Evaluator *) evaluator)->root);
-}
-
-void
-evaluator_write(void *evaluator, char *string)
-{
-  /*
-   * Write evaluator textual representation to given string.
-   */
-  node_write(((Evaluator *) evaluator)->root, string);
-}
-
-void *
-evaluator_derivative(void *evaluator, char *name)
-{
-  Evaluator      *derivative;	/* Derivative function evaluator.  */
-  
-  /*
-   * Allocate memory for and initalize data structure for evaluator
-   * representing derivative of function given by evaluator.
-   */
-  derivative = XMALLOC(Evaluator, 1);
-  derivative->root = node_simplify(node_derivative(((Evaluator *) evaluator)->root, name,
-						   ((Evaluator *) evaluator)->symbol_table));
-  derivative->symbol_table = symbol_table_assign(((Evaluator *) evaluator)->symbol_table);
-	derivative->count=0;
-	derivative->names=NULL;
-  
-  return derivative;
-}
-
-double
-evaluator_evaluate_x(void *evaluator, double x)
-{
-  char           *names[] = {"x"};	/* Array of variable names.  */
-  double          values[] = {x};	/* Array of variable values.  */
-  
-  /*
-   * Evaluate function for given values of variable "x".
-   */
-  return evaluator_evaluate(evaluator, sizeof(names) / sizeof(names[0]), names, values);
-}
-
-double
-evaluator_evaluate_x_y(void *evaluator, double x, double y)
-{
-  char           *names[] = {"x", "y"};	/* Array of variable
-					 * names.  */
-  double          values[] = {x, y};	/* Array of variable values.  */
-  
-  /*
-   * Evaluate function for given values of variable "x" and "y".
-   */
-  return evaluator_evaluate(evaluator, sizeof(names) / sizeof(names[0]), names, values);
-}
-
-double
-evaluator_evaluate_x_y_z(void *evaluator, double x, double y, double z)
-{
-  char           *names[] = {"x", "y", "z"};	/* Array of variable
-						 * names.  */
-  double          values[] = {x, y, z};	/* Array of variable
-					 * values.  */
-  
-  /*
-   * Evaluate function for given values of variable "x", "y" and "z".
-   */
-  return evaluator_evaluate(evaluator, sizeof(names) / sizeof(names[0]), names, values);
-}
-
-void *
-evaluator_derivative_x(void *evaluator)
-{
-  /*
-   * Differentiate function using derivation variable "x".
-   */
-  return evaluator_derivative(evaluator, "x");
-}
-
-void *
-evaluator_derivative_y(void *evaluator)
-{
-  /*
-   * Differentiate function using derivation variable "y".
-   */
-  return evaluator_derivative(evaluator, "y");
-}
-
-void *
-evaluator_derivative_z(void *evaluator)
-{
-  /*
-   * Differentiate function using derivation variable "z".
-   */
-  return evaluator_derivative(evaluator, "z");
-}
-
-void
-evaluator_get_variables(void *evaluator, char ***names, int *count)
-{
-	Record        **records;	/* Array of symbol table records
-					 * containing evaluator variables. 
-					 */
-	int             i;	/* Loop counter.  */
-
-	/* If not already, find and remember evaluator variable names. */
-	if (!((Evaluator *) evaluator)->names) {
-		symbol_table_clear_flags(((Evaluator *) evaluator)->
-					 symbol_table);
-		node_flag_variables(((Evaluator *) evaluator)->root);
-		((Evaluator *) evaluator)->count =
-		    symbol_table_get_flagged_count(((Evaluator *)
-						    evaluator)->
-						   symbol_table);
-		records =
-		    XMALLOC(Record *, ((Evaluator *) evaluator)->count);
-		symbol_table_get_flagged(((Evaluator *) evaluator)->
-					 symbol_table, records,
-					 ((Evaluator *) evaluator)->count);
-		((Evaluator *) evaluator)->names =
-		    XMALLOC(char *, ((Evaluator *) evaluator)->count);
-		for (i = 0; i < ((Evaluator *) evaluator)->count; i++)
-			((Evaluator *) evaluator)->names[i] =
-			    records[i]->name;
-		XFREE(records);
-	}
-
-	/* Return requested information. */
-	*count = ((Evaluator *) evaluator)->count;
-	*names = ((Evaluator *) evaluator)->names;
-}
diff --git a/contrib/MathEval/matheval.h b/contrib/MathEval/matheval.h
deleted file mode 100644
index cb4a639423479369985472e4d21d37a11d8bbc28..0000000000000000000000000000000000000000
--- a/contrib/MathEval/matheval.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 1999, 2002, 2003  Free Software Foundation, Inc.
- * 
- * This file is part of GNU libmatheval
- * 
- * GNU libmatheval is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2, or (at your option) any later
- * version.
- * 
- * GNU libmatheval is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* This file was modified for inclusion in Gmsh */
-
-#ifndef EVALUATOR_H
-#define EVALUATOR_H
-
-/*
- * Create evaluator from string representing function.  Function
- * returns pointer that should be passed as first argument to all
- * other library functions.  If an error occurs, function will return
- * null pointer.
- */
-void    *evaluator_create(char *string);
-
-/*
- * Destroy evaluator specified.
- */
-void     evaluator_destroy(void *evaluator);
-
-/*
- * Evaluate function represented by evaluator given.  Variable names
- * and respective values are represented by function third and fourth
- * argument. Number of variables i.e. length of these two arrays is
- * given by second argument.  Function returns evaluated function
- * value.  In case that function contains variables with names not
- * given through third function argument, value of this variable is
- * undeterminated.
- */
-double   evaluator_evaluate(void *evaluator, int count, char **names, double *values);
-
-/*
- * Calculate length of textual representation of evaluator. This
- * procedure is inteded to be used along with evaluator_write()
- * procedure that follows.
- */
-int      evaluator_calculate_length(void *evaluator);
-
-/*
- * Write textual representation of evaluator (i.e. corresponding
- * function) to given string.  No string overflow is checked by this
- * procedure; string of appropriate length (calculated beforehand
- * using above evaluator_calculate_length() procedure) is expected to
- * be allocated beforehand.
- */
-void     evaluator_write(void *evaluator, char *length);
-
-/*
- * Create evaluator for first derivative of function represented by
- * evaluator given as first argument using derivative variable given
- * as second argument.
- */
-void    *evaluator_derivative(void *evaluator, char *name);
-
-/*
- * Helper functions to simplify evaluation when variable names are
- * "x", "x" and "y" or "x" and "y" and "z" respectively.
- */
-double   evaluator_evaluate_x(void *evaluator, double x);
-double   evaluator_evaluate_x_y(void *evaluator, double x, double y);
-double   evaluator_evaluate_x_y_z(void *evaluator, double x, double y, double z);
-
-/*
- * Helper functions to simplify differentiation when variable names
- * are "x" or "y" or "z" respectively.
- */
-void    *evaluator_derivative_x(void *evaluator);
-void    *evaluator_derivative_y(void *evaluator);
-void    *evaluator_derivative_z(void *evaluator);
-
-/* Get array of strings with names of variables appearing in
- * function represented by given evaluator.  Only variables
- * referenced by evaluator after simplification are returned.
- * Address of first string in array is stored into location
- * pointed by function second argument.  Number of array elements
- * is stored into location pointed by third argument.  Array is
- * allocated, remembered and later destroyed by evaluator object,
- * thus caller must not free any of string nor array itself.
- * Returned information is valid until evaluator object destroyed. 
- */
-extern void     evaluator_get_variables(void *evaluator,
-					char ***names, int *count);
-
-#endif
diff --git a/contrib/MathEval/node.cpp b/contrib/MathEval/node.cpp
deleted file mode 100644
index 5d7bc033af63bda830f977a520c46309988b8d5d..0000000000000000000000000000000000000000
--- a/contrib/MathEval/node.cpp
+++ /dev/null
@@ -1,720 +0,0 @@
-/*
- * Copyright (C) 1999, 2002, 2003  Free Software Foundation, Inc.
- *
- * This file is part of GNU libmatheval
- *
- * GNU libmatheval is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2, or (at your option) any later
- * version.
- *
- * GNU libmatheval is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <assert.h>
-#include <stdarg.h>
-#include "common.h"
-#include "node.h"
-
-Node *
-node_create(char type,...)
-{
-  Node           *node;	/* New node.  */
-  va_list         ap;		/* Variable argument list.  */
-  
-  /*
-   * Allocate memory for node and initialize its type.
-   */
-  node = XMALLOC(Node, 1);
-  node->type = type;
-  
-  /*
-   * According to node type, initialize rest of the node from variable
-   * argument list.
-   */
-  va_start(ap, type);
-  switch (node->type) {
-  case 'c':
-    /*
-     * Initialize constant value.
-     */
-    node->data.constant = va_arg(ap, double);
-    break;
-    
-  case 'v':
-    /*
-     * Remember pointer to symbol table record describing
-     * variable.
-     */
-    node->data.variable = va_arg(ap, Record *);
-    break;
-    
-  case 'f':
-    /*
-     * Remember pointer to symbol table record describing
-     * function and initialize function argument.
-     */
-    node->data.function.record = va_arg(ap, Record *);
-    node->data.function.child = va_arg(ap, Node *);
-    break;
-    
-  case 'u':
-    /*
-     * Initialize operator type and operand.
-     */
-    node->data.un_op.operatorr = (char) va_arg(ap, int);
-    node->data.un_op.child = va_arg(ap, Node *);
-    break;
-    
-  case 'b':
-    /*
-     * Initialize operator type and operands.
-     */
-    node->data.un_op.operatorr = (char) va_arg(ap, int);
-    node->data.bin_op.left = va_arg(ap, Node *);
-    node->data.bin_op.right = va_arg(ap, Node *);
-    break;
-    
-  default:
-    assert(0);
-  }
-  va_end(ap);
-  
-  return node;
-}
-
-void
-node_destroy(Node * node)
-{
-  /*
-   * Skip if node already null (this may occur during simplification).
-   */
-  if (!node)
-    return;
-  
-  /*
-   * If necessary, destroy subtree rooted at node.
-   */
-  switch (node->type) {
-  case 'c':
-  case 'v':
-    break;
-    
-  case 'f':
-    node_destroy(node->data.function.child);
-    break;
-    
-  case 'u':
-    node_destroy(node->data.un_op.child);
-    break;
-    
-  case 'b':
-    node_destroy(node->data.bin_op.left);
-    node_destroy(node->data.bin_op.right);
-    break;
-  }
-  
-  /*
-   * Deallocate memory used by node.
-   */
-  XFREE(node);
-}
-
-Node *
-node_copy(Node * node)
-{
-  /*
-   * According to node type, create (deep) copy of subtree rooted at
-   * node.
-   */
-  switch (node->type) {
-  case 'c':
-    return node_create('c', node->data.constant);
-    
-  case 'v':
-    return node_create('v', node->data.variable);
-    
-  case 'f':
-    return node_create('f', node->data.function.record, node_copy(node->data.function.child));
-    
-  case 'u':
-    return node_create('u', node->data.un_op.operatorr, node_copy(node->data.un_op.child));
-    
-  case 'b':
-    return node_create('b', node->data.bin_op.operatorr, node_copy(node->data.bin_op.left), node_copy(node->data.bin_op.right));
-  }
-  
-  return NULL;
-}
-
-Node *
-node_simplify(Node * node)
-{
-  /*
-   * According to node type, apply further simplifications.
-   */
-  switch (node->type) {
-  case 'c':
-  case 'v':
-    return node;
-    
-  case 'f':
-    /*
-     * Simplify function argument and if constant evaluate function
-     * and replace function node with constant node (unless the
-     * function is Rand(x)).
-     */
-    node->data.function.child = node_simplify(node->data.function.child);
-    if (node->data.function.child->type == 'c' && 
-	strcmp(node->data.function.record->name, "Rand")) {
-      double          value = node_evaluate(node);
-      
-      node_destroy(node);
-      return node_create('c', value);
-    }
-    else
-      return node;
-    
-  case 'u':
-    /*
-     * Simplify unary operator operand and if constant apply
-     * operator and replace operator node with constant node.
-     */
-    node->data.un_op.child = node_simplify(node->data.un_op.child);
-    if (node->data.un_op.operatorr == '-' && node->data.un_op.child->type == 'c') {
-      double          value = node_evaluate(node);
-      
-      node_destroy(node);
-      return node_create('c', value);
-    } 
-    else
-      return node;
-    
-  case 'b':
-    /*
-     * Simplify binary operator operands.
-     */
-    node->data.bin_op.left = node_simplify(node->data.bin_op.left);
-    node->data.bin_op.right = node_simplify(node->data.bin_op.right);
-    
-    /*
-     * If operands constant apply operator and replace operator
-     * node with constant node.
-     */
-    if (node->data.bin_op.left->type == 'c' && node->data.bin_op.right->type == 'c') {
-      double          value = node_evaluate(node);
-      
-      node_destroy(node);
-      return node_create('c', value);
-    }
-    /*
-     * Eliminate 0 as neutral addition operand.
-     */
-    else if (node->data.bin_op.operatorr == '+')
-      if (node->data.bin_op.left->type == 'c' && node->data.bin_op.left->data.constant == 0) {
-	Node *right;
-	right = node->data.bin_op.right;
-	node->data.bin_op.right = NULL;
-	node_destroy(node);
-	return right;
-      } 
-      else if (node->data.bin_op.right->type == 'c' && node->data.bin_op.right->data.constant == 0) {
-	Node *left;
-	left = node->data.bin_op.left;
-	node->data.bin_op.left = NULL;
-	node_destroy(node);
-	return left;
-      }
-      else
-	return node;
-    /*
-     * Eliminate 0 as neutral subtraction right operand.
-     */
-    else if (node->data.bin_op.operatorr == '-')
-      if (node->data.bin_op.right->type == 'c' && node->data.bin_op.right->data.constant == 0) {
-	Node *left;
-	left = node->data.bin_op.left;
-	node->data.bin_op.left = NULL;
-	node_destroy(node);
-	return left;
-      }
-      else
-	return node;
-    /*
-     * Eliminate 1 as neutral multiplication operand.
-     */
-    else if (node->data.bin_op.operatorr == '*')
-      if (node->data.bin_op.left->type == 'c' && node->data.bin_op.left->data.constant == 1) {
-	Node *right;
-	right = node->data.bin_op.right;
-	node->data.bin_op.right = NULL;
-	node_destroy(node);
-	return right;
-      } 
-      else if (node->data.bin_op.right->type == 'c' && node->data.bin_op.right->data.constant == 1) {
-	Node *left;
-	left = node->data.bin_op.left;
-	node->data.bin_op.left = NULL;
-	node_destroy(node);
-	return left;
-      }
-      else
-	return node;
-    /*
-     * Eliminate 1 as neutral division right operand.
-     */
-    else if (node->data.bin_op.operatorr == '/')
-      if (node->data.bin_op.right->type == 'c' && node->data.bin_op.right->data.constant == 1) {
-	Node *left;
-	left = node->data.bin_op.left;
-	node->data.bin_op.left = NULL;
-	node_destroy(node);
-	return left;
-      }
-      else
-	return node;
-    /*
-     * Eliminate 0 and 1 as both left and right exponentiation
-     * operands.
-     */
-    else if (node->data.bin_op.operatorr == '^')
-      if (node->data.bin_op.left->type == 'c' && node->data.bin_op.left->data.constant == 0) {
-	node_destroy(node);
-	return node_create('c', 0.0);
-      } 
-      else if (node->data.bin_op.left->type == 'c' && node->data.bin_op.left->data.constant == 1) {
-	node_destroy(node);
-	return node_create('c', 1.0);
-      }
-      else if (node->data.bin_op.right->type == 'c' && node->data.bin_op.right->data.constant == 0) {
-	node_destroy(node);
-	return node_create('c', 1.0);
-      }
-      else if (node->data.bin_op.right->type == 'c' && node->data.bin_op.right->data.constant == 1) {
-	Node *left;
-	left = node->data.bin_op.left;
-	node->data.bin_op.left = NULL;
-	node_destroy(node);
-	return left;
-      }
-      else
-	return node;
-    else
-      return node;
-  }
-  
-  return NULL;
-}
-
-double
-node_evaluate(Node * node)
-{
-  /*
-   * According to node type, evaluate subtree rooted at node.
-   */
-  switch (node->type) {
-  case 'c':
-    return node->data.constant;
-    
-  case 'v':
-    /*
-     * Variable values are used from symbol table.
-     */
-    return node->data.variable->data.value;
-    
-  case 'f':
-    /*
-     * Functions are evaluated through symbol table.
-     */
-    return (*node->data.function.record->data.function) (node_evaluate(node->data.function.child));
-    
-  case 'u':
-    /*
-     * Unary operator node is evaluated according to operator
-     * type.
-     */
-    switch (node->data.un_op.operatorr) {
-    case '-':
-      return -node_evaluate(node->data.un_op.child);
-    }
-    
-  case 'b':
-    /*
-     * Binary operator node is evaluated according to operator
-     * type.
-     */
-    switch (node->data.un_op.operatorr) {
-    case '+':
-      return node_evaluate(node->data.bin_op.left) + node_evaluate(node->data.bin_op.right);
-      
-    case '-':
-      return node_evaluate(node->data.bin_op.left) - node_evaluate(node->data.bin_op.right);
-      
-    case '*':
-      return node_evaluate(node->data.bin_op.left) * node_evaluate(node->data.bin_op.right);
-      
-    case '/':
-      return node_evaluate(node->data.bin_op.left) / node_evaluate(node->data.bin_op.right);
-      
-    case '^':
-      return pow(node_evaluate(node->data.bin_op.left), node_evaluate(node->data.bin_op.right));
-    }
-  }
-  
-  return 0;
-}
-
-Node *
-node_derivative(Node * node, char *name, SymbolTable * symbol_table)
-{
-  /*
-   * According to node type, derivative tree for subtree rooted at node
-   * is created.
-   */
-  switch (node->type) {
-  case 'c':
-    /*
-     * Derivative of constant equals 0.
-     */
-    return node_create('c', 0.0);
-    
-  case 'v':
-    /*
-     * Derivative of variable equals 1 if variable is derivative
-     * variable, 0 otherwise.
-     */
-    return node_create('c', (!strcmp(name, node->data.variable->name)) ? 1.0 : 0.0);
-    
-  case 'f':
-    /*
-     * Apply rule of exponential function derivative.
-     */
-    if (!strcmp(node->data.function.record->name, "Exp"))
-      return node_create('b', '*', node_derivative(node->data.function.child, name, symbol_table), node_copy(node));
-    /*
-     * Apply rule of logarithmic function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Log"))
-      return node_create('b', '/', node_derivative(node->data.function.child, name, symbol_table), node_copy(node->data.function.child));
-    /*
-     * Apply rule of base 10 logarithmic function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Log10"))
-      return node_create('b', '/', node_derivative(node->data.function.child, name, symbol_table), 
-			 node_create('b', '*', node_create('c', log(10.)), node_copy(node->data.function.child)));
-    /*
-     * Apply rule of square root function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Sqrt"))
-      return node_create('b', '/', node_derivative(node->data.function.child, name, symbol_table), node_create('b', '*', node_create('c', 2.0), node_copy(node)));
-    /*
-     * Apply rule of sine function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Sin"))
-      return node_create('b', '*', node_derivative(node->data.function.child, name, symbol_table), node_create('f', symbol_table_lookup(symbol_table, "Cos"), node_copy(node->data.function.child)));
-    /*
-     * Apply rule of cosine function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Cos"))
-      return node_create('u', '-', node_create('b', '*', node_derivative(node->data.function.child, name, symbol_table), node_create('f', symbol_table_lookup(symbol_table, "Sin"), node_copy(node->data.function.child))));
-    /*
-     * Apply rule of tangent function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Tan"))
-      return node_create('b', '/', node_derivative(node->data.function.child, name, symbol_table), node_create('b', '^', node_create('f', symbol_table_lookup(symbol_table, "Cos"), node_copy(node->data.function.child)), node_create('c', 2.0)));
-    /*
-     * Apply rule of cotangent function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Ctan"))
-      return node_create('u', '-', node_create('b', '/', node_derivative(node->data.function.child, name, symbol_table), node_create('b', '^', node_create('f', symbol_table_lookup(symbol_table, "Sin"), node_copy(node->data.function.child)), node_create('c', 2.0))));
-    /*
-     * Apply rule of inverse sine function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Asin"))
-      return node_create('b', '/', node_derivative(node->data.function.child, name, symbol_table), node_create('f', symbol_table_lookup(symbol_table, "Sqrt"), node_create('b', '-', node_create('c', 1.0), node_create('b', '^', node_copy(node->data.function.child), node_create('c', 2.0)))));
-    /*
-     * Apply rule of inverse cosine function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Acos"))
-      return node_create('u', '-', node_create('b', '/', node_derivative(node->data.function.child, name, symbol_table), node_create('f', symbol_table_lookup(symbol_table, "Sqrt"), node_create('b', '-', node_create('c', 1.0), node_create('b', '^', node_copy(node->data.function.child), node_create('c', 2.0))))));
-    /*
-     * Apply rule of inverse tangent function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Atan"))
-      return node_create('b', '/', node_derivative(node->data.function.child, name, symbol_table), node_create('b', '+', node_create('c', 1.0), node_create('b', '^', node_copy(node->data.function.child), node_create('c', 2.0))));
-    /*
-     * Apply rule of inverse cotanget function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Actan"))
-      return node_create('u', '-', node_create('b', '/', node_derivative(node->data.function.child, name, symbol_table), node_create('b', '+', node_create('c', 1.0), node_create('b', '^', node_copy(node->data.function.child), node_create('c', 2.0)))));
-    /*
-     * Apply rule of hyperbolic sine function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Sinh"))
-      return node_create('b', '*', node_derivative(node->data.function.child, name, symbol_table), node_create('f', symbol_table_lookup(symbol_table, "Cosh"), node_copy(node->data.function.child)));
-    /*
-     * Apply rule of hyperbolic cosine function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Cosh"))
-      return node_create('b', '*', node_derivative(node->data.function.child, name, symbol_table), node_create('f', symbol_table_lookup(symbol_table, "Sinh"), node_copy(node->data.function.child)));
-    /*
-     * Apply rule of hyperbolic tangent function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Tanh"))
-      return node_create('b', '/', node_derivative(node->data.function.child, name, symbol_table), node_create('b', '^', node_create('f', symbol_table_lookup(symbol_table, "Cosh"), node_copy(node->data.function.child)), node_create('c', 2.0)));
-    /*
-     * Apply rule of hyperbolic cotangent function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Ctanh"))
-      return node_create('u', '-', node_create('b', '/', node_derivative(node->data.function.child, name, symbol_table), node_create('b', '^', node_create('f', symbol_table_lookup(symbol_table, "sinh"), node_copy(node->data.function.child)), node_create('c', 2.0))));
-    /*
-     * Apply rule of inverse hyperbolic sine function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Asinh"))
-      return node_create('b', '/', node_derivative(node->data.function.child, name, symbol_table), node_create('f', symbol_table_lookup(symbol_table, "Sqrt"), node_create('b', '-', node_create('c', 1.0), node_create('b', '^', node_copy(node->data.function.child), node_create('c', 2.0)))));
-    /*
-     * Apply rule of inverse hyperbolic cosine function
-     * derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Acosh"))
-      return node_create('b', '/', node_derivative(node->data.function.child, name, symbol_table), node_create('f', symbol_table_lookup(symbol_table, "Sqrt"), node_create('b', '-', node_create('b', '^', node_copy(node->data.function.child), node_create('c', 2.0)), node_create('c', 1.0))));
-    /*
-     * Apply rule of inverse hyperbolic tangent function
-     * derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Atanh"))
-      return node_create('b', '/', node_derivative(node->data.function.child, name, symbol_table), node_create('b', '-', node_create('c', 1.0), node_create('b', '^', node_copy(node->data.function.child), node_create('c', 2.0))));
-    /*
-     * Apply rule of inverse hyperbolic cotangent function
-     * derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Actanh"))
-      return node_create('b', '/', node_derivative(node->data.function.child, name, symbol_table), node_create('b', '-', node_create('b', '^', node_copy(node->data.function.child), node_create('c', 2.0)), node_create('c', 1.0)));
-    /*
-     * Apply rule of absolute value function derivative.
-     */
-    else if (!strcmp(node->data.function.record->name, "Fabs"))
-      return node_create('b', '/', node_create('b', '*', node_derivative(node->data.function.child, name, symbol_table), node_copy(node->data.function.child)), node_create('f', symbol_table_lookup(symbol_table, "Sqrt"), node_create('b', '^', node_copy(node->data.function.child), node_create('c', 2.0))));
-
-     /*
-     * Apply rule of step function derivative. 
-     */
-    else if (!strcmp(node->data.function.record->name, "Step"))
-      return node_create('b', '*',node_derivative(node->data.function.child, name, symbol_table), node_create('f', symbol_table_lookup(symbol_table,"Delta"), node_copy(node->data.function.child)));
-
-    /*
-     * Apply rule of floor function derivative. 
-     */
-    else if (!strcmp(node->data.function.record->name, "Floor"))
-       return node_create('b', '*', node_derivative(node->data.function.child, name, symbol_table), node_create('f',symbol_table_lookup(symbol_table, "Delta"), node_copy(node->data.function.child)));
-
-    /*
-     * Apply rule of smoothed heaviside function derivative. 
-     */
-    else if (!strcmp(node->data.function.record->name, "HeavS")){
-      //printf("********************************  Derivative of smoothed heaviside function not implemented yet, return a Delta function ...");
-      return node_create('b', '*',node_derivative(node->data.function.child, name, symbol_table), node_create('f', symbol_table_lookup(symbol_table,"Delta"), node_copy(node->data.function.child)));
-    }
-
-    /*
-     * Apply rule of delta function derivative. 
-     */
-    else if (!strcmp(node->data.function.record->name, "Delta"))
-      return node_create('b', '*',node_derivative(node->data.function.child, name,symbol_table),node_create('f',symbol_table_lookup(symbol_table, "NanDelta"), node_copy(node->data.function.child)));
-     
-
-    /*
-     * Apply rule of nandelta function derivative. 
-     */
-    else if (!strcmp(node->data.function.record->name, "NanDelta"))
-      return node_create('b', '*', node_derivative(node->data.function.child, name, symbol_table), node_create('f',symbol_table_lookup(symbol_table, "NanDelta"), node_copy(node->data.function.child)));
-
-
-
-
-    
-  case 'u':
-    switch (node->data.un_op.operatorr) {
-    case '-':
-      /*
-       * Apply (-f)'=-f' derivative rule.
-       */
-      return node_create('u', '-', node_derivative(node->data.un_op.child, name, symbol_table));
-    }
-    
-  case 'b':
-    switch (node->data.bin_op.operatorr) {
-    case '+':
-      /*
-       * Apply (f+g)'=f'+g' derivative rule.
-       */
-      return node_create('b', '+', node_derivative(node->data.bin_op.left, name, symbol_table), node_derivative(node->data.bin_op.right, name, symbol_table));
-      
-    case '-':
-      /*
-       * Apply (f-g)'=f'-g' derivative rule.
-       */
-      return node_create('b', '-', node_derivative(node->data.bin_op.left, name, symbol_table), node_derivative(node->data.bin_op.right, name, symbol_table));
-      
-    case '*':
-      /*
-       * Apply (f*g)'=f'*g+f*g' derivative rule.
-       */
-      return node_create('b', '+', node_create('b', '*', node_derivative(node->data.bin_op.left, name, symbol_table), node_copy(node->data.bin_op.right)), node_create('b', '*', node_copy(node->data.bin_op.left), node_derivative(node->data.bin_op.right, name, symbol_table)));
-      
-    case '/':
-      /*
-       * Apply (f/g)'=(f'*g-f*g')/g^2 derivative rule.
-       */
-      return node_create('b', '/', node_create('b', '-', node_create('b', '*', node_derivative(node->data.bin_op.left, name, symbol_table), node_copy(node->data.bin_op.right)), node_create('b', '*', node_copy(node->data.bin_op.left), node_derivative(node->data.bin_op.right, name, symbol_table))), node_create('b', '^', node_copy(node->data.bin_op.right), node_create('c', 2.0)));
-      
-    case '^':
-      /*
-       * If right operand of exponentiation constant apply
-       * (f^n)'=n*f^(n-1)*f' derivative rule.
-       */
-      if (node->data.bin_op.right->type == 'c')
-	return node_create('b', '*', node_create('b', '*', node_create('c', node->data.bin_op.right->data.constant), node_derivative(node->data.bin_op.left, name, symbol_table)), node_create('b', '^', node_copy(node->data.bin_op.left), node_create('c', node->data.bin_op.right->data.constant - 1.0)));
-      /*
-       * Otherwise, apply logaritmhic derivative rule:
-       * (log(f^g))'=(f^g)'/f^g =>
-       * (f^g)'=f^g*(log(f^g))'=f^g*(g*log(f))'
-       */
-      else {
-	Node *log_node, *derivative;
-	log_node = node_create('b', '*', node_copy(node->data.bin_op.right), node_create('f', symbol_table_lookup(symbol_table, "Log"), node_copy(node->data.bin_op.left)));
-	derivative = node_create('b', '*', node_copy(node), node_derivative(log_node, name, symbol_table));
-	node_destroy(log_node);
-	return derivative;
-      }
-    }
-  }
-  
-  return NULL;
-}
-
-int
-node_calculate_length(Node * node)
-{
-  char            string[1024];	/* String representing constant node
-				 * value. */
-  int             length;	/* Length of above string. */
-  
-  /*
-   * According to node type, calculate length of string representing
-   * subtree rooted at node.
-   */
-  switch (node->type) {
-  case 'c':
-    length = 0;
-    if (node->data.constant < 0)
-      length += 1;
-    sprintf(string, "%g", node->data.constant);
-    length += strlen(string);
-    if (node->data.constant < 0)
-      length += 1;
-    return length;
-    
-  case 'v':
-    return strlen(node->data.variable->name);
-    
-  case 'f':
-    return strlen(node->data.function.record->name) + 1 + node_calculate_length(node->data.function.child) + 1;
-    break;
-    
-  case 'u':
-    return 1 + 1 + node_calculate_length(node->data.un_op.child) + 1;
-    
-  case 'b':
-    return 1 + node_calculate_length(node->data.bin_op.left) + 1 + node_calculate_length(node->data.bin_op.right) + 1;
-  }
-  
-  return 0;
-}
-
-void
-node_write(Node * node, char *string)
-{
-  /*
-   * According to node type, write subtree rooted at node to node
-   * string variable.  Always use parenthesis to resolve operator
-   * precedence.
-   */
-  switch (node->type) {
-  case 'c':
-    if (node->data.constant < 0) {
-      sprintf(string, "%c", '(');
-      string += strlen(string);
-    }
-    sprintf(string, "%g", node->data.constant);
-    string += strlen(string);
-    if (node->data.constant < 0)
-      sprintf(string, "%c", ')');
-    break;
-    
-  case 'v':
-    sprintf(string, "%s", node->data.variable->name);
-    break;
-    
-  case 'f':
-    sprintf(string, "%s%c", node->data.function.record->name, '(');
-    string += strlen(string);
-    node_write(node->data.function.child, string);
-    string += strlen(string);
-    sprintf(string, "%c", ')');
-    break;
-    
-  case 'u':
-    sprintf(string, "%c", '(');
-    string += strlen(string);
-    sprintf(string, "%c", node->data.un_op.operatorr);
-    string += strlen(string);
-    node_write(node->data.un_op.child, string);
-    string += strlen(string);
-    sprintf(string, "%c", ')');
-    break;
-    
-  case 'b':
-    sprintf(string, "%c", '(');
-    string += strlen(string);
-    node_write(node->data.bin_op.left, string);
-    string += strlen(string);
-    sprintf(string, "%c", node->data.bin_op.operatorr);
-    string += strlen(string);
-    node_write(node->data.bin_op.right, string);
-    string += strlen(string);
-    sprintf(string, "%c", ')');
-    break;
-  }
-}
-void
-node_flag_variables(Node * node)
-{
-	/* According to node type, flag variable in symbol table or
-	 * proceed with calling function recursively on node children. */
-	switch (node->type) {
-	case 'v':
-		node->data.variable->flag = true;
-		break;
-
-	case 'f':
-		node_flag_variables(node->data.function.child);
-		break;
-
-	case 'u':
-		node_flag_variables(node->data.un_op.child);
-		break;
-
-	case 'b':
-		node_flag_variables(node->data.bin_op.left);
-		node_flag_variables(node->data.bin_op.right);
-		break;
-	}
-}
diff --git a/contrib/MathEval/node.h b/contrib/MathEval/node.h
deleted file mode 100644
index 0aee3fd97c7c4eae42adc409406e486bc7f2fb38..0000000000000000000000000000000000000000
--- a/contrib/MathEval/node.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 1999, 2002, 2003  Free Software Foundation, Inc.
- * 
- * This file is part of GNU libmatheval
- * 
- * GNU libmatheval is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2, or (at your option) any later
- * version.
- * 
- * GNU libmatheval is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* This file was modified for inclusion in Gmsh */
-
-#ifndef NODE_H
-#define NODE_H 1
-
-#include "symbol_table.h"
-
-/* Data structure representing function tree node.  */
-typedef struct _Node {
-  char            type;	/* Node type ('c' for constant, 'v' for
-			 * variable, 'f' for function, 'u' for unary
-			 * operator, 'b' for binary operator).  */
-  union {
-    double          constant;	/* Constant value.  */
-    Record         *variable;	/* Symbol table record for
-				 * variable.  */
-    struct {
-      Record         *record;	/* Symbol table record for
-				 * function.  */
-      struct _Node   *child;	/* Function argument node.  */
-    }               function;	/* Structure representing
-				 * function.  */
-    struct {
-      char            operatorr;/* Operator type ('-'
-				 * for unary minus).  */
-      struct _Node   *child;	/* Operand node.  */
-    }               un_op;	/* Structure representing unary
-				 * operator.  */
-    struct {
-      char            operatorr;/* Operator type ('+'
-				 * for adition, '-' for
-				 * subtraction, '*' for
-				 * multiplication, '/'
-				 * for division and '^'
-				 * for exponentiation).  */
-      struct _Node   *left, *right;	/* Operands nodes.  */
-    }               bin_op;	/* Structure representing binary
-				 * operator.  */
-  }               data;
-}               Node;
-
-/*
- * Create node of given type and initialize it from optional arguments.
- * Function returns pointer to node object that should be passed as first
- * argument to all other node functions.
- */
-Node           *node_create(char type,...);
-
-/* Destroy subtree rooted at specified node.  */
-void            node_destroy(Node * node);
-
-/*
- * Make a copy of subtree rooted at given node.  Deep copy operation is
- * employed.
- */
-Node           *node_copy(Node * node);
-
-/*
- * Simplify subtree rooted at given node.  Function returns root of
- * simplified subtree (that may or may not be original node).
- */
-Node           *node_simplify(Node * node);
-
-/*
- * Evaluate subtree rooted at given node.  For variables, values from symbol
- * table are used.
- */
-double          node_evaluate(Node * node);
-
-/*
- * Create derivative tree for subtree rooted at given node.  Second argument
- * is derivation variable, third argument is symbol table (needed for
- * functions derivatives).  Function returns root of corresponding derivation
- * tree.
- */
-Node           *node_derivative(Node * node, char *name, SymbolTable * symbol_table);
-
-/*
- * Calculate length of the string representing subtree rooted at specified
- * node.
- */
-int             node_calculate_length(Node * node);
-
-/*
- * Write subtree rooted at specified node to given string variable.  No
- * checking of string overflow is done by this procedure; it is expected that
- * string of appropriate length is passed as argument.
- */
-void            node_write(Node * node, char *string);
-
-/* Flag each variable in symbol table that is used from subtree rooted at
- * specified node. */
-void            node_flag_variables(Node * node);
-#endif
diff --git a/contrib/MathEval/parser.tab.cpp b/contrib/MathEval/parser.tab.cpp
deleted file mode 100644
index 0c486588f702c26a6e82f048acd3b12faf1c5dab..0000000000000000000000000000000000000000
--- a/contrib/MathEval/parser.tab.cpp
+++ /dev/null
@@ -1,1693 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "2.3"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 0
-
-/* Using locations.  */
-#define YYLSP_NEEDED 0
-
-/* Substitute the variable and function names.  */
-#define yyparse meparse
-#define yylex   melex
-#define yyerror meerror
-#define yylval  melval
-#define yychar  mechar
-#define yydebug medebug
-#define yynerrs menerrs
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     NUMBER = 258,
-     VARIABLE = 259,
-     FUNCTION = 260,
-     NEG = 261
-   };
-#endif
-/* Tokens.  */
-#define NUMBER 258
-#define VARIABLE 259
-#define FUNCTION 260
-#define NEG 261
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 1 "parser.y"
-
-/*
- * Copyright (C) 1999, 2002, 2003  Free Software Foundation, Inc.
- * 
- * This file is part of GNU libmatheval
- *
- * GNU libmatheval is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * GNU libmatheval is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-/* This file was modified for inclusion in Gmsh */
-
-#include "common.h"
-#include "node.h"
-
-/* Variables used to communicate with code using parser.  */
-extern Node* matheval_root; /* Root of tree representation of function.  */
-extern int matheval_ok; /* Flag representing success of parsing.  */
-
-/* Report parsing error.  */
-int yyerror (char *s);
-
-/* Function used to tokenize string representing function (this function
-   is generated by scanner generator).  */
-int yylex (void);
-
-/* Function used to flush the internal flex buffer when we exit
-   prematurely (i.e., in case of a parse error) so that the next time
-   we call the scanner, all is nicely reset. Without this, the
-   behaviour of the next call after an error is unpredictable.  */
-void force_buffer_flush(void);
-
-
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 48 "parser.y"
-{
-  Node *node;
-  Record *record;
-}
-/* Line 193 of yacc.c.  */
-#line 167 "parser.tab.cpp"
-	YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations.  */
-
-
-/* Line 216 of yacc.c.  */
-#line 180 "parser.tab.cpp"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
-    int i;
-#endif
-{
-  return i;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef _STDLIB_H
-#      define _STDLIB_H 1
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
-       && ! ((defined YYMALLOC || defined malloc) \
-	     && (defined YYFREE || defined free)))
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-#  ifndef YYFREE
-#   define YYFREE free
-#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  yytype_int16 yyss;
-  YYSTYPE yyvs;
-  };
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
-      + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)		\
-      do					\
-	{					\
-	  YYSIZE_T yyi;				\
-	  for (yyi = 0; yyi < (Count); yyi++)	\
-	    (To)[yyi] = (From)[yyi];		\
-	}					\
-      while (YYID (0))
-#  endif
-# endif
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack)					\
-    do									\
-      {									\
-	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack, Stack, yysize);				\
-	Stack = &yyptr->Stack;						\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-	yyptr += yynewbytes / sizeof (*yyptr);				\
-      }									\
-    while (YYID (0))
-
-#endif
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  11
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   41
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  15
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  3
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  12
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  26
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   261
-
-#define YYTRANSLATE(YYX)						\
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const yytype_uint8 yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      12,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      13,    14,     8,     7,     2,     6,     2,     9,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,    11,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,    10
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint8 yyprhs[] =
-{
-       0,     0,     3,     6,     8,    10,    14,    18,    22,    26,
-      29,    33,    38
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] =
-{
-      16,     0,    -1,    17,    12,    -1,     3,    -1,     4,    -1,
-      17,     7,    17,    -1,    17,     6,    17,    -1,    17,     8,
-      17,    -1,    17,     9,    17,    -1,     6,    17,    -1,    17,
-      11,    17,    -1,     5,    13,    17,    14,    -1,    13,    17,
-      14,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const yytype_uint8 yyrline[] =
-{
-       0,    71,    71,    78,    81,    84,    88,    92,    96,   100,
-     104,   108,   112
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "NUMBER", "VARIABLE", "FUNCTION", "'-'",
-  "'+'", "'*'", "'/'", "NEG", "'^'", "'\\n'", "'('", "')'", "$accept",
-  "input", "expression", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const yytype_uint16 yytoknum[] =
-{
-       0,   256,   257,   258,   259,   260,    45,    43,    42,    47,
-     261,    94,    10,    40,    41
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    15,    16,    17,    17,    17,    17,    17,    17,    17,
-      17,    17,    17
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     2,     1,     1,     3,     3,     3,     3,     2,
-       3,     4,     3
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint8 yydefact[] =
-{
-       0,     3,     4,     0,     0,     0,     0,     0,     0,     9,
-       0,     1,     0,     0,     0,     0,     0,     2,     0,    12,
-       6,     5,     7,     8,    10,    11
-};
-
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int8 yydefgoto[] =
-{
-      -1,     6,     7
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -8
-static const yytype_int8 yypact[] =
-{
-      10,    -8,    -8,    -7,    10,    10,     7,    29,    10,    13,
-      11,    -8,    10,    10,    10,    10,    10,    -8,    20,    -8,
-      -6,    -6,    13,    13,    -8,    -8
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int8 yypgoto[] =
-{
-      -8,    -8,    -4
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -1
-static const yytype_uint8 yytable[] =
-{
-       9,    10,    14,    15,    18,    16,     8,    11,    20,    21,
-      22,    23,    24,     1,     2,     3,     4,    12,    13,    14,
-      15,     0,    16,     5,    16,    19,    12,    13,    14,    15,
-       0,    16,     0,     0,    25,    12,    13,    14,    15,     0,
-      16,    17
-};
-
-static const yytype_int8 yycheck[] =
-{
-       4,     5,     8,     9,     8,    11,    13,     0,    12,    13,
-      14,    15,    16,     3,     4,     5,     6,     6,     7,     8,
-       9,    -1,    11,    13,    11,    14,     6,     7,     8,     9,
-      -1,    11,    -1,    -1,    14,     6,     7,     8,     9,    -1,
-      11,    12
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
-{
-       0,     3,     4,     5,     6,    13,    16,    17,    13,    17,
-      17,     0,     6,     7,     8,     9,    11,    12,    17,    14,
-      17,    17,    17,    17,    17,    14
-};
-
-#define yyerrok		(yyerrstatus = 0)
-#define yyclearin	(yychar = YYEMPTY)
-#define YYEMPTY		(-2)
-#define YYEOF		0
-
-#define YYACCEPT	goto yyacceptlab
-#define YYABORT		goto yyabortlab
-#define YYERROR		goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
-
-#define YYFAIL		goto yyerrlab
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)					\
-do								\
-  if (yychar == YYEMPTY && yylen == 1)				\
-    {								\
-      yychar = (Token);						\
-      yylval = (Value);						\
-      yytoken = YYTRANSLATE (yychar);				\
-      YYPOPSTACK (1);						\
-      goto yybackup;						\
-    }								\
-  else								\
-    {								\
-      yyerror (YY_("syntax error: cannot back up")); \
-      YYERROR;							\
-    }								\
-while (YYID (0))
-
-
-#define YYTERROR	1
-#define YYERRCODE	256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)				\
-    do									\
-      if (YYID (N))                                                    \
-	{								\
-	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
-	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
-	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
-	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
-	}								\
-      else								\
-	{								\
-	  (Current).first_line   = (Current).last_line   =		\
-	    YYRHSLOC (Rhs, 0).last_line;				\
-	  (Current).first_column = (Current).last_column =		\
-	    YYRHSLOC (Rhs, 0).last_column;				\
-	}								\
-    while (YYID (0))
-#endif
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
-
-#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)			\
-     fprintf (File, "%d.%d-%d.%d",			\
-	      (Loc).first_line, (Loc).first_column,	\
-	      (Loc).last_line,  (Loc).last_column)
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)			\
-do {						\
-  if (yydebug)					\
-    YYFPRINTF Args;				\
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
-do {									  \
-  if (yydebug)								  \
-    {									  \
-      YYFPRINTF (stderr, "%s ", Title);					  \
-      yy_symbol_print (stderr,						  \
-		  Type, Value); \
-      YYFPRINTF (stderr, "\n");						  \
-    }									  \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (!yyvaluep)
-    return;
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
-# endif
-  switch (yytype)
-    {
-      default:
-	break;
-    }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
-#else
-static void
-yy_stack_print (bottom, top)
-    yytype_int16 *bottom;
-    yytype_int16 *top;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)				\
-do {								\
-  if (yydebug)							\
-    yy_stack_print ((Bottom), (Top));				\
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
-    YYSTYPE *yyvsp;
-    int yyrule;
-#endif
-{
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  unsigned long int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-	     yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      fprintf (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-		       &(yyvsp[(yyi + 1) - (yynrhs)])
-		       		       );
-      fprintf (stderr, "\n");
-    }
-}
-
-# define YY_REDUCE_PRINT(Rule)		\
-do {					\
-  if (yydebug)				\
-    yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef	YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
-{
-  YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      YYSIZE_T yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-	switch (*++yyp)
-	  {
-	  case '\'':
-	  case ',':
-	    goto do_not_strip_quotes;
-
-	  case '\\':
-	    if (*++yyp != '\\')
-	      goto do_not_strip_quotes;
-	    /* Fall through.  */
-	  default:
-	    if (yyres)
-	      yyres[yyn] = *yyp;
-	    yyn++;
-	    break;
-
-	  case '"':
-	    if (yyres)
-	      yyres[yyn] = '\0';
-	    return yyn;
-	  }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into YYRESULT an error message about the unexpected token
-   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
-   including the terminating null byte.  If YYRESULT is null, do not
-   copy anything; just return the number of bytes that would be
-   copied.  As a special case, return 0 if an ordinary "syntax error"
-   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
-   size calculation.  */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
-  int yyn = yypact[yystate];
-
-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else
-    {
-      int yytype = YYTRANSLATE (yychar);
-      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
-      YYSIZE_T yysize = yysize0;
-      YYSIZE_T yysize1;
-      int yysize_overflow = 0;
-      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-      int yyx;
-
-# if 0
-      /* This is so xgettext sees the translatable formats that are
-	 constructed on the fly.  */
-      YY_("syntax error, unexpected %s");
-      YY_("syntax error, unexpected %s, expecting %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
-      char *yyfmt;
-      char const *yyf;
-      static char const yyunexpected[] = "syntax error, unexpected %s";
-      static char const yyexpecting[] = ", expecting %s";
-      static char const yyor[] = " or %s";
-      char yyformat[sizeof yyunexpected
-		    + sizeof yyexpecting - 1
-		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
-		       * (sizeof yyor - 1))];
-      char const *yyprefix = yyexpecting;
-
-      /* Start YYX at -YYN if negative to avoid negative indexes in
-	 YYCHECK.  */
-      int yyxbegin = yyn < 0 ? -yyn : 0;
-
-      /* Stay within bounds of both yycheck and yytname.  */
-      int yychecklim = YYLAST - yyn + 1;
-      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-      int yycount = 1;
-
-      yyarg[0] = yytname[yytype];
-      yyfmt = yystpcpy (yyformat, yyunexpected);
-
-      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-	  {
-	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-	      {
-		yycount = 1;
-		yysize = yysize0;
-		yyformat[sizeof yyunexpected - 1] = '\0';
-		break;
-	      }
-	    yyarg[yycount++] = yytname[yyx];
-	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-	    yysize_overflow |= (yysize1 < yysize);
-	    yysize = yysize1;
-	    yyfmt = yystpcpy (yyfmt, yyprefix);
-	    yyprefix = yyor;
-	  }
-
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      yysize = yysize1;
-
-      if (yysize_overflow)
-	return YYSIZE_MAXIMUM;
-
-      if (yyresult)
-	{
-	  /* Avoid sprintf, as that infringes on the user's name space.
-	     Don't have undefined behavior even if the translation
-	     produced a string with the wrong number of "%s"s.  */
-	  char *yyp = yyresult;
-	  int yyi = 0;
-	  while ((*yyp = *yyf) != '\0')
-	    {
-	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
-		{
-		  yyp += yytnamerr (yyp, yyarg[yyi++]);
-		  yyf += 2;
-		}
-	      else
-		{
-		  yyp++;
-		  yyf++;
-		}
-	    }
-	}
-      return yysize;
-    }
-}
-#endif /* YYERROR_VERBOSE */
-
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  YYUSE (yyvaluep);
-
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  switch (yytype)
-    {
-
-      default:
-	break;
-    }
-}
-
-
-/* Prevent warnings from -Wmissing-prototypes.  */
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-/* The look-ahead symbol.  */
-int yychar;
-
-/* The semantic value of the look-ahead symbol.  */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-  
-  int yystate;
-  int yyn;
-  int yyresult;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Look-ahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
-
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
-
-  /* The state stack.  */
-  yytype_int16 yyssa[YYINITDEPTH];
-  yytype_int16 *yyss = yyssa;
-  yytype_int16 *yyssp;
-
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
-
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-
-  /* The number of symbols on the RHS of the reduced rule.
-     Keep to zero when no symbol should be popped.  */
-  int yylen = 0;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY;		/* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-
-  yyssp = yyss;
-  yyvsp = yyvs;
-
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-	/* Give user a chance to reallocate the stack.  Use copies of
-	   these so that the &'s don't force the real ones into
-	   memory.  */
-	YYSTYPE *yyvs1 = yyvs;
-	yytype_int16 *yyss1 = yyss;
-
-
-	/* Each stack pointer address is followed by the size of the
-	   data in use in that stack, in bytes.  This used to be a
-	   conditional around just the two extra args, but that might
-	   be undefined if yyoverflow is a macro.  */
-	yyoverflow (YY_("memory exhausted"),
-		    &yyss1, yysize * sizeof (*yyssp),
-		    &yyvs1, yysize * sizeof (*yyvsp),
-
-		    &yystacksize);
-
-	yyss = yyss1;
-	yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-	goto yyexhaustedlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-	yystacksize = YYMAXDEPTH;
-
-      {
-	yytype_int16 *yyss1 = yyss;
-	union yyalloc *yyptr =
-	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-	if (! yyptr)
-	  goto yyexhaustedlab;
-	YYSTACK_RELOCATE (yyss);
-	YYSTACK_RELOCATE (yyvs);
-
-#  undef YYSTACK_RELOCATE
-	if (yyss1 != yyssa)
-	  YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-		  (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-	YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     look-ahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to look-ahead token.  */
-  yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
-    goto yydefault;
-
-  /* Not known => get a look-ahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-	goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  /* Shift the look-ahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
-
-  yystate = yyn;
-  *++yyvsp = yylval;
-
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 2:
-#line 71 "parser.y"
-    {
-  matheval_root = (yyvsp[(1) - (2)].node);
-  return 1;
-;}
-    break;
-
-  case 3:
-#line 78 "parser.y"
-    {
-  (yyval.node) = (yyvsp[(1) - (1)].node);
-;}
-    break;
-
-  case 4:
-#line 81 "parser.y"
-    {
-  (yyval.node) = (yyvsp[(1) - (1)].node);
-;}
-    break;
-
-  case 5:
-#line 84 "parser.y"
-    {
-  /* Create addition binary operator node.  */
-  (yyval.node) = node_create ('b', '+', (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-;}
-    break;
-
-  case 6:
-#line 88 "parser.y"
-    {
-  /* Create subtraction binary operator node.  */
-  (yyval.node) = node_create ('b', '-', (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-;}
-    break;
-
-  case 7:
-#line 92 "parser.y"
-    {
-  /* Create multiplication binary operator node.  */
-  (yyval.node) = node_create ('b', '*', (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-;}
-    break;
-
-  case 8:
-#line 96 "parser.y"
-    {
-  /* Create division binary operator node.  */
-  (yyval.node) = node_create ('b', '/', (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-;}
-    break;
-
-  case 9:
-#line 100 "parser.y"
-    {
-  /* Create minus unary operator node.  */
-  (yyval.node) = node_create ('u', '-', (yyvsp[(2) - (2)].node));
-;}
-    break;
-
-  case 10:
-#line 104 "parser.y"
-    {
-  /* Create exponentiation unary operator node.  */
-  (yyval.node) = node_create ('b', '^', (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-;}
-    break;
-
-  case 11:
-#line 108 "parser.y"
-    {
-  /* Create function node.  */
-  (yyval.node) = node_create ('f', (yyvsp[(1) - (4)].record), (yyvsp[(3) - (4)].node));
-;}
-    break;
-
-  case 12:
-#line 112 "parser.y"
-    {
-  (yyval.node) = (yyvsp[(2) - (3)].node);
-;}
-    break;
-
-
-/* Line 1267 of yacc.c.  */
-#line 1469 "parser.tab.cpp"
-      default: break;
-    }
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-
-  /* Now `shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if ! YYERROR_VERBOSE
-      yyerror (YY_("syntax error"));
-#else
-      {
-	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
-	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
-	  {
-	    YYSIZE_T yyalloc = 2 * yysize;
-	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
-	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
-	    if (yymsg != yymsgbuf)
-	      YYSTACK_FREE (yymsg);
-	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
-	    if (yymsg)
-	      yymsg_alloc = yyalloc;
-	    else
-	      {
-		yymsg = yymsgbuf;
-		yymsg_alloc = sizeof yymsgbuf;
-	      }
-	  }
-
-	if (0 < yysize && yysize <= yymsg_alloc)
-	  {
-	    (void) yysyntax_error (yymsg, yystate, yychar);
-	    yyerror (yymsg);
-	  }
-	else
-	  {
-	    yyerror (YY_("syntax error"));
-	    if (yysize != 0)
-	      goto yyexhaustedlab;
-	  }
-      }
-#endif
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse look-ahead token after an
-	 error, discard it.  */
-
-      if (yychar <= YYEOF)
-	{
-	  /* Return failure if at end of input.  */
-	  if (yychar == YYEOF)
-	    YYABORT;
-	}
-      else
-	{
-	  yydestruct ("Error: discarding",
-		      yytoken, &yylval);
-	  yychar = YYEMPTY;
-	}
-    }
-
-  /* Else will try to reuse look-ahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
-
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
-	{
-	  yyn += YYTERROR;
-	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-	    {
-	      yyn = yytable[yyn];
-	      if (0 < yyn)
-		break;
-	    }
-	}
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-	YYABORT;
-
-
-      yydestruct ("Error: popping",
-		  yystos[yystate], yyvsp);
-      YYPOPSTACK (1);
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  *++yyvsp = yylval;
-
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#ifndef yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (YY_("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  if (yychar != YYEOF && yychar != YYEMPTY)
-     yydestruct ("Cleanup: discarding lookahead",
-		 yytoken, &yylval);
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYABORT or YYACCEPT.  */
-  YYPOPSTACK (yylen);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss)
-    {
-      yydestruct ("Cleanup: popping",
-		  yystos[*yyssp], yyvsp);
-      YYPOPSTACK (1);
-    }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
-}
-
-
-#line 117 "parser.y"
-
-
-int yyerror(char* s)
-{
-  /* Indicate parsing error through appropriate flag and stop
-     parsing.  */
-  matheval_ok = 0;
-  force_buffer_flush();
-  return 0;
-}
-
diff --git a/contrib/MathEval/parser.tab.hpp b/contrib/MathEval/parser.tab.hpp
deleted file mode 100644
index 6430ec6e8f36025349eb7017cc90f1114a273791..0000000000000000000000000000000000000000
--- a/contrib/MathEval/parser.tab.hpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     NUMBER = 258,
-     VARIABLE = 259,
-     FUNCTION = 260,
-     NEG = 261
-   };
-#endif
-/* Tokens.  */
-#define NUMBER 258
-#define VARIABLE 259
-#define FUNCTION 260
-#define NEG 261
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 48 "parser.y"
-{
-  Node *node;
-  Record *record;
-}
-/* Line 1529 of yacc.c.  */
-#line 66 "parser.tab.hpp"
-	YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYSTYPE melval;
-
diff --git a/contrib/MathEval/parser.y b/contrib/MathEval/parser.y
deleted file mode 100644
index 9b5817bf816afb85f09cfd263e3e5073e291d7ba..0000000000000000000000000000000000000000
--- a/contrib/MathEval/parser.y
+++ /dev/null
@@ -1,126 +0,0 @@
-%{
-/*
- * Copyright (C) 1999, 2002, 2003  Free Software Foundation, Inc.
- * 
- * This file is part of GNU libmatheval
- *
- * GNU libmatheval is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * GNU libmatheval is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-/* This file was modified for inclusion in Gmsh */
-
-#include "common.h"
-#include "node.h"
-
-/* Variables used to communicate with code using parser.  */
-extern Node* matheval_root; /* Root of tree representation of function.  */
-extern int matheval_ok; /* Flag representing success of parsing.  */
-
-/* Report parsing error.  */
-int yyerror (char *s);
-
-/* Function used to tokenize string representing function (this function
-   is generated by scanner generator).  */
-int yylex (void);
-
-/* Function used to flush the internal flex buffer when we exit
-   prematurely (i.e., in case of a parse error) so that the next time
-   we call the scanner, all is nicely reset. Without this, the
-   behaviour of the next call after an error is unpredictable.  */
-void force_buffer_flush(void);
-
-%}
-
-/* Parser semantic values type.  */
-%union {
-  Node *node;
-  Record *record;
-}
-
-/* Grammar terminal symbols.  */
-%token <node> NUMBER VARIABLE
-%token <record> FUNCTION
-
-/* Grammar non-terminal symbols.  */
-%type <node> expression
-
-%left '-' '+'
-%left '*' '/'
-%left NEG
-%left '^'
-
-/* Grammar start non-terminal.  */
-%start input
-
-%%
-
-input
-: expression '\n' {
-  matheval_root = $1;
-  return 1;
-}
-;
-
-expression
-: NUMBER {
-  $$ = $1;
-}
-| VARIABLE {
-  $$ = $1;
-}
-| expression '+' expression {
-  /* Create addition binary operator node.  */
-  $$ = node_create ('b', '+', $1, $3);
-}
-| expression '-' expression {
-  /* Create subtraction binary operator node.  */
-  $$ = node_create ('b', '-', $1, $3);
-}
-| expression '*' expression {
-  /* Create multiplication binary operator node.  */
-  $$ = node_create ('b', '*', $1, $3);
-}
-| expression '/' expression {
-  /* Create division binary operator node.  */
-  $$ = node_create ('b', '/', $1, $3);
-}
-| '-' expression %prec NEG {
-  /* Create minus unary operator node.  */
-  $$ = node_create ('u', '-', $2);
-}
-| expression '^' expression {
-  /* Create exponentiation unary operator node.  */
-  $$ = node_create ('b', '^', $1, $3);
-}
-| FUNCTION '(' expression ')' {
-  /* Create function node.  */
-  $$ = node_create ('f', $1, $3);
-}
-| '(' expression ')' {
-  $$ = $2;
-}
-;
-
-%%
-
-int yyerror(char* s)
-{
-  /* Indicate parsing error through appropriate flag and stop
-     parsing.  */
-  matheval_ok = 0;
-  force_buffer_flush();
-  return 0;
-}
diff --git a/contrib/MathEval/scanner.l b/contrib/MathEval/scanner.l
deleted file mode 100644
index 396558adfca3f009ca8f4cfd448d92b3672a8433..0000000000000000000000000000000000000000
--- a/contrib/MathEval/scanner.l
+++ /dev/null
@@ -1,136 +0,0 @@
-%{
-/*
- * Copyright (C) 1999, 2002, 2003  Free Software Foundation, Inc.
- * 
- * This file is part of GNU libmatheval
- *
- * GNU libmatheval is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * GNU libmatheval is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-/* This file was modified for inclusion in Gmsh */
-
-#include "common.h"
-#include "node.h"
-#include "parser.tab.hpp"
-#include "symbol_table.h"
-
-#define YY_ALWAYS_INTERACTIVE 1
-
-/* Redefine macro to redirect scanner input from string instead of
-   standard input.  */
-#define YY_INPUT( buffer, result, max_size ) \
-{ result = input_from_string (buffer, max_size); }
-
-/* Added by Gmsh for MSVC */
-#if defined(WIN32)
-#define isatty(arg) -1
-#define YY_NO_UNISTD_H
-#endif
-
-/* Variables used to communicate with code using scanner.  */
-extern SymbolTable *matheval_symbol_table; /* Evaluator symbol table.  */
-extern char *matheval_input_string; /* String representing function.  */
-
-/* Read next max_size character from string into buffer.  */
-static int input_from_string (char *buffer, int max_size);
-%}
-
-/* Token definitions.  */
-whitespace [\ \t]+
-digit [0-9]
-number ({digit}+|{digit}+"."{digit}*|{digit}*"."{digit}+)([Ee][-+]?{digit}+)?
-function "Exp"|"Log"|"Sqrt"|"Sin"|"Cos"|"Tan"|"Ctan"|"Asin"|"Acos"|"Atan"|"Actan"|"Sinh"|"Cosh"|"Tanh"|"Ctanh"|"Asinh"|"Acosh"|"Atanh"|"Actanh"|"Fabs"|"Rand"|"Log10"|"Step"|"Delta"|"NanDelta"|"Floor"|"HeavS"
-identifier [a-zA-Z\_][a-zA-Z0-9\_]*
-
-%%
-
-{whitespace}
-
-{number} {
-  /* Create node representing constant with appropriate value.  */
-  melval.node = node_create ('c', atof (metext));
-  return NUMBER;
-}
-
-{function} {
-  /* Find symbol table record corresponding to function name.  */
-  melval.record = symbol_table_lookup (matheval_symbol_table, metext);
-  return FUNCTION;
-}
-
-{identifier} {
-  Record *record; /* Symbol table record.  */
-  /* Inserty variable into symbol table.  */
-  record = symbol_table_insert (matheval_symbol_table, metext, 'v');
-  melval.node = node_create ('v', record);
-  return VARIABLE;
-}
-
-"+" {
-  return '+';
-}
-
-"-" {
-  return '-';
-}
-
-"*" {
-  return '*';
-}
-
-"/" {
-  return '/';
-}
-
-"^" {
-  return '^';
-}
-
-"(" {
-  return '(';
-}
-
-")" {
-  return ')';
-}
-
-"\n" {
-  return '\n';
-}
-
-%%
-
-#undef mewrap
-
-int mewrap() { return 1; }
-
-static int input_from_string (char *buffer, int max_size)
-{
-  int count; /* Count of characters to copy from input string to buffer.  */
-
-  /* Calculate count of characters to copy.  */
-  count = strlen (matheval_input_string);
-  if (count > max_size)
-    count = max_size;
-
-  /* Perform copy operation and update input string.  */
-  memcpy(buffer, matheval_input_string, count);
-  matheval_input_string += count;
-
-  return count;
-}
-
-void force_buffer_flush() { YY_FLUSH_BUFFER; }
diff --git a/contrib/MathEval/scanner.yy.cpp b/contrib/MathEval/scanner.yy.cpp
deleted file mode 100644
index 02f20b530247dc6c53543a644b1e23d1725318c7..0000000000000000000000000000000000000000
--- a/contrib/MathEval/scanner.yy.cpp
+++ /dev/null
@@ -1,1918 +0,0 @@
-#line 2 "scanner.yy.cpp"
-
-#line 4 "scanner.yy.cpp"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 33
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types. 
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t; 
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN               (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN              (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX               (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX              (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX              (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX              (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX             (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#endif
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-#if __STDC__
-
-#define YY_USE_CONST
-
-#endif	/* __STDC__ */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* Enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN (yy_start) = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START (((yy_start) - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE merestart(mein  )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#define YY_BUF_SIZE 16384
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-extern int meleng;
-
-extern FILE *mein, *meout;
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-    #define YY_LESS_LINENO(n)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up metext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = (yy_hold_char); \
-		YY_RESTORE_YY_MORE_OFFSET \
-		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up metext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, (yytext_ptr)  )
-
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef unsigned int yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_n_chars;
-
-	/* Whether we "own" the buffer - i.e., we know we created it,
-	 * and can realloc() it to grow it, and should free() it to
-	 * delete it.
-	 */
-	int yy_is_our_buffer;
-
-	/* Whether this is an "interactive" input source; if so, and
-	 * if we're using stdio for input, then we want to use getc()
-	 * instead of fread(), to make sure we stop fetching input after
-	 * each newline.
-	 */
-	int yy_is_interactive;
-
-	/* Whether we're considered to be at the beginning of a line.
-	 * If so, '^' rules will be active on the next match, otherwise
-	 * not.
-	 */
-	int yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
-	 * shouldn't try reading from the input source any more.  We might
-	 * still have a bunch of tokens to match, though, because of
-	 * possible backing-up.
-	 *
-	 * When we actually see the EOF, we change the status to "new"
-	 * (via merestart()), so that the user can continue scanning by
-	 * just pointing mein at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* Stack of input buffers. */
-static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
-static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
-static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
-                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
-                          : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
-
-/* yy_hold_char holds the character lost when metext is formed. */
-static char yy_hold_char;
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-int meleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 0;		/* whether we need to initialize */
-static int yy_start = 0;	/* start state number */
-
-/* Flag which is used to allow mewrap()'s to do buffer switches
- * instead of setting up a fresh mein.  A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
-
-void merestart (FILE *input_file  );
-void me_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
-YY_BUFFER_STATE me_create_buffer (FILE *file,int size  );
-void me_delete_buffer (YY_BUFFER_STATE b  );
-void me_flush_buffer (YY_BUFFER_STATE b  );
-void mepush_buffer_state (YY_BUFFER_STATE new_buffer  );
-void mepop_buffer_state (void );
-
-static void meensure_buffer_stack (void );
-static void me_load_buffer_state (void );
-static void me_init_buffer (YY_BUFFER_STATE b,FILE *file  );
-
-#define YY_FLUSH_BUFFER me_flush_buffer(YY_CURRENT_BUFFER )
-
-YY_BUFFER_STATE me_scan_buffer (char *base,yy_size_t size  );
-YY_BUFFER_STATE me_scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE me_scan_bytes (yyconst char *bytes,int len  );
-
-void *mealloc (yy_size_t  );
-void *merealloc (void *,yy_size_t  );
-void mefree (void *  );
-
-#define yy_new_buffer me_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        meensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            me_create_buffer(mein,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        meensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            me_create_buffer(mein,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-typedef unsigned char YY_CHAR;
-
-FILE *mein = (FILE *) 0, *meout = (FILE *) 0;
-
-typedef int yy_state_type;
-
-extern int melineno;
-
-int melineno = 1;
-
-extern char *metext;
-#define yytext_ptr metext
-
-static yy_state_type yy_get_previous_state (void );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
-static int yy_get_next_buffer (void );
-static void yy_fatal_error (yyconst char msg[]  );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up metext.
- */
-#define YY_DO_BEFORE_ACTION \
-	(yytext_ptr) = yy_bp; \
-	meleng = (size_t) (yy_cp - yy_bp); \
-	(yy_hold_char) = *yy_cp; \
-	*yy_cp = '\0'; \
-	(yy_c_buf_p) = yy_cp;
-
-#define YY_NUM_RULES 13
-#define YY_END_OF_BUFFER 14
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[87] =
-    {   0,
-        0,    0,   14,   13,    1,   12,   10,   11,    7,    5,
-        6,   13,    8,    2,    4,    4,    4,    4,    4,    4,
-        4,    4,    4,    4,    4,    4,    9,    1,    2,    2,
-        2,    0,    4,    4,    4,    4,    4,    4,    4,    4,
-        4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
-        2,    0,    2,    4,    4,    4,    4,    3,    4,    4,
-        3,    4,    4,    4,    3,    4,    4,    3,    4,    4,
-        3,    3,    4,    3,    3,    3,    4,    4,    4,    4,
-        4,    3,    4,    4,    4,    0
-    } ;
-
-static yyconst flex_int32_t yy_ec[256] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    2,    1,    1,    1,    1,    1,    1,    1,    4,
-        5,    6,    7,    1,    8,    9,   10,   11,   12,   13,
-       13,   13,   13,   13,   13,   13,   13,    1,    1,    1,
-        1,    1,    1,    1,   14,   15,   16,   17,   18,   19,
-       15,   20,   15,   15,   15,   21,   15,   22,   15,   15,
-       15,   23,   24,   25,   15,   15,   15,   15,   15,   15,
-        1,    1,    1,   26,   15,    1,   27,   28,   29,   30,
-
-       31,   15,   32,   33,   34,   15,   15,   35,   15,   36,
-       37,   38,   39,   40,   41,   42,   15,   43,   15,   44,
-       15,   15,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1
-    } ;
-
-static yyconst flex_int32_t yy_meta[45] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-        2,    2,    2,    2,    2,    1,    2,    2,    2,    2,
-        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-        2,    2,    2,    2
-    } ;
-
-static yyconst flex_int16_t yy_base[88] =
-    {   0,
-        0,    0,  155,  156,  152,  156,  156,  156,  156,  156,
-      156,   34,  156,   39,   20,    0,   16,  122,  108,   28,
-      120,  113,  122,  121,   25,  120,  156,  144,   60,   63,
-       71,   85,    0,   23,  111,  117,  102,  115,  106,  102,
-      111,  101,  110,  104,   99,   98,   97,   92,  100,   94,
-       88,   74,   92,   88,  101,   91,   90,   92,   88,   81,
-        0,   81,   84,   77,  106,  100,   86,   82,   72,   75,
-       79,   78,   74,   76,   75,   74,   68,   50,   64,   68,
-       46,   36,   33,   24,   29,  156,   52
-    } ;
-
-static yyconst flex_int16_t yy_def[88] =
-    {   0,
-       86,    1,   86,   86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   86,   86,   86,   86,
-       86,   86,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       86,   86,   86,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,   87,   87,   87,   87,   87,
-       87,   87,   87,   87,   87,    0,   86
-    } ;
-
-static yyconst flex_int16_t yy_nxt[201] =
-    {   0,
-        4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
-       14,   14,   14,   15,   16,   17,   18,   19,   20,   21,
-       22,   23,   24,   25,   26,   27,   16,   16,   16,   16,
-       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-       16,   16,   16,   16,   29,   29,   29,   30,   34,   31,
-       31,   31,   37,   33,   41,   61,   32,   38,   47,   54,
-       35,   36,   42,   48,   55,   85,   49,   84,   61,   32,
-       29,   29,   29,   51,   51,   51,   83,   32,   61,   30,
-       32,   31,   31,   31,   53,   53,   53,   61,   32,   61,
-       32,   52,   52,   32,   61,   53,   53,   53,   51,   51,
-
-       51,   32,   53,   53,   53,   32,   61,   61,   61,   82,
-       61,   61,   61,   61,   61,   61,   81,   80,   32,   79,
-       78,   61,   77,   76,   61,   75,   74,   73,   72,   71,
-       70,   69,   68,   67,   66,   65,   64,   63,   62,   61,
-       60,   59,   58,   57,   56,   28,   50,   46,   45,   44,
-       43,   40,   39,   28,   86,    3,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86
-
-    } ;
-
-static yyconst flex_int16_t yy_chk[201] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,   12,   12,   12,   14,   15,   14,
-       14,   14,   17,   87,   20,   85,   14,   17,   25,   34,
-       15,   15,   20,   25,   34,   84,   25,   83,   82,   14,
-       29,   29,   29,   30,   30,   30,   81,   29,   80,   31,
-       30,   31,   31,   31,   52,   52,   52,   79,   31,   78,
-       29,   32,   32,   30,   77,   32,   32,   32,   51,   51,
-
-       51,   31,   53,   53,   53,   51,   76,   75,   74,   73,
-       72,   71,   70,   69,   68,   67,   66,   65,   51,   64,
-       63,   62,   60,   59,   58,   57,   56,   55,   54,   50,
-       49,   48,   47,   46,   45,   44,   43,   42,   41,   40,
-       39,   38,   37,   36,   35,   28,   26,   24,   23,   22,
-       21,   19,   18,    5,    3,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
-       86,   86,   86,   86,   86,   86,   86,   86,   86,   86
-
-    } ;
-
-static yy_state_type yy_last_accepting_state;
-static char *yy_last_accepting_cpos;
-
-extern int me_flex_debug;
-int me_flex_debug = 0;
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-char *metext;
-#line 1 "scanner.l"
-#line 2 "scanner.l"
-/*
- * Copyright (C) 1999, 2002, 2003  Free Software Foundation, Inc.
- * 
- * This file is part of GNU libmatheval
- *
- * GNU libmatheval is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * GNU libmatheval is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-/* This file was modified for inclusion in Gmsh */
-
-#include "common.h"
-#include "node.h"
-#include "parser.tab.hpp"
-#include "symbol_table.h"
-
-#define YY_ALWAYS_INTERACTIVE 1
-
-/* Redefine macro to redirect scanner input from string instead of
-   standard input.  */
-#define YY_INPUT( buffer, result, max_size ) \
-{ result = input_from_string (buffer, max_size); }
-
-/* Added by Gmsh for MSVC */
-#if defined(WIN32)
-#define isatty(arg) -1
-#define YY_NO_UNISTD_H
-#endif
-
-/* Variables used to communicate with code using scanner.  */
-extern SymbolTable *matheval_symbol_table; /* Evaluator symbol table.  */
-extern char *matheval_input_string; /* String representing function.  */
-
-/* Read next max_size character from string into buffer.  */
-static int input_from_string (char *buffer, int max_size);
-/* Token definitions.  */
-#line 573 "scanner.yy.cpp"
-
-#define INITIAL 0
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-static int yy_init_globals (void );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int mewrap (void );
-#else
-extern int mewrap (void );
-#endif
-#endif
-
-    static void yyunput (int c,char *buf_ptr  );
-    
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int );
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * );
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (void );
-#else
-static int input (void );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO (void) fwrite( metext, meleng, 1, meout )
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
-		{ \
-		int c = '*'; \
-		size_t n; \
-		for ( n = 0; n < max_size && \
-			     (c = getc( mein )) != EOF && c != '\n'; ++n ) \
-			buf[n] = (char) c; \
-		if ( c == '\n' ) \
-			buf[n++] = (char) c; \
-		if ( c == EOF && ferror( mein ) ) \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-		result = n; \
-		} \
-	else \
-		{ \
-		errno=0; \
-		while ( (result = fread(buf, 1, max_size, mein))==0 && ferror(mein)) \
-			{ \
-			if( errno != EINTR) \
-				{ \
-				YY_FATAL_ERROR( "input in flex scanner failed" ); \
-				break; \
-				} \
-			errno=0; \
-			clearerr(mein); \
-			} \
-		}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
-#endif
-
-/* end tables serialization structures and prototypes */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int melex (void);
-
-#define YY_DECL int melex (void)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after metext and meleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
-    
-#line 58 "scanner.l"
-
-
-#line 729 "scanner.yy.cpp"
-
-	if ( !(yy_init) )
-		{
-		(yy_init) = 1;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! (yy_start) )
-			(yy_start) = 1;	/* first start state */
-
-		if ( ! mein )
-			mein = stdin;
-
-		if ( ! meout )
-			meout = stdout;
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			meensure_buffer_stack ();
-			YY_CURRENT_BUFFER_LVALUE =
-				me_create_buffer(mein,YY_BUF_SIZE );
-		}
-
-		me_load_buffer_state( );
-		}
-
-	while ( 1 )		/* loops until end-of-file is reached */
-		{
-		yy_cp = (yy_c_buf_p);
-
-		/* Support of metext. */
-		*yy_cp = (yy_hold_char);
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = (yy_start);
-yy_match:
-		do
-			{
-			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
-			if ( yy_accept[yy_current_state] )
-				{
-				(yy_last_accepting_state) = yy_current_state;
-				(yy_last_accepting_cpos) = yy_cp;
-				}
-			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-				{
-				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 87 )
-					yy_c = yy_meta[(unsigned int) yy_c];
-				}
-			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-			++yy_cp;
-			}
-		while ( yy_base[yy_current_state] != 156 );
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-		if ( yy_act == 0 )
-			{ /* have to back up */
-			yy_cp = (yy_last_accepting_cpos);
-			yy_current_state = (yy_last_accepting_state);
-			yy_act = yy_accept[yy_current_state];
-			}
-
-		YY_DO_BEFORE_ACTION;
-
-do_action:	/* This label is used only to access EOF actions. */
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = (yy_hold_char);
-			yy_cp = (yy_last_accepting_cpos);
-			yy_current_state = (yy_last_accepting_state);
-			goto yy_find_action;
-
-case 1:
-YY_RULE_SETUP
-#line 60 "scanner.l"
-
-	YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 62 "scanner.l"
-{
-  /* Create node representing constant with appropriate value.  */
-  melval.node = node_create ('c', atof (metext));
-  return NUMBER;
-}
-	YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 68 "scanner.l"
-{
-  /* Find symbol table record corresponding to function name.  */
-  melval.record = symbol_table_lookup (matheval_symbol_table, metext);
-  return FUNCTION;
-}
-	YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 74 "scanner.l"
-{
-  Record *record; /* Symbol table record.  */
-  /* Inserty variable into symbol table.  */
-  record = symbol_table_insert (matheval_symbol_table, metext, 'v');
-  melval.node = node_create ('v', record);
-  return VARIABLE;
-}
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 82 "scanner.l"
-{
-  return '+';
-}
-	YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 86 "scanner.l"
-{
-  return '-';
-}
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 90 "scanner.l"
-{
-  return '*';
-}
-	YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 94 "scanner.l"
-{
-  return '/';
-}
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 98 "scanner.l"
-{
-  return '^';
-}
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 102 "scanner.l"
-{
-  return '(';
-}
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 106 "scanner.l"
-{
-  return ')';
-}
-	YY_BREAK
-case 12:
-/* rule 12 can match eol */
-YY_RULE_SETUP
-#line 110 "scanner.l"
-{
-  return '\n';
-}
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 114 "scanner.l"
-ECHO;
-	YY_BREAK
-#line 908 "scanner.yy.cpp"
-case YY_STATE_EOF(INITIAL):
-	yyterminate();
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = (yy_hold_char);
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed mein at a new source and called
-			 * melex().  If so, then we have to assure
-			 * consistency between YY_CURRENT_BUFFER and our
-			 * globals.  Here is the right place to do so, because
-			 * this is the first action (other than possibly a
-			 * back-up) that will match for the new input source.
-			 */
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = mein;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_c_buf_p will
-		 * already have been incremented past the NUL character
-		 * (since all states make transitions on EOB to the
-		 * end-of-buffer state).  Contrast this with the test
-		 * in input().
-		 */
-		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state(  );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_get_previous_state() go ahead and do it
-			 * for us because it doesn't know how to deal
-			 * with the possibility of jamming (and we don't
-			 * want to build jamming into it because then it
-			 * will run more slowly).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state );
-
-			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++(yy_c_buf_p);
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = (yy_c_buf_p);
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer(  ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				(yy_did_buffer_switch_on_eof) = 0;
-
-				if ( mewrap( ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * metext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				(yy_c_buf_p) =
-					(yytext_ptr) + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				(yy_c_buf_p) =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-} /* end of melex */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- *	EOB_ACT_LAST_MATCH -
- *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- *	EOB_ACT_END_OF_FILE - end of file
- */
-static int yy_get_next_buffer (void)
-{
-    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = (yytext_ptr);
-	register int number_to_move, i;
-	int ret_val;
-
-	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
-			{
-			/* We matched a single character, the EOB, so
-			 * treat this as a final EOF.
-			 */
-			return EOB_ACT_END_OF_FILE;
-			}
-
-		else
-			{
-			/* We matched some text prior to the EOB, first
-			 * process it.
-			 */
-			return EOB_ACT_LAST_MATCH;
-			}
-		}
-
-	/* Try to read more data. */
-
-	/* First move last chars to start of buffer. */
-	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
-
-	else
-		{
-			int num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-		while ( num_to_read <= 0 )
-			{ /* Not enough room in the buffer - grow it. */
-
-			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
-			int yy_c_buf_p_offset =
-				(int) ((yy_c_buf_p) - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					merealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			(yy_n_chars), num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	if ( (yy_n_chars) == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			merestart(mein  );
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	(yy_n_chars) += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
-
-	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (void)
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
-    
-	yy_current_state = (yy_start);
-
-	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
-		{
-		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
-		if ( yy_accept[yy_current_state] )
-			{
-			(yy_last_accepting_state) = yy_current_state;
-			(yy_last_accepting_cpos) = yy_cp;
-			}
-		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-			{
-			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 87 )
-				yy_c = yy_meta[(unsigned int) yy_c];
-			}
-		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
-{
-	register int yy_is_jam;
-    	register char *yy_cp = (yy_c_buf_p);
-
-	register YY_CHAR yy_c = 1;
-	if ( yy_accept[yy_current_state] )
-		{
-		(yy_last_accepting_state) = yy_current_state;
-		(yy_last_accepting_cpos) = yy_cp;
-		}
-	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-		{
-		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 87 )
-			yy_c = yy_meta[(unsigned int) yy_c];
-		}
-	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 86);
-
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-    static void yyunput (int c, register char * yy_bp )
-{
-	register char *yy_cp;
-    
-    yy_cp = (yy_c_buf_p);
-
-	/* undo effects of setting up metext */
-	*yy_cp = (yy_hold_char);
-
-	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-		{ /* need to shift things up to make room */
-		/* +2 for EOB chars. */
-		register int number_to_move = (yy_n_chars) + 2;
-		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
-					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
-		register char *source =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
-
-		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			*--dest = *--source;
-
-		yy_cp += (int) (dest - source);
-		yy_bp += (int) (dest - source);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
-
-		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-			YY_FATAL_ERROR( "flex scanner push-back overflow" );
-		}
-
-	*--yy_cp = (char) c;
-
-	(yytext_ptr) = yy_bp;
-	(yy_hold_char) = *yy_cp;
-	(yy_c_buf_p) = yy_cp;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (void)
-#else
-    static int input  (void)
-#endif
-
-{
-	int c;
-    
-	*(yy_c_buf_p) = (yy_hold_char);
-
-	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_c_buf_p now points to the character we want to return.
-		 * If this occurs *before* the EOB characters, then it's a
-		 * valid NUL; if not, then we've hit the end of the buffer.
-		 */
-		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			/* This was really a NUL. */
-			*(yy_c_buf_p) = '\0';
-
-		else
-			{ /* need more input */
-			int offset = (yy_c_buf_p) - (yytext_ptr);
-			++(yy_c_buf_p);
-
-			switch ( yy_get_next_buffer(  ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_g_n_b()
-					 * sees that we've accumulated a
-					 * token and flags that we need to
-					 * try matching the token before
-					 * proceeding.  But for input(),
-					 * there's no matching to consider.
-					 * So convert the EOB_ACT_LAST_MATCH
-					 * to EOB_ACT_END_OF_FILE.
-					 */
-
-					/* Reset buffer status. */
-					merestart(mein );
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( mewrap( ) )
-						return 0;
-
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput();
-#else
-					return input();
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					(yy_c_buf_p) = (yytext_ptr) + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
-	*(yy_c_buf_p) = '\0';	/* preserve metext */
-	(yy_hold_char) = *++(yy_c_buf_p);
-
-	return c;
-}
-#endif	/* ifndef YY_NO_INPUT */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- * 
- * @note This function does not reset the start condition to @c INITIAL .
- */
-    void merestart  (FILE * input_file )
-{
-    
-	if ( ! YY_CURRENT_BUFFER ){
-        meensure_buffer_stack ();
-		YY_CURRENT_BUFFER_LVALUE =
-            me_create_buffer(mein,YY_BUF_SIZE );
-	}
-
-	me_init_buffer(YY_CURRENT_BUFFER,input_file );
-	me_load_buffer_state( );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * 
- */
-    void me_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
-{
-    
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		mepop_buffer_state();
-	 *		mepush_buffer_state(new_buffer);
-     */
-	meensure_buffer_stack ();
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	me_load_buffer_state( );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (mewrap()) processing, but the only time this flag
-	 * is looked at is after mewrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-static void me_load_buffer_state  (void)
-{
-    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	mein = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	(yy_hold_char) = *(yy_c_buf_p);
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * 
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE me_create_buffer  (FILE * file, int  size )
-{
-	YY_BUFFER_STATE b;
-    
-	b = (YY_BUFFER_STATE) mealloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in me_create_buffer()" );
-
-	b->yy_buf_size = size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) mealloc(b->yy_buf_size + 2  );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in me_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	me_init_buffer(b,file );
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with me_create_buffer()
- * 
- */
-    void me_delete_buffer (YY_BUFFER_STATE  b )
-{
-    
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		mefree((void *) b->yy_ch_buf  );
-
-	mefree((void *) b  );
-}
-
-#ifndef __cplusplus
-extern int isatty (int );
-#endif /* __cplusplus */
-    
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a merestart() or at EOF.
- */
-    static void me_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
-
-{
-	int oerrno = errno;
-    
-	me_flush_buffer(b );
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then me_init_buffer was _probably_
-     * called from merestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-    
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * 
- */
-    void me_flush_buffer (YY_BUFFER_STATE  b )
-{
-    	if ( ! b )
-		return;
-
-	b->yy_n_chars = 0;
-
-	/* We always need two end-of-buffer characters.  The first causes
-	 * a transition to the end-of-buffer state.  The second causes
-	 * a jam in that state.
-	 */
-	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		me_load_buffer_state( );
-}
-
-/** Pushes the new state onto the stack. The new state becomes
- *  the current state. This function will allocate the stack
- *  if necessary.
- *  @param new_buffer The new state.
- *  
- */
-void mepush_buffer_state (YY_BUFFER_STATE new_buffer )
-{
-    	if (new_buffer == NULL)
-		return;
-
-	meensure_buffer_stack();
-
-	/* This block is copied from me_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		(yy_buffer_stack_top)++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from me_switch_to_buffer. */
-	me_load_buffer_state( );
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  
- */
-void mepop_buffer_state (void)
-{
-    	if (!YY_CURRENT_BUFFER)
-		return;
-
-	me_delete_buffer(YY_CURRENT_BUFFER );
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if ((yy_buffer_stack_top) > 0)
-		--(yy_buffer_stack_top);
-
-	if (YY_CURRENT_BUFFER) {
-		me_load_buffer_state( );
-		(yy_did_buffer_switch_on_eof) = 1;
-	}
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void meensure_buffer_stack (void)
-{
-	int num_to_alloc;
-    
-	if (!(yy_buffer_stack)) {
-
-		/* First allocation is just for 2 elements, since we don't know if this
-		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
-		 * immediate realloc on the next call.
-         */
-		num_to_alloc = 1;
-		(yy_buffer_stack) = (struct yy_buffer_state**)mealloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		
-		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
-		(yy_buffer_stack_max) = num_to_alloc;
-		(yy_buffer_stack_top) = 0;
-		return;
-	}
-
-	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		int grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = (yy_buffer_stack_max) + grow_size;
-		(yy_buffer_stack) = (struct yy_buffer_state**)merealloc
-								((yy_buffer_stack),
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-
-		/* zero only the new slots.*/
-		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
-		(yy_buffer_stack_max) = num_to_alloc;
-	}
-}
-
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- * 
- * @return the newly allocated buffer state object. 
- */
-YY_BUFFER_STATE me_scan_buffer  (char * base, yy_size_t  size )
-{
-	YY_BUFFER_STATE b;
-    
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return 0;
-
-	b = (YY_BUFFER_STATE) mealloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in me_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	me_switch_to_buffer(b  );
-
-	return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to melex() will
- * scan from a @e copy of @a str.
- * @param str a NUL-terminated string to scan
- * 
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- *       me_scan_bytes() instead.
- */
-YY_BUFFER_STATE me_scan_string (yyconst char * yystr )
-{
-    
-	return me_scan_bytes(yystr,strlen(yystr) );
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to melex() will
- * scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
- * 
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE me_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	int i;
-    
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = _yybytes_len + 2;
-	buf = (char *) mealloc(n  );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in me_scan_bytes()" );
-
-	for ( i = 0; i < _yybytes_len; ++i )
-		buf[i] = yybytes[i];
-
-	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = me_scan_buffer(buf,n );
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in me_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg )
-{
-    	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up metext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		metext[meleng] = (yy_hold_char); \
-		(yy_c_buf_p) = metext + yyless_macro_arg; \
-		(yy_hold_char) = *(yy_c_buf_p); \
-		*(yy_c_buf_p) = '\0'; \
-		meleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the current line number.
- * 
- */
-int meget_lineno  (void)
-{
-        
-    return melineno;
-}
-
-/** Get the input stream.
- * 
- */
-FILE *meget_in  (void)
-{
-        return mein;
-}
-
-/** Get the output stream.
- * 
- */
-FILE *meget_out  (void)
-{
-        return meout;
-}
-
-/** Get the length of the current token.
- * 
- */
-int meget_leng  (void)
-{
-        return meleng;
-}
-
-/** Get the current token.
- * 
- */
-
-char *meget_text  (void)
-{
-        return metext;
-}
-
-/** Set the current line number.
- * @param line_number
- * 
- */
-void meset_lineno (int  line_number )
-{
-    
-    melineno = line_number;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * 
- * @see me_switch_to_buffer
- */
-void meset_in (FILE *  in_str )
-{
-        mein = in_str ;
-}
-
-void meset_out (FILE *  out_str )
-{
-        meout = out_str ;
-}
-
-int meget_debug  (void)
-{
-        return me_flex_debug;
-}
-
-void meset_debug (int  bdebug )
-{
-        me_flex_debug = bdebug ;
-}
-
-static int yy_init_globals (void)
-{
-        /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from melex_destroy(), so don't allocate here.
-     */
-
-    (yy_buffer_stack) = 0;
-    (yy_buffer_stack_top) = 0;
-    (yy_buffer_stack_max) = 0;
-    (yy_c_buf_p) = (char *) 0;
-    (yy_init) = 0;
-    (yy_start) = 0;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    mein = stdin;
-    meout = stdout;
-#else
-    mein = (FILE *) 0;
-    meout = (FILE *) 0;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * melex_init()
-     */
-    return 0;
-}
-
-/* melex_destroy is for both reentrant and non-reentrant scanners. */
-int melex_destroy  (void)
-{
-    
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		me_delete_buffer(YY_CURRENT_BUFFER  );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		mepop_buffer_state();
-	}
-
-	/* Destroy the stack itself. */
-	mefree((yy_buffer_stack) );
-	(yy_buffer_stack) = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * melex() is called, initialization will occur. */
-    yy_init_globals( );
-
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
-{
-	register int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s )
-{
-	register int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *mealloc (yy_size_t  size )
-{
-	return (void *) malloc( size );
-}
-
-void *merealloc  (void * ptr, yy_size_t  size )
-{
-	/* The cast to (char *) in the following accommodates both
-	 * implementations that use char* generic pointers, and those
-	 * that use void* generic pointers.  It works with the latter
-	 * because both ANSI C and C++ allow castless assignment from
-	 * any pointer type to void*, and deal with argument conversions
-	 * as though doing an assignment.
-	 */
-	return (void *) realloc( (char *) ptr, size );
-}
-
-void mefree (void * ptr )
-{
-	free( (char *) ptr );	/* see merealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 114 "scanner.l"
-
-
-
-#undef mewrap
-
-int mewrap() { return 1; }
-
-static int input_from_string (char *buffer, int max_size)
-{
-  int count; /* Count of characters to copy from input string to buffer.  */
-
-  /* Calculate count of characters to copy.  */
-  count = strlen (matheval_input_string);
-  if (count > max_size)
-    count = max_size;
-
-  /* Perform copy operation and update input string.  */
-  memcpy(buffer, matheval_input_string, count);
-  matheval_input_string += count;
-
-  return count;
-}
-
-void force_buffer_flush() { YY_FLUSH_BUFFER; }
-
diff --git a/contrib/MathEval/symbol_table.cpp b/contrib/MathEval/symbol_table.cpp
deleted file mode 100644
index 5819936fccb61420c5d533017ac73377b685ed4f..0000000000000000000000000000000000000000
--- a/contrib/MathEval/symbol_table.cpp
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (C) 1999, 2002, 2003  Free Software Foundation, Inc.
- *
- * This file is part of GNU libmatheval
- *
- * GNU libmatheval is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2, or (at your option) any later
- * version.
- *
- * GNU libmatheval is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* This file was modified for inclusion in Gmsh */
-
-#include <assert.h>
-#include <stdarg.h>
-
-#include "common.h"
-#include "symbol_table.h"
-#include "xmath.h"
-#include <iostream>
-
-/*
- * Type definition for function accepting single argument of double type and
- * returning double value.
- */
-typedef double (*function_type) (double);
-
-/* Calculate hash value for given name and hash table length.  */
-static int hash(char *name, int length);
-
-SymbolTable *
-symbol_table_create(int length)
-{
-  SymbolTable    *symbol_table;	/* Pointer to symbol table.  */
-  static char    *names[] = {"Exp", "Log", "Sqrt", "Sin", "Cos", "Tan", "Ctan", 
-			     "Asin", "Acos", "Atan", "Actan", "Sinh", "Cosh", "Tanh",
-			     "Ctanh", "Asinh", "Acosh", "Atanh", "Actanh", "Fabs", 
-			     "Rand", "Log10" , "Step", "Delta", "NanDelta", "Floor", "HeavS"};
-  static double   (*functions[]) (double) = { exp, log, sqrt, sin, cos, tan, x_ctan, 
-					      asin, acos, atan, x_actan, sinh, cosh, tanh, 
-					      x_ctanh, x_asinh, x_acosh, x_atanh, x_actanh,
-					      fabs, x_rand, log10, x_step, x_delta , x_nandelta, floor, x_heavs};
-  unsigned int i;
-  
-  /*
-   * Allocate memory for symbol table data structure as well as for
-   * corresponding hash table.
-   */
-  symbol_table = XMALLOC(SymbolTable, 1);
-  symbol_table->length = length;
-  symbol_table->records = XCALLOC(Record, symbol_table->length);
-  
-  /*
-   * Insert predefined functions into symbol table.
-   */
-  for (i = 0; i < sizeof(names) / sizeof(names[0]); i++)
-    symbol_table_insert(symbol_table, names[i], 'f', functions[i]);
-  
-  /*
-   * Initialize symbol table reference count.
-   */
-  symbol_table->reference_count = 1;
-  
-  return symbol_table;
-}
-
-void
-symbol_table_destroy(SymbolTable * symbol_table)
-{
-  Record         *curr, *next; /* Pointers to current and next record
-				* while traversing hash table bucket.  */
-  int             i;
-
-  if(!symbol_table)
-    return;
-  
-  /*
-   * Decrement refernce count and return if symbol table still used
-   * elsewhere.
-   */
-  if (--symbol_table->reference_count > 0)
-    return;
-  
-  /*
-   * Delete hash table as well as data structure representing symbol
-   * table.
-   */
-  for (i = 0; i < symbol_table->length; i++)
-    for (curr = symbol_table->records[i].next; curr;) {
-      next = curr->next;
-      XFREE(curr->name);
-      XFREE(curr);
-      curr = next;
-    }
-  XFREE(symbol_table->records);
-  XFREE(symbol_table);
-}
-
-Record *
-symbol_table_insert(SymbolTable * symbol_table, char *name, char type,...)
-{
-  Record         *record;	/* Pointer to symbol table record
-				 * corresponding to name given.  */
-  va_list         ap;		/* Function variable argument list.  */
-  int             i;
-  
-  /*
-   * Check if symbol already in table and, if affirmative and record
-   * type same as type given, return corresponding record immediately.
-   */
-  if ((record = symbol_table_lookup(symbol_table, name))) {
-    assert(record->type == type);
-    return record;
-  }
-  /*
-   * Allocate memory for and initialize new record.
-   */
-  record = XMALLOC(Record, 1);
-  record->name = XMALLOC(char, strlen(name) + 1);
-  strcpy(record->name, name);
-  record->type = type;
-  
-  /*
-   * Parse function variable argument list to complete record
-   * initialization.
-   */
-  va_start(ap, type);
-  switch (record->type) {
-  case 'v':
-    record->data.value = 0;
-    break;
-    
-  case 'f':
-    record->data.function = va_arg(ap, function_type);
-    break;
-  }
-  va_end(ap);
-  
-  /*
-   * Calculate hash value and put record in corresponding hash table
-   * bucket.
-   */
-  i = hash(name, symbol_table->length);
-  record->next = symbol_table->records[i].next;
-  symbol_table->records[i].next = record;
-  
-  return record;
-}
-
-Record *
-symbol_table_lookup(SymbolTable * symbol_table, char *name)
-{
-  int             i;	/* Hash value. */
-  Record         *curr;	/* Pointer to current symbol table record.  */
-  
-  /*
-   * Calcuate hash value for name given.
-   */
-  i = hash(name, symbol_table->length);
-  
-  /*
-   * Lookup for name in hash table bucket corresponding to above hash
-   * value.
-   */
-  for (curr = symbol_table->records[i].next; curr; curr = curr->next)
-    if (!strcmp(curr->name, name))
-      return curr;
-  
-  return NULL;
-}
-
-SymbolTable *
-symbol_table_assign(SymbolTable * symbol_table)
-{
-  /*
-   * Increase symbol table reference count and return pointer to data
-   * structure representing table.
-   */
-  symbol_table->reference_count++;
-  return symbol_table;
-}
-
-/*
- * Function below reused from A.V. Aho, R. Sethi, J.D. Ullman, "Compilers -
- * Principle, Techniques, and Tools", Addison-Wesley, 1986, pp 435-437, and
- * in turn from P.J. Weineberger's C compiler.
- */
-static int
-hash(char *s, int n)
-{
-  char           *p;
-  unsigned        h, g;
-  
-  h = 0;
-  
-  for (p = s; *p; p++) {
-    h = (h << 4) + *p;
-    if ((g = h & 0xf0000000)) {
-      h = h ^ (g >> 24);
-      h = h ^ g;
-    }
-  }
-  
-  return h % n;
-}
-
-void
-symbol_table_clear_flags(SymbolTable * symbol_table)
-{
-	Record         *curr;	/* Pointer to current symbol table record
-				 * while traversing hash table bucket. */
-	int             i;	/* Loop counter.  */
-
-	/* Clear flag for all records in symbol table. */
-	for (i = 0; i < symbol_table->length; i++)
-		for (curr = symbol_table->records[i].next; curr;
-		     curr = curr->next)
-			curr->flag = false;
-}
-
-int
-symbol_table_get_flagged_count(SymbolTable * symbol_table)
-{
-	int             count;	/* Number of flagged symbol table records. 
-				 */
-	Record         *curr;	/* Pointer to current symbol table record
-				 * while traversing hash table bucket. */
-	int             i;	/* Loop counter.  */
-
-	/* Calculate number of records in symbol table with flag set. */
-	count = 0;
-	for (i = 0; i < symbol_table->length; i++)
-		for (curr = symbol_table->records[i].next; curr;
-		     curr = curr->next)
-			if (curr->flag)
-				count++;
-	return count;
-}
-
-int
-symbol_table_get_flagged(SymbolTable * symbol_table, Record ** records,
-			 int length)
-{
-	int             count;	/* Number of pointers to symbol table
-				 * records put into given array. */
-	Record         *curr;	/* Pointers to current symbol table record 
-				 * while traversing hash table bucket.  */
-	int             i;	/* Loop counter.  */
-
-	/* Put pointers to records in symbol table with flag set into
-	 * given array. */
-	count = 0;
-	for (i = 0; i < symbol_table->length; i++)
-		for (curr = symbol_table->records[i].next; curr;
-		     curr = curr->next)
-			if (curr->flag) {
-				records[count++] = curr;
-				if (count == length)
-					return count;
-			}
-	return count;
-}
diff --git a/contrib/MathEval/symbol_table.h b/contrib/MathEval/symbol_table.h
deleted file mode 100644
index d6d75b4f0eb528ba4ccf6f978824f9574c526569..0000000000000000000000000000000000000000
--- a/contrib/MathEval/symbol_table.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 1999, 2002, 2003  Free Software Foundation, Inc.
- * 
- * This file is part of GNU libmatheval
- * 
- * GNU libmatheval is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2, or (at your option) any later
- * version.
- * 
- * GNU libmatheval is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* This file was modified for inclusion in Gmsh */
-
-#ifndef SYMBOL_TABLE_H
-#define SYMBOL_TABLE_H
-
-/* Data structure representing symbol table record.  */
-typedef struct _Record {
-  struct _Record *next;	/* Pointer to next record.  */
-  char *name; /* Symbol name.  */
-  char type; /* Symbol type ('v' for variable, 'f' for function).  */
-  union {
-    double value; /* Variable value.  */
-    double (*function) (double); /* Pointer to function to calculate
-				  * its value.  */
-  } data;
-	int             flag;	/* Record flag used for symbol table
-				 * selective traversal.  */
-} Record;
-
-/*
- * Data structure representing symbol table (hash table is used for this
- * purpose).
- */
-typedef struct {
-  int length; /* Hash table length.  */
-  Record  *records; /* Hash table buckets.  */
-  int reference_count; /* Reference count for symbol table (evaluator
-			* for derivative uses same symbol table as
-			* evaluator for corresponding function).  */
-} SymbolTable;
-
-/* Create symbol table using specified length of hash table.  */
-SymbolTable *symbol_table_create(int length);
-
-/* Destroy symbol table.  */
-void symbol_table_destroy(SymbolTable * symbol_table);
-
-/*
- * Insert symbol into given symbol table.  Further arguments are symbol name
- * and its type, as well as additional arguments according to symbol type.
- * Return value is pointer to symobl table record created to represent
- * symbol.  If symbol already in symbol table, pointer to its record is
- * returned immediately.
- */
-Record *symbol_table_insert(SymbolTable * symbol_table, char *name, char type,...);
-
-/*
- * Lookup symbol by name from given symbol table.  Pointer to symbol record
- * is returned if symbol found, null pointer otherwise.
- */
-Record *symbol_table_lookup(SymbolTable * symbol_table, char *name);
-
-/*
- * Return symbol table pointer to be assigned to variable.  This function
- * should be used instead of simple pointer assignement for proper reference
- * counting.  Users willing to manage reference counts by themselves are free
- * to ignore this functions.
- */
-SymbolTable *symbol_table_assign(SymbolTable * symbol_table);
-
-/* Clear flag for each symbol table record. */
-void            symbol_table_clear_flags(SymbolTable * symbol_table);
-
-/* Count number of flagged records in symbol table. */
-int             symbol_table_get_flagged_count(SymbolTable * symbol_table);
-
-/* Fill given array with pointers to records from given symbol table that
- * have flag set.  Further arguments are array to store pointers and array 
- * capacity.  Number of records that are actually put into array is
- * returned. */
-int             symbol_table_get_flagged(SymbolTable * symbol_table,
-					 Record ** records, int length);
-#endif
diff --git a/contrib/MathEval/xmath.cpp b/contrib/MathEval/xmath.cpp
deleted file mode 100644
index 8a6b0197a02f76d02f80c5f7228ab7d254076f4f..0000000000000000000000000000000000000000
--- a/contrib/MathEval/xmath.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 1999, 2002, 2003  Free Software Foundation, Inc.
- *
- * This file is part of GNU libmatheval
- *
- * GNU libmatheval is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2, or (at your option) any later
- * version.
- *
- * GNU libmatheval is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* This file was modified for inclusion in Gmsh */
-
-#include "xmath.h"
-#include <math.h>
-#include <stdlib.h>
-#include <cmath>
-#include <stdio.h>
-
-using std::fabs;
-
-double
-x_ctan(double x)
-{
-  /*
-   * Calculate cotangent value.
-   */
-  return 1 / tan(x);
-}
-
-double
-x_actan(double x)
-{
-  /*
-   * Calculate inverse cotangent value.
-   */
-  return atan(1 / x);
-}
-
-double
-x_ctanh(double x)
-{
-  /*
-   * Calculate hyperbolic cotangent value.
-   */
-  return 1 / tanh(x);
-}
-
-double
-x_asinh(double x)
-{
-  /*
-   * Calculate inverse hyperbolic sine value using relation between
-   * hyperbolic and exponential functions.
-   */
-  return log(x + sqrt(x * x + 1));
-}
-
-double
-x_acosh(double x)
-{
-  /*
-   * Calculate inverse hyperbolic cosine value using relation between
-   * hyperbolic and exponential functions.
-   */
-  return log(x + sqrt(x * x - 1));
-}
-
-double
-x_atanh(double x)
-{
-  /*
-   * Calculate inverse hyperbolic tangent value using relation between
-   * hyperbolic and exponential functions.
-   */
-  return 0.5 * log((1 + x) / (1 - x));
-}
-
-double
-x_actanh(double x)
-{
-  /*
-   * Calculate inverse hyperbolic cotangent value.
-   */
-  return 0.5 * log((x + 1) / (x - 1));
-}
-
-double
-x_rand(double x)
-{
-  /*
-   * Calculate random value in [0, x].
-   */
-  
-  return x*(double)rand()/(double)RAND_MAX;
-}
-double
-x_step(double x)
-{
-	/* 
-	 * Calculate step function value.
-	 */
-	return (x < 0) ? 0 : 1;
-}
-
-double
-x_heavs(double x) //, double eps)
-{
-	/* 
-	 * Calculate smoothed heaviside function value.
-	 */
-  double eps=3.0;
-         return (fabs(x) < eps) ? 0.5*(1+ x/eps +1/3.14*sin(3.14*x/eps)):(x<0? 0:1);
-}
-
-#if !defined(INFINITY)
-#define INFINITY 1.e100
-#endif
-
-#if !defined(NAN)
-#define NAN 1.e100
-#endif
-
-double
-x_delta(double x)
-{
-	/* 
-	 * Calculate delta function value.
-	 */
-	return (x == 0) ? INFINITY : 0;
-}
-
-double
-x_nandelta(double x)
-{
-	/* 
-	 * Calculate modified delta function value.
-	 */
-	return (x == 0) ? NAN : 0;
-}
-
diff --git a/contrib/MathEval/xmath.h b/contrib/MathEval/xmath.h
deleted file mode 100644
index 62003a22973a615acb295c8652ed855249ea7229..0000000000000000000000000000000000000000
--- a/contrib/MathEval/xmath.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 1999, 2002, 2003  Free Software Foundation, Inc.
- * 
- * This file is part of GNU libmatheval
- * 
- * GNU libmatheval is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2, or (at your option) any later
- * version.
- * 
- * GNU libmatheval is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- * 
- * You should have received a copy of the GNU General Public License along with
- * program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* This file was modified for inclusion in Gmsh */
-
-#ifndef XMATH_H
-#define XMATH_H
-
-double x_ctan(double x);
-double x_actan(double x);
-double x_ctanh(double x);
-double x_asinh(double x);
-double x_acosh(double x);
-double x_atanh(double x);
-double x_actanh(double x);
-double x_rand(double x);
-double x_step(double x);
-double x_heavs(double x);
-double x_delta(double x);
-double x_nandelta(double x);
-
-#endif
diff --git a/contrib/TreeBrowser/CMakeLists.txt b/contrib/MathEx/CMakeLists.txt
similarity index 72%
rename from contrib/TreeBrowser/CMakeLists.txt
rename to contrib/MathEx/CMakeLists.txt
index 1ba08e3011b7d27d40b3682c1a6970196575a674..94a6dbe5f80d13790a022807b7aed4625493352d 100644
--- a/contrib/TreeBrowser/CMakeLists.txt
+++ b/contrib/MathEx/CMakeLists.txt
@@ -4,7 +4,7 @@
 # bugs and problems to <gmsh@geuz.org>.
 
 set(SRC
-  Flu_Tree_Browser.cpp
+  mathex.cpp
 )
 
-append_gmsh_src(contrib/TreeBrowser "${SRC}")
+append_gmsh_src(contrib/MathEx "${SRC}")
diff --git a/contrib/MathEx/lesser.txt b/contrib/MathEx/lesser.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3f50d0454c7d886c6f8d551e2e8b1a86f17e3713
--- /dev/null
+++ b/contrib/MathEx/lesser.txt
@@ -0,0 +1,506 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  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 combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  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
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
+
+
diff --git a/contrib/MathEx/license.txt b/contrib/MathEx/license.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1bc419433b75a3d9e095f1cfbf740722b0fece97
--- /dev/null
+++ b/contrib/MathEx/license.txt
@@ -0,0 +1,35 @@
+BMP libray License
+------------------
+
+The MathEx library and included programs are part of SSCILIB and provided under
+the terms of the GNU Library/Lesser General Public License (LGPL) 2.1 or latter,
+with following static linking exceptions:
+
+   1. The combined work statically linked with unmodified MathEx library will
+distributed under your own license.
+
+   2. The application or libraries statically linked with MathEx library must identify 
+their use of SSCILIB library. For example, text like
+"[application/library] is based in part on the work of the SSCILIB Library
+ (http://sscilib.sourceforge.net/)" 
+will included in document or help to satisfy this requirement.
+
+   3. The folowing five modifications on MathEx library in way to fit your 
+requirement does not implies in modification of source code:
+    i. Modification of the MathEx config script, makefiles or instalation tools.
+   ii. change of name space definition
+using namespace smlib
+to other one (need if it conflict with other library)
+
+   4. The modifications of source code implies in the GNU Library/Lesser General Public License 2.1 or latter, without this static linking exceptions.
+
+End of license term
+-------------------
+
+For GNU Library/lesser General Public License, see the lesser.txt or visit
+http://www.gnu.org/
+
+June of 2003.
+
+Sadao Massago
+http://www2.dm.ufscar.br/~sadao
diff --git a/contrib/MathEx/mathex.cpp b/contrib/MathEx/mathex.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c09e220784a1626d94950da6aa8c8be80709c721
--- /dev/null
+++ b/contrib/MathEx/mathex.cpp
@@ -0,0 +1,1024 @@
+///////////////////////////////////////////////////////////////////////////
+// mathex 0.2.3 (beta) - Copyright (C) 2000-2003, by Sadao Massago       //
+// file: mathex.h (math expression evaluator header file)                //
+// requires: none                                                        //
+// project web page: http://sscilib.sourceforge.net/                     //
+// ----------------------------------------------------------------------//
+// The mathex library and related files is licenced under the term of    //
+// GNU LGPL (Lesser General Public License) version 2.1 or latter        //
+// with exceptions that allow for static linking.                        //
+// See license.txt for detail.                                           //
+// For GNU LGPL, see lesser.txt.                                         //
+// For information over GNU or GNU compatible license, visit the site    //
+// http://www.gnu.org.                                                   //
+///////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+// references:
+//-------------------------------------------------------------------------
+// title: Algoritms and Data Structures
+// author: Niklaus Wirth
+// publisher: Prentice-Hall
+// year: 1989
+//-------------------------------------------------------------------------
+// title: The C++ Programming Language
+// edition: thrird
+// author: Bjarne Stroustrup
+// publisher: Addilson-Wesley
+// year: 1997
+//-------------------------------------------------------------------------
+// title: building your own C interpreter
+// author: Schildt, Helbert
+// journal: Dr. Dobb's Jornal (http://www.ddj.com)
+// number: August/1989
+// pages: 38-49, 110-122
+///////////////////////////////////////////////////////////////////////////
+
+// #define _DEBUG_
+
+#include "mathex.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string>
+#include <vector>
+#include <cctype>
+// debug purpose
+#ifdef _DEBUG_
+  #include <iostream>
+#endif
+
+   namespace smlib {
+      using namespace std;
+   
+   
+   ////////////////////////////////////
+   // local variables, functions, etc
+   ////////////////////////////////////
+      namespace {
+      
+      //////////////////////////////////
+      // C function with one parameter
+      //--------------------------------
+      
+          double fac(double x)
+         // Function return the factorial of integer belong to range 0..170.
+         // in future, will implement aproximation for gamma function to evaluate for x > 170
+         {
+            double p;
+            unsigned n;
+         
+            if((x <0) || (x>170)) // maximum admited where
+               throw mathex::error("Error [fac()]: range error");
+            else {
+               n = static_cast<unsigned>(x+0.5);
+               if(x < 2)
+                  return 1;
+               else if(n == 2)
+                  return(2);
+               for(p=1;1<n;n--)
+                  p *= n;
+               return p;
+            }
+         } // fac()
+      
+      // convert radian to degree
+          double deg(double x)
+         {
+            return( x * 180.0 / M_PI);
+         } // deg()
+      
+      // convert degree to radian
+          double rad(double x)
+         {
+            return(x * M_PI / 180.0);
+         } // rad()
+      
+      // return square
+      /*    double sqr(double x)
+      {
+         return (x*x);
+      } */
+      // sqr()
+      
+      // return real part
+          double trunc(double x)
+         {
+            return static_cast<long>(x);
+         } // trunc()
+      
+      // return rounded value to int
+          double round(double x)
+         {
+            return static_cast<long>(x+0.5);
+         } // round
+      
+      // return 0 if x negative, 1 otherwise
+          double step(double x)
+         {
+           if ( x < 0 ) return static_cast<long>(0.);
+           return static_cast<long>(1.);
+         } // step
+      
+      // return -1 if x negative, 1 otherwise
+          double sign(double x)
+         {
+           if ( x < 0 ) return static_cast<long>(-1.);
+           return static_cast<long>(1.);
+         } // sign
+      
+      //////////////////////////////////////////////////////////
+      // arithmetic operators
+      //////////////////////////////////////////////////////////
+      // operators was treated in Parsingr time, to check the
+      //   operator level.
+      //   unary operator is the function double op(double) and
+      //   binary operator is function double op(double,double)
+      //--------------------------------------------------------
+      //   unary:
+      //   "+" -> none
+      //   "-" -> unary_minus
+      //   binary:
+      //   "+" -> binary_plus
+      //   "-" -> binary_minus
+      //   "*" -> binary_times
+      //   "/" -> binary_divide
+      //   "^" -> binary_power
+      //   "%" -> fmod (defined in math.h)
+      ///////////////////////////////////////////////////////////
+      
+      //////////////////////
+      // C unary operator
+      
+          double unary_minus(double x)
+         {
+            return -x;
+         } // unary_minus()
+      
+      //////////////////////////////////////////
+      // C binary operators
+      //----------------------------------------
+      
+          double binary_plus(double x, double y)
+         {
+            return x + y;
+         } // binary_plus() 
+      
+          double binary_minus(double x, double y)
+         {
+            return x - y;
+         } // binary_minus()
+      
+          double binary_times(double x, double y)
+         {
+            return x * y;
+         } // binary_timess()
+      
+          double binary_divide(double x, double y)
+         // in future, put more precisery checking, for overflow ?
+         {
+            if (y == 0)
+               throw mathex::error("Error [binary_divide()]: divisin by zero");
+            else
+               return (x/y);
+         } // binary_divide()
+      
+          double binary_power(double x, double y)
+         {
+            return pow(x,y);
+         } // binary_power()
+      
+      /////////////////////////////////////////
+      // pre-defined user defined functions
+      //---------------------------------------
+      
+          double p_rand(vector <double> const &x)
+         // rand() return value between [0,1)
+         {
+            if(x.size() != 0)
+               throw mathex::error("Error [p_rand()]: can not use argument");
+            return rand()/(RAND_MAX+1.0);
+         } // p_rand()
+      
+      // maximum
+          double p_max(vector <double> const & x)
+         {
+         
+            double maxval=0;
+         
+            if(x.size() == 0)
+               throw mathex::error("Error [p_max()]: No arguments");
+            maxval = x[0];
+            for(unsigned i=0; i<x.size(); i++)
+               if(x[i] > maxval)
+                  maxval = x[i];
+         
+            return maxval;
+         } // p_max
+      
+      // minimum
+          double p_min(vector <double> const & x)
+         {
+         
+            double minval=0;
+         
+            if(x.size() == 0)
+               throw mathex::error("Error [p_min()]: No arguments");
+            minval = x[0];
+            for(unsigned i=0; i<x.size(); i++)
+               if(x[i] < minval)
+                  minval = x[i];
+         
+            return minval;
+         } // p_min
+      
+      // sum
+          double p_sum(vector <double> const & x)
+         {
+         
+            double sumval=0;
+         
+            if(x.size() == 0)
+               throw mathex::error("Error [p_sum()]: No arguments");
+            for(unsigned i=0; i<x.size(); i++)
+               sumval += x[i];
+         
+            return sumval;
+         } // p_sum
+      
+      // average
+          double p_med(vector <double> const & x)
+         {
+            if(x.size() == 0)
+               throw mathex::error("Error [p_med()]: No arguments");
+            return p_sum(x)/x.size();
+         } // p_med()
+      
+      ////////////////////////////////
+      // function/constant tables
+      ////////////////////////////////
+      
+      //////////////////////////////////
+      // One parameter C function table
+      
+      // Record for one parameter C functions
+         typedef 
+             struct
+            {
+               const char *name;
+               double  (*f)(double x); // one parameter function
+            } CFUNCREC;
+      	
+      ///////////////////////////////////////////////////////////   
+      // One parameter internal C defined functions
+      // the unary operator are stored on first part of table
+      //---------------------------------------------------------
+      // CAUTION:
+      // if add unary operator, adjust the definiftion of NUM_UNARY_OP 
+      #define NUM_UNARY_OP 1
+         CFUNCREC cfunctable[] =
+         {
+         // name and funtion pointer
+         // first part of table is unary operators
+         {"-", unary_minus}, // unary operator
+         // seccond part of table is functions
+         { "abs",     fabs },
+         { "Abs",     fabs },
+         { "fabs",     fabs },
+         { "Fabs",     fabs },
+         { "acos",    acos },
+         { "Acos",    acos },
+         { "asin",    asin },
+         { "Asin",    asin },
+         { "atan",    atan },
+         { "Atan",    atan },
+         { "cos",     cos },
+         { "Cos",     cos },
+         { "cosh",    cosh },
+         { "Cosh",    cosh },
+         { "deg",     deg },   // added
+         { "Deg",     deg },
+         { "exp",     exp },
+         { "Exp",     exp },
+         { "fac",     fac },   // added
+         { "Fac",     fac },
+         { "log",     log },
+         { "Log",     log },
+         { "log10",   log10 },
+         { "Log10",   log10 },
+         // { "pow10",   pow10 } // in future, add it?
+         { "rad",     rad },   // added 
+         { "Rad",     rad },
+         { "round",   round }, // added
+         { "Round",   round },
+         { "sign",    sign },
+         { "Sign",    sign },
+         { "sin",     sin },
+         { "Sin",     sin },
+         { "sinh",    sinh },
+         { "Sinh",    sinh },
+         // { "sqr",     sqr }, // added
+         { "sqrt",    sqrt },
+         { "Sqrt",    sqrt },
+         { "step",    step },
+         { "Step",    step },
+         { "tan",     tan },
+         { "Tan",     tan },
+         { "tanh",    tanh },
+         { "Tanh",    tanh },
+         { "trunc",   trunc }, // added
+         { "Trunc",   trunc },
+         { "floor",   floor }, // largest integer not grather than x
+         { "Floor",   floor },
+         { "ceil",    ceil }, // smallest integer not less than x
+         { "Ceil",    ceil },
+         
+         { 0, 0 } // 0 mark the end of table
+         };
+      
+      /////////////////////
+      // binary operators
+      
+      // binary operator's record
+          class BINOPREC {
+         public:
+            char name;
+            double (*f)(double, double);
+         };
+      
+      ////////////////////
+      // binary operators
+         BINOPREC binoptable[] =
+         {
+         // name, value
+         { '+',  binary_plus},
+         { '-',  binary_minus},
+         { '*',  binary_times},
+         { '/',  binary_divide},
+         { '^',  binary_power},
+         { '%',  fmod},
+         
+         { '\0' , 0 } // '\0' mark the end of table
+         };
+      
+      //////////////
+      // constants
+      
+      // constants record
+          class CONSTREC {
+         public:
+            const char *name;
+            double value;
+         };
+      
+      /////////////
+      // constants
+         CONSTREC consttable[] =
+         {
+         // name, value
+         { "pi",  M_PI },
+         { "e",   M_E },
+         
+         { NULL, 0 } // NULL mark the end of table
+         };
+      
+      } // namespace {
+   
+   
+   ////////////////////////////
+   // implementations
+   ///////////////////////////
+   
+   ///////////////
+   // constatnts
+   /// undefined number of arguments (for user defined functions
+      const int mathex::UNDEFARGS = -1; // for user function arguments   
+   
+   ////////////////
+   // methods
+       void mathex::addstdfunc()
+      {
+         addfunc("rand", p_rand, 0);
+         addfunc("Rand", p_rand, 0);
+         addfunc("sum", p_sum, UNDEFARGS);
+         addfunc("Sum", p_sum, UNDEFARGS);
+         addfunc("max", p_max, UNDEFARGS);
+         addfunc("Max", p_max, UNDEFARGS);
+         addfunc("min", p_min, UNDEFARGS);
+         addfunc("Min", p_min, UNDEFARGS);
+         addfunc("med", p_med, UNDEFARGS);
+         addfunc("Med", p_med, UNDEFARGS);
+      } // addstdfunc()
+   
+       void mathex::reset()
+      {
+         delvar();
+         delfunc();
+         status = notparsed;
+         expr = "";
+         bytecode.clear();
+         pos = 0;
+         addstdfunc();  
+      } // reset
+   
+   /////////////////////////////////
+   // varibles table manipulations
+   
+       bool mathex::addvar(string const &name, double *var)
+      // register the program internal variable
+      {
+         unsigned i;
+      
+         for(i=0; (i<vartable.size()) && (vartable[i].name != name);i++);
+         if(i<vartable.size()) { // found! overwrite
+            vartable[i].var = var;
+            return true;
+         }
+         else if(!isnewvalidname(name))
+            return false;
+         vartable.push_back(VARREC(name, var));
+         return true;
+      } // addvar()
+   
+       bool mathex::delvar(string const &name)
+      // delete one variable
+      {
+         unsigned i;
+      
+         for(i=0; (i<vartable.size()) && (vartable[i].name != name);i++);
+         if(i < vartable.size())  {
+         // how to use erase?
+         // vartable.erase(&vartable[i],&vartable[i+1]);
+            for(unsigned j=0; j<vartable.size()-1; j++)
+               vartable[j] = vartable[j+1];
+            vartable.pop_back(); // delete last
+            status = notparsed;
+            return true;
+         }
+         else
+            return false;
+      } // delvar()
+   
+   //////////////////////////////////////////////
+   // user defined function table manipulation
+   //////////////////////////////////////////////
+   
+       bool mathex::addfunc(string const &name, double (*f)(vector<double> const &), int NumArgs)
+      // register the user defined function
+      {
+         unsigned i;
+      
+         for(i=0; (i<functable.size()) && (functable[i].name != name);i++);
+         if(i<functable.size()) { // found! overwrite
+            functable[i].f = f;
+            functable[i].numargs = NumArgs;
+            return true;
+         }
+         else if(!isnewvalidname(name))
+            return false;
+         functable.push_back(FUNCREC(name, f, NumArgs));
+         return true;
+      } // addfunc()
+   
+       bool mathex::delfunc(string const &name)
+      // delete the user defined function
+      {
+         unsigned i;
+      
+         for(i=0; (i<functable.size()) && (functable[i].name != name);i++);
+         if(i < functable.size())  {
+         // how to use erase?
+         // functable.erase(&vartable[i],&vartable[i+1]);
+            for(unsigned j=0; j<vartable.size()-1; j++)
+               functable[j] = functable[j+1];
+            functable.pop_back(); // delete last
+            return true;
+         }
+         else
+            return false;
+      } // delfunc()
+   
+   ////////////////////////////////////////////////////
+   // get the index of variables/constants/functions/
+   //     binary operator/user defined functions
+   //--------------------------------------------------
+   // return -1 if not found
+   ////////////////////////////////////////////////////
+   
+       int mathex::getconst(string const &name)
+      // get index of const
+      // return -1 if not found
+      {
+         unsigned i;
+      // look up the constants
+         for(i=0;consttable[i].name && strcmp(name.c_str(), consttable[i].name);i++);
+         if(consttable[i].name != NULL) // if found
+            return i;
+         else
+            return -1;
+      } // getconst
+   
+   
+       int mathex::getvar(string const &name)
+      // get index of variable
+      // return -1 if not found
+      {
+         unsigned i;
+      
+      // look up the table
+         for(i=0;(i<vartable.size()) && strcmp(name.c_str(), vartable[i].name.c_str());i++);
+         if(i<vartable.size()) // if found
+            return i;
+         else
+            return -1;
+      } // getvar
+   
+   
+       int mathex::getcfunc(string const &name)
+      // get index of one parameter function
+      // return -1 if not found
+      {
+         unsigned i;
+      // look up the constants
+         for(i=NUM_UNARY_OP;cfunctable[i].name && strcmp(name.c_str(), cfunctable[i].name);i++);
+         if(cfunctable[i].name != NULL) // if found
+            return i;
+         else
+            return -1;
+      } // getcfunc
+   
+       int mathex::getunaryop(string const &name)
+      // get index of unary operator
+      // return -1 if not found
+      {
+         unsigned i;
+      // look up the constants
+         for(i=0; cfunctable[i].name && strcmp(name.c_str(), cfunctable[i].name);i++);
+         if(cfunctable[i].name != NULL) // if found
+            return i;
+         else
+            return -1;
+      } // getunaryop
+   
+       int mathex::getbinop(char name)
+      // get index of one parameter function
+      // return -1 if not found
+      {
+         unsigned i;
+      // look up the constants
+         for(i=0;binoptable[i].name && (name != binoptable[i].name);i++);
+         if(binoptable[i].name != '\0') // if found
+            return i;
+         else
+            return -1;
+      } // getbinop
+   
+   
+       int mathex::getuserfunc(string const &name)
+      // get index of variable
+      // return -1 if not found
+      {
+         unsigned i;
+      // look up the constants
+         for(i=0;(i<functable.size()) && strcmp(name.c_str(), functable[i].name.c_str());i++);
+         if(i<functable.size()) // if found
+            return i;
+         else
+            return -1;
+      } // getuserfunc
+   
+   
+       bool mathex::isnewvalidname(string const &name)
+      // Name validation.
+      {
+         if(name.empty() || (!isalpha(name[0]) && (name[0] != '_')))
+            return false;
+      // check for rest of characters
+         for(unsigned j=0; j<name.size(); j++)
+            if(!isalnum(name[j]) && (name[j] != '-'))
+               return false;
+         return (getcfunc(name) < 0) && (getconst(name) < 0) 
+            && (getuserfunc(name) < 0) && (getvar(name) < 0);
+      } // isnewvalidname
+   
+   
+   //////////////////
+   //  Evaluation 
+   
+   // main evaluator: internal use only
+   
+   // main evaluation function
+       double mathex::eval()
+      //  Eval the parsed stack and return
+      {
+         static vector <double> x; // suppose that eval does not eval
+         evalstack.clear();
+      
+         if(status == notparsed) parse();
+         if(status == invalid) throw error("eval()", "invalid expression");
+      
+         for(unsigned i=0; i<bytecode.size(); i++)
+         {
+            switch(bytecode[i].state) {
+               case CODETOKEN::VALUE: evalstack.push_back(bytecode[i].value);
+                  break;
+               case CODETOKEN::VARIABLE:
+               // get value of variable as value
+                  evalstack.push_back(*vartable[bytecode[i].idx].var);
+                  break;
+               case CODETOKEN::FUNCTION: // Call the C internal functions with one parameter
+               #ifdef _DEBUG_
+               if(evalstack.size()<1) // error: It does not to occur if currect parsed.
+                  throw error("eval()", "stack error");
+               #endif
+                  evalstack.back() = cfunctable[bytecode[i].idx].f(evalstack.back());
+                  break;
+               case CODETOKEN::BINOP: // Call the intern C function with two parameters
+               #ifdef _DEBUG_
+               if(evalstack.size() < 2) // error: It does not to occur if currect parsed.
+                  throw error("eval()", "stack error");
+               #endif
+                  evalstack[evalstack.size()-2] = binoptable[bytecode[i].idx].f
+                     (evalstack[evalstack.size()-2], evalstack.back());
+                  evalstack.pop_back(); // delete last
+                  break;				
+               case CODETOKEN::USERFUNC: // Call the user defined functions
+               #ifdef _DEBUG_
+               if(bytecode[i].numargs > evalstack.size())
+                  throw error("eval()", "stack error");
+               #endif
+                  if(bytecode[i].numargs > 0) {
+                     x.resize(bytecode[i].numargs);
+                     for(unsigned j=0; j<static_cast<unsigned>(bytecode[i].numargs); j++)
+                        x[bytecode[i].numargs-1-j] = evalstack[evalstack.size()-1-j];
+                     evalstack.resize(evalstack.size()-bytecode[i].numargs+1);
+							
+                     evalstack.back() = functable[bytecode[i].idx].f(x);
+                  }
+						else // Fixing bug pointed by  Hugh Denman <denmanh@tcd.ie> November 06, 2003
+						   evalstack.push_back(functable[bytecode[i].idx].f(x));
+                  break;         
+               default: // invarid stack. It does not occur if currect parsed
+                  throw  error("eval()", "invalid code token");
+            }
+         } // for(i=0; ByteCode[i].state != EMPTY;i++);
+      
+      #ifdef _DEBUG_
+      if(evalstack.size() != 1)
+         throw error("eval()", "stack error");  
+      #endif
+         return evalstack[0];
+      } // eval()
+   
+   /////////////////
+   // parser
+   //---------------
+   
+   /////////////////
+   // get the token
+   
+   // get the number token
+       bool mathex::getnumber(double &x)
+      {
+         unsigned long i = pos;
+         bool decimal;
+      
+      // is a number?
+         if((i >= expr.size()) || !strchr("0123456789.", expr[i])) // not a number
+            return false;
+      
+      // getting the number
+         for(decimal=false; i<expr.size(); i++) {
+            if(!isdigit(expr[i]) && ((expr[i] != '.') || decimal) )
+               break;
+            if(expr[i] == '.') decimal = true;
+         }
+      
+         if((i==(pos+1)) && (expr[i]=='.')) // is not a number
+            return false;
+      
+      // if scientific notation
+         if((toupper(expr[i])=='E') && (i<expr.size())) { // cientific notation 
+         // decimal = true; // turn on to detect that are double
+            i++; // skip this
+            if((i<expr.size()) && ((expr[i]=='+') || (expr[i]=='-')) ) { // if sign
+               i++;
+            }
+         // get the expoent
+            while((i<expr.size()) && isdigit(expr[i]))
+               i++;
+         }
+      // now, copy the token and conter to number
+      // if decimal is true, the number is double. otherwise, number is integer
+      // for this detection, cientific notation need to enable decimal too.
+      // The integer value are not used for this package
+      
+         x = strtod(expr.substr(pos, i-pos).c_str(), 0);
+         pos = i;
+         return true;
+      } // getnumber()
+   
+       bool mathex::getidentifier(string &name)
+      {
+         unsigned i = pos;
+      
+         name.erase();
+         if((i>=expr.size()) || (!isalpha(expr[i]) && (expr[i] != '_'))) // not a identifier
+            return false;
+      
+      // identifier
+         for(;(i<expr.size()) &&(isalnum(expr[i]) || (expr[i] == '_')); i++);
+      
+         name = expr.substr(pos, i-pos);
+         pos = i; // advance the input
+      
+         return true;
+      } // getidentifier()
+   
+   
+       mathex::PARSERTOKEN::type mathex::nexttoken()
+      // Gets the next token from the expr
+      {
+         string identifier;
+      
+         while((pos<expr.size()) && isspace(expr[pos]) )
+            pos++;
+      
+         if(pos == expr.size()) {
+            curtok.state = PARSERTOKEN::END;
+            return curtok.state;
+         }
+      
+         if(getnumber(curtok.value)) {
+            curtok.state = PARSERTOKEN::VALUE;
+            return curtok.state;
+         }
+         else if(getidentifier(identifier)) { // if identifier
+         // checking the identifier type
+            if((curtok.idx = getcfunc(identifier))>=0) // internal C functions
+               curtok.state = PARSERTOKEN::FUNCTION;
+            else if((curtok.idx=getuserfunc(identifier))>=0) { // user defined functions
+               curtok.numargs = functable[curtok.idx].numargs;
+               curtok.state = PARSERTOKEN::USERFUNC;
+            }
+            else if((curtok.idx=getvar(identifier))>=0) // variable
+               curtok.state = PARSERTOKEN::VARIABLE;
+            else if((curtok.idx=getconst(identifier))>=0) {  // constant are treated as NUMBER
+               curtok.state = PARSERTOKEN::VALUE;
+               curtok.value = consttable[curtok.idx].value;
+            }
+            else { // new identifier: not supported
+               curtok.state = PARSERTOKEN::INVALID;
+            }
+         }
+         else { // will be operators or delimiters
+            switch(expr[pos]) {
+               case '+' : curtok.state = PARSERTOKEN::PLUS;
+                  break;
+               case '-' : curtok.state = PARSERTOKEN::MINUS;
+                  break;
+               case '*' : curtok.state = PARSERTOKEN::TIMES;
+                  break;
+               case '/' : curtok.state = PARSERTOKEN::DIVIDE;
+                  break;
+               case '%' : curtok.state = PARSERTOKEN::MODULE;
+                  break;
+               case '^' : curtok.state = PARSERTOKEN::POWER;
+                  break;
+               case ',' : curtok.state = PARSERTOKEN::COMMA;
+                  break;
+               case '(' : curtok.state = PARSERTOKEN::OPAREN;
+                  break;
+               case ')' : curtok.state = PARSERTOKEN::CPAREN;
+                  break;
+               default  : curtok.state = PARSERTOKEN::INVALID;
+            } // switch 
+            if(curtok.state != PARSERTOKEN::INVALID) {
+               curtok.idx = getbinop(expr[pos]);
+               pos++;
+            }
+         } // else
+      
+         return curtok.state;
+      } // nexttoken()
+   
+   ////////////////////////////
+   // CodeStack operations 
+   ////////////////////////////
+   #ifdef _DEBUG_
+    void mathex::printcoderec(CODETOKEN const &token)
+   // print the Code Stack status
+   {
+      switch(token.state) {
+      // case CODETOKEN::EMPTY: cout << "EMPTY\n";
+      //  break;
+         case CODETOKEN::VALUE:
+            cout << "VALUE: " << token.value << endl;
+            break;
+         case CODETOKEN::VARIABLE:
+            cout << "VARIABLE: " << vartable[token.idx].name << endl;
+            break;
+         case CODETOKEN::FUNCTION:
+            if(token.idx <NUM_UNARY_OP) 
+               cout << "unary operator: " << cfunctable[token.idx].name << endl;
+            else
+               cout << "FUNCTION: " << cfunctable[token.idx].name << endl;
+            break;
+         case CODETOKEN::BINOP:
+            cout << "binary operator: " << binoptable[token.idx].name << endl;
+            break;
+         case CODETOKEN::USERFUNC:
+            cout << "USERFUNC: " << functable[token.idx].name << endl;
+            break;
+         default: printf("INVALID\n");
+      }
+   
+   } // printcoderec()
+   
+    void mathex::printbytecode()
+   {
+      cout << "codesize = "<< bytecode.size() << endl;
+      for(unsigned i=0; i<bytecode.size(); i++)
+         printcoderec(bytecode[i]);
+   }
+   #endif
+   
+       void mathex::parse()
+      // Parse the expression
+      {
+      // parserstatus = true;
+         bytecode.clear();
+         status = invalid;
+         pos=0;
+         nexttoken();
+         parsearithmetic1();
+      #ifdef _DEBUG_
+        printbytecode();
+      #endif
+         if(curtok.state != PARSERTOKEN::END) // if remain token
+            throw error("parse()", "End of expression expected");
+         status = parsed;
+      } // parse()
+   
+       void mathex::parsearithmetic1(void)
+      // level 1 arithmetic operator: binary plus/minus
+      {
+         unsigned savedidx; 
+         parsearithmetic2();
+         while((curtok.state == PARSERTOKEN::PLUS) || (curtok.state == PARSERTOKEN::MINUS)) {
+            savedidx = curtok.idx;
+            nexttoken();
+            if((curtok.state == PARSERTOKEN::PLUS) || (curtok.state == PARSERTOKEN::MINUS)) 
+               throw error("parse()", "Invalid expression");
+            parsearithmetic2();      
+            bytecode.push_back(CODETOKEN(CODETOKEN::BINOP, savedidx));
+         } // while
+      } // parsearithmetic1
+   
+   
+       void mathex::parsearithmetic2(void)
+      // level 2 arithmetic operator: multiplication, division, module
+      {
+         unsigned savedidx;
+         parsearithmetic3();   
+         while( (curtok.state == PARSERTOKEN::TIMES) || (curtok.state == PARSERTOKEN::DIVIDE)
+           || (curtok.state == PARSERTOKEN::MODULE) ) {
+            savedidx = curtok.idx;
+            nexttoken();
+            if((curtok.state == PARSERTOKEN::PLUS) || (curtok.state == PARSERTOKEN::MINUS)) 
+               throw error("parse()", "Invalid expression");
+            parsearithmetic3();
+            bytecode.push_back(CODETOKEN(CODETOKEN::BINOP, savedidx));
+         }
+      } // parsearithmetic3
+   
+       void mathex::parsearithmetic3(void)
+      // level 3 arithmetic operator: power
+      {
+         unsigned savedidx;
+         parsearithmetic4();
+         if(curtok.state == PARSERTOKEN::POWER) {
+            savedidx = curtok.idx;
+            nexttoken();
+            if((curtok.state == PARSERTOKEN::PLUS) || (curtok.state == PARSERTOKEN::MINUS)) 
+               throw error("parse()", "Invalid expression");
+            parsearithmetic4();
+            bytecode.push_back(CODETOKEN(CODETOKEN::BINOP, savedidx));
+         }
+      } // parsearithmetic3()
+   
+       void mathex::parsearithmetic4(void)
+      // level 4 arithmetic operator: unary plus/minus
+      {
+         PARSERTOKEN::type state;
+         if(((state=curtok.state) == PARSERTOKEN::PLUS) || (state == PARSERTOKEN::MINUS))
+            nexttoken();
+         if((curtok.state == PARSERTOKEN::PLUS) || (curtok.state == PARSERTOKEN::MINUS)) 
+            throw error("parse()", "Invalid expression");
+         parseatom();
+      
+         if(state == PARSERTOKEN::MINUS) // stored index are for binary operator. Get correct index
+            bytecode.push_back(CODETOKEN(CODETOKEN::FUNCTION, getunaryop("-"))); 
+      	// unary minus are on function table
+      } // parsearithmetic5()
+   
+       void mathex::parseatom(void)
+      // level 6: literal numbers, variables and functions
+      {
+         unsigned i;
+      
+      // parentesis expression
+         if(curtok.state == PARSERTOKEN::OPAREN) {
+            nexttoken();
+            if(curtok.state == PARSERTOKEN::CPAREN)
+               throw error("parseatom()", "No expression inside parentesis");
+            parsearithmetic1();
+         
+            if(curtok.state != PARSERTOKEN::CPAREN)
+               throw error("parseatom()", "\")\" expected");
+            nexttoken();  // Added by Hugh Denman (<denmanh@tcd.ie> or hdenman@cantab.net) Oct/03/2003     
+         }
+         // Number
+         else if(curtok.state == PARSERTOKEN::VALUE) { // numbers
+            bytecode.push_back(CODETOKEN(curtok.value));
+            nexttoken();
+         }
+         // variables
+         else if(curtok.state == PARSERTOKEN::VARIABLE) { // variables
+            bytecode.push_back(CODETOKEN(CODETOKEN::VARIABLE, curtok.idx));
+            nexttoken();
+         }
+         // internal C function with one parameters
+         else if(curtok.state == PARSERTOKEN::FUNCTION) { // one parameter C functions
+            parserstack.push_back(curtok);
+            nexttoken();
+            if(curtok.state != PARSERTOKEN::OPAREN)
+               throw error("parseatom()", "\"(\" expected");
+            nexttoken();
+            if(curtok.state == PARSERTOKEN::CPAREN) 
+               throw error("parseatom()", "invalid number of arguments");
+            parsearithmetic1();
+            if(curtok.state != PARSERTOKEN::CPAREN)
+               throw error("parseatom()", "\")\" expected");
+            curtok = parserstack.back();
+            parserstack.pop_back();
+            bytecode.push_back(CODETOKEN(CODETOKEN::FUNCTION, curtok.idx));
+            nexttoken();
+         }
+         // user defined functions
+         else if(curtok.state == PARSERTOKEN::USERFUNC) { // user defined function
+            parserstack.push_back(curtok);
+            nexttoken();
+            if(curtok.state != PARSERTOKEN::OPAREN)
+               throw error("parseatom()", "\"(\" expected");
+            nexttoken();
+            if(curtok.state == PARSERTOKEN::CPAREN)
+               i = 0;
+            else { // arguments exist
+               parsearithmetic1();
+               i = 1;
+            // while(parserstatus && (curtok.state != PARSERTOKEN::END)
+            //        &&(curtok.state != PARSERTOKEN::CPAREN)) {
+               while((curtok.state != PARSERTOKEN::END) && (curtok.state != PARSERTOKEN::CPAREN)) {
+                  if(curtok.state == PARSERTOKEN::COMMA) {
+                     nexttoken();
+                     i++;
+                  }
+                  else 
+                     throw error("parseatom()", "unknow error");
+                  parsearithmetic1();
+               } // while
+               if(curtok.state != PARSERTOKEN::CPAREN)
+                  throw error("parseatom()", "\")\" expected");
+            } // else
+            curtok = parserstack.back();
+            parserstack.pop_back();
+         
+            if ((curtok.numargs != UNDEFARGS) && (i != static_cast<unsigned>(curtok.numargs)))
+            // i is current number of parameters
+               throw error("parseatom()", "invalid number of arguments");
+         
+         // number of parameters is correct. Now, put the function
+         // i is number of arguments    
+            bytecode.push_back(CODETOKEN(CODETOKEN::USERFUNC, curtok.idx, i));
+         
+            nexttoken();
+         } // user defined functions
+         // End of buffer
+         else if (curtok.state == PARSERTOKEN::END)
+            throw error("parseatom()", "unexpected end of expression");
+         // invalid
+         else if (curtok.state == PARSERTOKEN::INVALID)
+            throw error("parseatom()", "invalid token on expression");
+         // unknow error
+         else // it not occur
+            throw error("parseatom()", "unknow error");  
+      } // parseatom()
+   
+   
+   
+   } // namespace smlib {
+
+
+// end of mathex.c
diff --git a/contrib/MathEx/mathex.h b/contrib/MathEx/mathex.h
new file mode 100644
index 0000000000000000000000000000000000000000..56e9029505be4db0f1c3357691f2afe31c8a4a70
--- /dev/null
+++ b/contrib/MathEx/mathex.h
@@ -0,0 +1,270 @@
+///////////////////////////////////////////////////////////////////////////
+// mathex 0.2.3 (beta) - Copyright (C) 2000-2003, by Sadao Massago       //
+// file: mathex.h (math expression evaluator header file)                //
+// requires: none                                                        //
+// project web page: http://sscilib.sourceforge.net/                     //
+//-----------------------------------------------------------------------//
+// The mathex library and related files is licensed under the term of    //
+// GNU LGPL (Lesser General Public License) version 2.1 or latter        //
+// with exceptions that allow for static linking.                        //
+// See license.txt for detail.                                           //
+// For GNU LGPL, see lesser.txt.                                         //
+// For information over GNU or GNU compatible license, visit the site    //
+// http://www.gnu.org.                                                   //
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+// references:
+//-------------------------------------------------------------------------
+// title: Algoritms and Data Structures
+// author: Niklaus Wirth
+// publisher: Prentice-Hall
+// year: 1989
+//-------------------------------------------------------------------------
+// title: The C++ programming language
+// edition: thrird
+// author: Bjarne Stroustrup
+// publisher: Addilson-Wesley
+// year: 1997
+//-------------------------------------------------------------------------
+// title: building your own C interpreter
+// author: Schildt, Helbert
+// journal: Dr. Dobb's Jornal (http://www.ddj.com)
+// number: August/1989
+// pages: 38-49, 110-122
+///////////////////////////////////////////////////////////////////////////
+
+// example file listing for doxygen
+
+/// \example inttest.cpp
+/// integration test using Trapezoidal rule
+
+/// \example userfunctest.cpp
+/// user defined function testing
+
+/// \example tabletest.cpp
+/// making table of function
+ 
+/// \example curvetest.cpp
+/// making table of parametric curve
+
+// #define _DEBUG_
+
+#ifndef _MATHEX_H
+ #define _MATHEX_H
+
+#include <string>
+#include <vector>
+#include <cmath>
+// #include <cctype>
+// debug purpose
+#ifdef _DEBUG_
+  #include <iostream>
+#endif
+
+namespace smlib {
+
+using namespace std;
+
+/////////////////////////////////////
+// mathex main class
+// it contain several sub classes
+// to handle expressions
+/////////////////////////////////////
+
+    class mathex {
+   /////////////////////////
+   // private sub calsses
+   ////////////////////////
+   
+     // code token used by evaluator
+       class CODETOKEN {
+      public:
+         // token type (code token type)
+         enum type {
+         VALUE=0, // numerical value stack
+         VARIABLE, // variable stack
+         FUNCTION, // internal C function with one parameters (include unary operators)
+         BINOP, // internal C binary opeartors (function with two parameters)
+         USERFUNC, // user defined functions
+         LASTTYPE=USERFUNC};
+      
+         type state;  // state of Token
+         unsigned numargs;
+         // The user defined function use it to pop values from stack
+			// In the undefined number of arguments case, it will not eliminated
+			double value; // numerical value
+         unsigned idx; // index of variable, function or user defined function on table
+          CODETOKEN(double x=0.0) // construct VALUE token
+         {
+            state = VALUE;
+            value = x;
+         }
+          CODETOKEN(type toktype, unsigned index, unsigned NumArgs=1) // construct token except VALUE
+          // in the used defined function case, num args need to set
+         {
+            state = toktype;
+            idx = index;
+				numargs = NumArgs;
+         }
+      }; // CODETOKEN
+   
+      // parse token used by parser
+       class PARSERTOKEN {
+      public:
+         enum type {
+         VALUE, VARIABLE, FUNCTION, USERFUNC,
+         PLUS, MINUS, TIMES, DIVIDE, MODULE, POWER, 
+         OPAREN, CPAREN, COMMA, END, INVALID, // invalid character on token
+         LASTTYPE=INVALID
+         };
+      
+         type state;
+         int numargs; // number of parameters of functions
+         double value;
+         int idx; // it are signed because receive func/var search index that will be -1
+      	         // atom parsing cede optimization
+      };  // parsetoken
+   
+   
+   // function record
+   
+   //  Record for user defined functions
+       class FUNCREC {
+      public:
+         string name;
+         double  (*f)(vector<double> const &x); // generic number of parameters
+         int numargs; // number of arguments
+          FUNCREC() // only for table (vector) operation
+         {name = ""; f = 0;}
+          FUNCREC(string const &funcname, double (*func)(vector<double> const &), int NumArgs)
+         {name = funcname; f = func; numargs = NumArgs; }
+      }; // FUNCREC
+   
+   
+   // variable record
+       class VARREC {
+      public:
+         string name;
+         double *var;
+          VARREC()
+         {name = ""; var = 0;}
+          VARREC(string const &varname, double *x)
+         {
+            if(x == NULL) throw error("Error [VARREC()]: variable without reference");
+            name = varname; var = x; }
+      }; // VARREC
+   
+   /////////////////////
+   // evalmath start here
+   /////////////////////
+      
+      vector<FUNCREC> functable; // used defined function table
+      vector<VARREC> vartable; // used defined variable table
+      vector<CODETOKEN> bytecode; // parsed code
+      vector<double> evalstack; // stack memory used by evaluator
+      string expr; // expression string
+      enum {invalid, notparsed, parsed} status; // prse status
+   
+      // used by addvar/addfunc to validate new variable/functions name
+      bool isnewvalidname(string const &name); // check if new valid name
+   
+      // table look up
+      int getconst(string const &name); // get index of constant
+      int getvar(string const &name); // get index of variable
+      int getcfunc(string const &name); // get index of one parameter internal C function
+      int getunaryop(string const &name); // get index of unary operator
+      int getbinop(char name); // get index of binary operator
+      int getuserfunc(string const &name); // get index of user defined functions
+      void addstdfunc(); // add standard user defined functions to table
+   
+      // token operators
+      bool getnumber(double &x); // get number from input string
+      bool getidentifier(string &name); // get identifier from input string
+      PARSERTOKEN::type nexttoken(); // get next token from input string
+      vector<PARSERTOKEN> parserstack; // stack used by parser
+      PARSERTOKEN curtok; // current token. Used by parser
+      unsigned long pos; // expression parsing position
+   
+      #ifdef _DEBUG_
+      void printcoderec(CODETOKEN const &token); // used by printbytecode()
+      #endif
+      // parser methods
+      // aritmethic operators
+      void parsearithmetic1(void);  // binary plus/minus 
+      void parsearithmetic2(void);  // timed, divide, modulo
+      void parsearithmetic3(void);  // power
+      void parsearithmetic4(void);  // unary minus 
+      void parseatom(void);  // atom: functions, variables, numbers...
+      
+   public:
+       ///////////////////////
+   	 // public sub classes
+   	 ///////////////////////
+   	 
+         /// error class to hamdle exceptions
+     class error : public std::exception {
+        private:
+         string msg;
+         public:
+            /// with message only
+          error(string const &message)
+         { msg = "Error [eval]: " + message; }
+			/// error with identifier and messages
+          error(string const &id, string const &message)
+         { msg = "Error [mathex::" + id + "]: " + message; }
+          /// unkone error
+          error()
+         { msg = "Error [mathex]: unkonw error"; }
+          /// return error message
+          const char * what() const throw()
+         { 
+            return msg.c_str(); }            
+          ~error() throw() {}
+       }; // error		
+   	 
+   	////////////////////////////////////////////////////
+      // mathex public constants, variables and methods
+   
+      #ifdef _DEBUG_
+      void printbytecode(); // output byte code to cout
+      #endif
+   
+   
+    // add/delete variables
+      bool addvar(string const &name, double *x); /// < add new variable
+      bool delvar(string const &name); /// < delete variable
+       void delvar() /// < delete all variables
+      {vartable.clear(); status = notparsed; }
+   
+       /// undefined number of arguments (for user defined functions
+      static const int UNDEFARGS; // for user function arguments   
+      // add/delete used defined functions
+      bool addfunc(string const &name, double (*f)(vector<double> const &), int NumArgs); /// < add new function
+      bool delfunc(string const &name); /// < delete variable
+       void delfunc() /// < delete all variable
+      {functable.clear(); addstdfunc(); status=notparsed; }
+    // expression string
+       string const &expression() /// < return expression string
+      {
+         return expr;}
+       void expression(string const &formula) /// < set expression string
+      { expr = formula; status = notparsed; pos=0; }
+       unsigned long stopposition() /// < return parser stoped position
+      { 
+         return pos; }
+      void parse(); /// < parse expression 
+      double eval(); /// < eval expression
+      void reset(); /// < reset all
+       mathex() /// < default constructor
+      {reset();}
+       mathex(string const &formula) /// < constructor that assign expression string
+      {reset(); expr = formula;}
+   }; /// mathex
+
+
+} // namespace smlib {
+
+#endif // #ifndef _MATHEX_H
+
+// end of mathex.c
diff --git a/contrib/TreeBrowser/Flu_Tree_Browser.cpp b/contrib/TreeBrowser/Flu_Tree_Browser.cpp
deleted file mode 100644
index 7767b7c7690763b710215f04c549d7b1cda4ad46..0000000000000000000000000000000000000000
--- a/contrib/TreeBrowser/Flu_Tree_Browser.cpp
+++ /dev/null
@@ -1,3474 +0,0 @@
-// This is a (fairly heavily) modified version of Jason Bryan's
-// Flu_Tree_Browser, for inclusion in Gmsh.
-//
-// The following changes have been made:
-//
-// * Removed drag-and-drop code
-// * Added pixmaps in the .cpp file
-// * Removed IntStack (replaced by std::vector)
-// * Removed FluSimpleString (replaced by std::string)
-// * Removed animation code
-// * Removed the "find" pass when adding a new node (cf. "CG") 
-//   to improve speed (WARNING: this fundamentally changes the 
-//   way the tree works: calling add("/a/b") followed by add("/a/c")
-//   will create two "a" branches. This is the desired behaviour
-//   for Gmsh; probably not for you)
-// 
-
-/***************************************************************
- *                FLU - FLTK Utility Widgets 
- *  Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University
- *
- * This file and its content is protected by a software license.
- * You should have received a copy of this license with this file.
- * If not, please contact the Ohio Supercomputer Center immediately:
- * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212
- * 
- ***************************************************************/
-
-#include <math.h>
-#include <FL/fl_draw.H>
-#include "Flu_Tree_Browser.h"
-
-static char * plus_xpm[] = {
-"15 15 4 1",
-"       c None",
-".      c #444444",
-"+      c #FFFFFF",
-"@      c #000000",
-"               ",
-"               ",
-"  ...........  ",
-"  .+++++++++.  ",
-"  .++++@++++.  ",
-"  .++++@++++.  ",
-"  .++++@++++.  ",
-"  .+@@@@@@@+.  ",
-"  .++++@++++.  ",
-"  .++++@++++.  ",
-"  .++++@++++.  ",
-"  .+++++++++.  ",
-"  ...........  ",
-"               ",
-"               "};
-
-static char * minus_xpm[] = {
-"15 15 4 1",
-"       c None",
-".      c #444444",
-"+      c #FFFFFF",
-"@      c #000000",
-"               ",
-"               ",
-"  ...........  ",
-"  .+++++++++.  ",
-"  .+++++++++.  ",
-"  .+++++++++.  ",
-"  .+++++++++.  ",
-"  .+@@@@@@@+.  ",
-"  .+++++++++.  ",
-"  .+++++++++.  ",
-"  .+++++++++.  ",
-"  .+++++++++.  ",
-"  ...........  ",
-"               ",
-"               "};
-
-static char * folder_closed_xpm[] = {
-"20 16 44 1",
-" 	c None",
-".	c #A68A5E",
-"+	c #54452F",
-"@	c #FEE89E",
-"#	c #FEE59B",
-"$	c #FEE298",
-"%	c #FEDE95",
-"&	c #FEDB93",
-"*	c #CEAB75",
-"=	c #FEF6A9",
-"-	c #FEF2A7",
-";	c #FEEFA4",
-">	c #FEECA1",
-",	c #FEE99E",
-"'	c #FEE69C",
-")	c #FEE399",
-"!	c #FEDF96",
-"~	c #FEDC93",
-"{	c #FED991",
-"]	c #FED68E",
-"^	c #FEF3A7",
-"/	c #FEF0A4",
-"(	c #FEEDA2",
-"_	c #FEE99F",
-":	c #FEE097",
-"<	c #FEDD94",
-"[	c #FEDA91",
-"}	c #FED78E",
-"|	c #FEF0A5",
-"1	c #FEEA9F",
-"2	c #FEE79D",
-"3	c #FEE49A",
-"4	c #FEE197",
-"5	c #FEDA92",
-"6	c #FED78F",
-"7	c #FEEEA3",
-"8	c #FEEAA0",
-"9	c #FEE198",
-"0	c #FEDB92",
-"a	c #FED88F",
-"b	c #FEEBA0",
-"c	c #FED890",
-"d	c #FEE299",
-"e	c #FED990",
-"                    ",
-"          .....+    ",
-"         .@#$%&.+   ",
-"   ......*******.   ",
-"   .=-;>,')!~{]].+  ",
-"   .^/(_'):<[}]].+  ",
-"   .|(1234<56]]].+  ",
-"   .78239%0a]]]].+  ",
-"   .b@#$%&c]]]]].+  ",
-"   .@#d!~e]]]]]].+  ",
-"   .')!~{]]]]]]].+  ",
-"   .):<[}]]]]]]].+  ",
-"   ..............+  ",
-"    ++++++++++++++  ",
-"                    ",
-"                    "};
-
-static char * folder_open_xpm[] = {
-"20 16 34 1",
-" 	c None",
-".	c #A68A5E",
-"+	c #FEF3A7",
-"@	c #FEECA1",
-"#	c #FEE49A",
-"$	c #FEDD94",
-"%	c #FED68E",
-"&	c #FEF6A9",
-"*	c #FEEEA3",
-"=	c #FEE79D",
-"-	c #FEDF96",
-";	c #FED890",
-">	c #FEF1A5",
-",	c #FEE99F",
-"'	c #FEE298",
-")	c #FEDA92",
-"!	c #FEF0A5",
-"~	c #FEEBA1",
-"{	c #FEE69C",
-"]	c #FEE198",
-"^	c #FEDC93",
-"/	c #FED78F",
-"(	c #54452F",
-"_	c #FEF2A6",
-":	c #FEEDA2",
-"<	c #FEE299",
-"[	c #FEE99E",
-"}	c #FEDE95",
-"|	c #FED991",
-"1	c #FEEFA4",
-"2	c #FEEA9F",
-"3	c #FEE59B",
-"4	c #FEE096",
-"5	c #FEDB92",
-"                    ",
-"          .....     ",
-"         .+@#$%.    ",
-"   ......&*=-;%%.   ",
-"   .&&&&&>,')%%%.   ",
-"   .&&&&+@#$%%%%.   ",
-"   .&&............  ",
-"   .&&.&!~{]^/%%%.( ",
-"   .&&._:=<$;%%%%.( ",
-"   .&.+*[#}|%%%%.(  ",
-"   .&.12345%%%%%.(  ",
-"    .!~{]^/%%%%.(   ",
-"    ............(   ",
-"    ((((((((((((    ",
-"                    ",
-"                    "};
-
-#define MAX( x, y ) ( (x)>(y) ? (x) : (y) )
-#define MIN( x, y ) ( (x)<(y) ? (x) : (y) )
-
-bool Flu_Tree_Browser::USE_FLU_WIDGET_CALLBACK = false;
-
-Flu_Tree_Browser :: NodeList :: NodeList()
-{
-  _nodes = NULL;
-  _nNodes = _size = 0;
-}
-
-Flu_Tree_Browser :: NodeList :: ~NodeList()
-{
-  clear();
-}
-
-typedef Flu_Tree_Browser::Node* NodeP;
-
-bool Flu_Tree_Browser :: NodeList :: search( const char *n, int &index )
-{
-  index = _nNodes;
-  if( _nNodes == 0 )
-    return false;
-
-  // we know we have at least one node. so use it to get the RData struct to find out what
-  // the insertion mode is
-  int iMode = _nodes[0]->tree->insertion_mode();
-
-  if( iMode == FLU_INSERT_SORTED || iMode == FLU_INSERT_SORTED_REVERSE )
-    return( binSearch( n, index ) );
-  else
-    return( linSearch( n, index ) );
-}
-
-bool Flu_Tree_Browser :: NodeList :: search( Node *n, int &index )
-{
-  index = _nNodes;
-  if( _nNodes == 0 )
-    return false;
-
-  // we know we have at least one node. so use it to get the RData struct to find out what
-  // the insertion mode is
-  int iMode = _nodes[0]->tree->insertion_mode();
-
-  if( iMode == FLU_INSERT_SORTED || iMode == FLU_INSERT_SORTED_REVERSE )
-    return( binSearch( n, index ) );
-  else
-    return( linSearch( n, index ) );
-}
-
-bool Flu_Tree_Browser :: NodeList :: linSearch( const char *n, int &index )
-{
-  index = _nNodes;
-  for( int i = 0; i < _nNodes; i++ )
-    {
-      if( strcmp( n, _nodes[i]->label() ) == 0 )
-	{
-	  index = i;
-	  return true;
-	}
-    }
-  return false;
-}
-
-bool Flu_Tree_Browser :: NodeList :: linSearch( Node *n, int &index )
-{
-  index = _nNodes;
-  for( int i = 0; i < _nNodes; i++ )
-    {
-      if( n == _nodes[i] )
-	{
-	  index = i;
-	  return true;
-	}
-    }
-  return false;
-}
-
-bool Flu_Tree_Browser :: NodeList :: binSearch( Node *n, int &index )
-{
-  if( binSearch( n->label(), index ) )
-    {
-      // the search found the first node with the label. since there are identical entries
-      // allowed, it may not be the actual node we want. therefore search forward until we find it
-      for( ; index < _nNodes; index++ )
-	if( _nodes[index] == n )
-	  return true;
-      return false;
-    }
-  else
-    return false;
-}
-
-bool Flu_Tree_Browser :: NodeList :: binSearch( const char *n, int &index )
-{
-  // do a binary search for a child with name == "n"
-  // return true if the child is found, and store its index in "index"
-  // return false if the child is not found, and store the index it would
-  // be in in "index"
-
-  // special case: no nodes
-  if( _nNodes == 0 )
-    {
-      index = 0;
-      return false;
-    }
-
-  // we know we have at least one node. so use it to get the RData struct to find out what
-  // the insertion mode is
-  int iMode = _nodes[0]->tree->insertion_mode();
-
-  // special case: 1 node
-  if( _nNodes == 1 )
-    {
-      int val = strcmp( n, _nodes[0]->label() );
-      if( iMode == FLU_INSERT_SORTED_REVERSE )
-	val *= -1;
-      if( val == 0 )
-	{
-	  index = 0;
-	  return true;
-	}
-      else if( val < 0 )
-	index = 0;
-      else
-	index = 1;
-      return false;
-    }
-
-  int first = 0, last = _nNodes - 1;
-  int val1, val2, mVal;
-  for(;;)
-    {
-      // the range is down to 2 nodes
-      if( last == first + 1 )
-	{
-	  val1 = strcmp( n, _nodes[first]->label() );
-	  if( iMode == FLU_INSERT_SORTED_REVERSE )
-	    val1 = -val1;
-	  if( val1 < 0 )
-	    {
-	      index = first;
-	      return false;
-	    }
-	  else if( val1 == 0 )
-	    {
-	      index = first;
-	      break;
-	    }
-	  val2 = strcmp( n, _nodes[last]->label() );
-	  if( iMode == FLU_INSERT_SORTED_REVERSE )
-	    val2 = -val2;
-	  if( val2 < 0 )
-	    {
-	      index = last;
-	      return false;
-	    }
-	  else if( val2 == 0 )
-	    {
-	      index = last;
-	      break;
-	    }
-	  else
-	    {
-	      index = last+1;
-	      return false;
-	    }
-	}
-
-      // pick which half of the array to search next
-      int midpoint = first + ((last-first)>>1);
-      mVal = strcmp( n, _nodes[midpoint]->label() );
-      if( iMode == FLU_INSERT_SORTED_REVERSE )
-	mVal = -mVal;
-      if( mVal < 0 )
-	last = midpoint;
-      else if( mVal > 0 )
-	first = midpoint;
-      else
-	{
-	  index = midpoint;
-	  break;
-	}
-    }
-
-  // we found *a* node equal to "n", now find the first node equal to "n"
-  // by searching until we hit a node not equal to "n"
-  for( first = index; first > 0; first-- )
-    if( strcmp( n, _nodes[first-1]->label() ) != 0 )
-      break;
-  index = first;
-
-  return true;
-}
-
-int Flu_Tree_Browser :: NodeList :: compareNodes( const void *arg1, const void* arg2 )
-{
-  Flu_Tree_Browser::Node *n1 = *((Flu_Tree_Browser::Node**)arg1), *n2 = *((Flu_Tree_Browser::Node**)arg2);
-  return strcmp( n1->text.c_str(), n2->text.c_str() );
-}
-
-int Flu_Tree_Browser :: NodeList :: reverseCompareNodes( const void *arg1, const void* arg2 )
-{
-  Flu_Tree_Browser::Node *n1 = *((Flu_Tree_Browser::Node**)arg1), *n2 = *((Flu_Tree_Browser::Node**)arg2);
-  return( -strcmp( n1->text.c_str(), n2->text.c_str() ) );
-}
-
-void Flu_Tree_Browser :: NodeList :: sort()
-{
-  if( _nNodes )
-    {
-      // we know we have at least one node. so use it to get the RData struct to find out what
-      // the insertion mode is
-      int iMode = _nodes[0]->tree->insertion_mode();
-      if( iMode == FLU_INSERT_SORTED )
-	qsort( _nodes, _nNodes, sizeof(Node*), compareNodes );
-      else if( iMode == FLU_INSERT_SORTED_REVERSE )
-	qsort( _nodes, _nNodes, sizeof(Node*), reverseCompareNodes );
-    }
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: insert( const char* fullpath, int pos )
-{
-  // insert the new node at the back of the tree
-  int imode = tree->insertion_mode();
-  tree->insertion_mode( FLU_INSERT_BACK );
-  Node *n = add( fullpath );
-  tree->insertion_mode( imode );
-  if( !n ) return NULL;
-  // find the node at position "pos" and
-  // move the new node before it, so it takes over position "pos"
-  if( pos < 0 ) pos = 0;
-  if( pos >= children() ) pos = children()-1;
-  move( n, MOVE_BEFORE, child(pos) );
-  return n;
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: insert_branch( const char* fullpath, int pos )
-{
-  std::string p( fullpath );
-  if( p.size() && p[p.size()-1] != '/' && p[p.size()-1] != '\\' ) p += "/";
-  return insert( p.c_str(), pos );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: insert_leaf( const char* fullpath, int pos )
-{
-  std::string p( fullpath );
-  if( p.size() && ( p[p.size()-1] == '/' || p[p.size()-1] == '\\' ) ) p[p.size()-1] = '\0';
-  return insert( p.c_str(), pos );
-}
-
-bool Flu_Tree_Browser :: Node :: move( int pos )
-{
-  // get this node's position
-  int i = index();
-  if( i == -1 ) return false;
-  // get the node in our parent at index "pos"
-  if( !parent() ) return false;
-  if( pos < 0 ) pos = 0;
-  if( pos >= parent()->children() ) pos = parent()->children()-1;
-  Node *n = parent()->child( pos );
-  // move this node to be before its sibling, so it takes over position "pos"
-  return move( this, MOVE_BEFORE, n );
-}
-
-bool Flu_Tree_Browser :: Node :: swap( Node* n1, Node* n2 )
-{
-  if( n1->tree != n2->tree ) return false;
-  Node *p1 = n1->parent(), *p2 = n2->parent();
-  if( !p1 || !p2 ) return false;
-  int i, index1 = -1, index2 = -1;
-  for( i = 0; i < p1->children(); i++ )
-    {
-      if( p1->child(i) == n1 )
-	{
-	  index1 = i;
-	  break;
-	}
-    }
-  if( index1 == -1 ) return false;
-  for( i = 0; i < p2->children(); i++ )
-    {
-      if( p2->child(i) == n2 )
-	{
-	  index2 = i;
-	  break;
-	}
-    }
-  if( index2 == -1 ) return false;
-  p1->_children._nodes[index1] = n2;
-  p2->_children._nodes[index2] = n1;
-  return true;
-}
-
-bool Flu_Tree_Browser :: Node :: move( Node* n1, int where, Node* n2 )
-{
-  if( isMoveValid( n1, where, n2 ) )
-    return( NodeList::move( n1, where, n2 ) );
-  else
-    return false;
-}
-
-void Flu_Tree_Browser :: Node :: sort()
-{
-  _children.sort();
-  for( int i = 0; i < _children.size(); i++ )
-    _children.child(i)->sort();
-}
-
-bool Flu_Tree_Browser :: Node :: is_ancestor( Node* n )
-{
-  Node *p = parent();
-  while( p )
-    {
-      if( p == n )
-	return true;
-      else
-	p = p->parent();
-    }
-  return false;
-}
-
-bool Flu_Tree_Browser :: Node :: is_descendent( Node* n )
-{
-  return n->is_ancestor( this );
-}
-
-bool Flu_Tree_Browser :: NodeList :: move( Node* n1, int where, Node* n2 )
-{
-  if( !n1 || !n2 )
-    return false;
-
-  if( n1->tree )
-    n1->tree->redraw();
-  if( n2->tree )
-    n2->tree->redraw();
-
-  // try to move n1 to the first child position of n2
-  if( where == MOVE_INSIDE )
-    {
-      if( !n2->is_branch() )
-	return false;
-      // get the parent of n1
-      Node* p1 = n1->parent();
-      if( p1 )
-	// remove n1 from its parent's list
-	p1->_children.erase( n1 );
-      // insert into n2
-      int iMode = n1->tree->insertion_mode();
-      if( iMode == FLU_INSERT_SORTED || iMode == FLU_INSERT_SORTED_REVERSE )
-	n2->_children.add( n1 );
-      else
-	n2->_children.add( n1, 0 );
-      // update the parent of n1
-      n1->_parent = n2;
-      return true;
-    }
-
-  // find the position of n2 in its parent's list
-  Node* p2 = n2->parent();
-  if( !p2 )
-    return false;
-  int index = 0, removed = -1;
-  if( p2->_children.search( n2, index ) )
-    {
-      // get the parent of n1
-      Node* p1 = n1->parent();
-      if( p1 )
-	// remove n1 from its parent's list. remember the position it was removed from
-	removed = p1->_children.erase( n1 );
-
-      // if n1 and n2 have the same parent, and if n1 came before the spot where
-      // n2 will be inserted, then our indexing is off by one because n1 has been removed
-      if( p1 == p2 && removed <= index )
-	index--;
-
-      if( where == MOVE_AFTER )
-       index++;
-
-      // insert n1 at the proper position
-      p2->_children.add( n1, index );
-
-      // update the parent of n1
-      n1->_parent = p2;
-    }
-
-  return true;
-}
-
-void Flu_Tree_Browser :: NodeList :: add( Node* n, int position )
-{
-  int i, index;
-  int mode = n->tree->insertion_mode();
-
-  // if the list is out of room, allocate a new one that's bigger
-  if( _nNodes == _size )
-    {
-      int newSize = ( _size == 0 ) ? 1 : _size*2; // double the size of the old list (same behavior as STL vector)
-      // allocate the new list
-      Node** newNodes = new NodeP[ newSize ];
-      // copy the old list to the new list
-      memcpy( newNodes, _nodes, _nNodes*sizeof(Node*) );
-      // delete the old list and replace it with the new list
-      delete[] _nodes;
-      //n->tree->rdata.cbNode = NULL;
-      _nodes = newNodes;
-      _size = newSize;
-    }
-
-  if( position >= 0 )
-    {
-      if( position > _nNodes )
-	index = _nNodes;
-      else
-	index = position;
-    }
-  else if( mode == FLU_INSERT_SORTED || mode == FLU_INSERT_SORTED_REVERSE )
-    {
-      // search through the list until we find where to insert the node
-      binSearch( n->label(), index );
-    }
-  else if( mode == FLU_INSERT_FRONT )
-    {
-      index = 0;
-    }
-  else if( mode == FLU_INSERT_BACK )
-    {
-      index = _nNodes;
-    }
-  else
-    return;
-
-  // shift all entries from the new insertion point down one spot
-  // to make room for the new node
-  for( i = _nNodes - 1; i >= index; i-- )
-    _nodes[i+1] = _nodes[i];
-
-  // add the new node
-  _nodes[index] = n;
-
-  _nNodes++;
-}
-
-int Flu_Tree_Browser :: NodeList :: erase( Node *n )
-{
-  if( n == NULL )
-    return -1;
-
-  int index;
-  if( search( n, index ) )
-    {
-      // move all the others down one spot to remove the node
-      for( int i = index; i < _nNodes-1; i++ )
-	_nodes[i] = _nodes[i+1];
-      _nNodes--;
-
-      return index;
-    }
-  return -1;
-}
-
-int Flu_Tree_Browser :: NodeList :: erase( const char* n )
-{
-  if( _nNodes == 0 )
-    return -1;
-
-  int index;
-  if( search( n, index ) )
-    {
-      // move all the others down one spot to remove the node
-      for( int i = index; i < _nNodes-1; i++ )
-	_nodes[i] = _nodes[i+1];
-      _nNodes--;
-      return index;
-    }
-  return -1;
-}
-
-void Flu_Tree_Browser :: NodeList :: erase( int n )
-{
-  // make sure n is in range
-  if( ( n < 0 ) || ( n >= _nNodes ) )
-    return;
-
-  // move all the others down one spot to remove the node
-  for( int i = n; i < _nNodes-1; i++ )
-    _nodes[i] = _nodes[i+1];
-
-  _nNodes--;
-}
-
-void Flu_Tree_Browser :: NodeList :: clear()
-{
-  if( _nodes )
-    {
-      //if( _nNodes )
-      //if( _nodes[0] )
-      //  _nodes[0]->tree->rdata.cbNode = NULL;
-      delete[] _nodes;
-    }
-  _nodes = NULL;
-  _nNodes = _size = 0;
-}
-
-int Flu_Tree_Browser :: NodeList :: findNum( const char *n )
-{
-  if( ( _nNodes == 0 ) || ( n == 0 ) )
-    return 0;
-
-  // see if there is a first node equal to "n"
-  int index, last;
-  if( !search( n, index ) )
-    return 0;
-
-  // now search forward until we hit a node not equal to "n"
-  for( last = index; last < _nNodes-1; last++ )
-    if( strcmp( n, _nodes[last+1]->label() ) != 0 )
-      break;
-
-  return last - index + 1;
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: NodeList :: find( const char* n, int which )
-{
-  if( ( _nNodes == 0 ) || ( n == 0 ) || ( which == 0 ) )
-    return NULL;
-
-  // see if there is a first node equal to "n"
-  int index, first;
-  if( !search( n, first ) )
-    return NULL;
-
-  // now search forward and try to find the which'th node named "n"
-  int total = 0;
-  for( index = first; index < _nNodes; index++ )
-    {
-      if( strcmp( n, _nodes[index]->label() ) == 0 )
-	{
-	  total++;
-	  if( total == which )
-	    break;
-	}
-      else
-	break;
-    }
-  if( total != which )
-    return NULL;
-
-  return _nodes[index];
-}
-
-#define SCROLL_SIZE 15
-
-Flu_Tree_Browser :: Flu_Tree_Browser( int x, int y, int w, int h, const char *l )
-  : Fl_Group( x, y, w, h )
-{
-  // add some widgets
-  _box = new Fl_Group( x, y, w-SCROLL_SIZE, h-SCROLL_SIZE );
-  _box->resizable( NULL );
-  _box->end();
-  //_box->set_output();
-  scrollV = new Fl_Scrollbar( x+w-SCROLL_SIZE, y, SCROLL_SIZE, h-SCROLL_SIZE );
-  scrollV->type( FL_VERTICAL );
-  scrollV->callback( _scrollCB, this );
-  scrollV->value( 0, 1, 0, 0 );
-  scrollH = new Fl_Scrollbar( x, y+h-SCROLL_SIZE, w-SCROLL_SIZE, SCROLL_SIZE );
-  scrollH->type( FL_HORIZONTAL );
-  scrollH->callback( _scrollCB, this );
-  scrollH->value( 0, 1, 0, 0 );
-  scrollBox = new Fl_Group( x+w-SCROLL_SIZE, y+h-SCROLL_SIZE, SCROLL_SIZE, SCROLL_SIZE );
-  scrollBox->box( FL_UP_BOX );
-  scrollBox->end();
-  resizable( _box );
-
-  // set up the recursive data structure
-  memset( &rdata, 0, sizeof(rdata) );
-  rdata.root = &root;
-  root.tree = this;
-  rdata.cbNode = NULL;
-  rdata.cbReason = FLU_NOTHING;
-  rdata.tree = this;
-  rdata.dragging = false;
-  rdata.forceResize = true;
-  rdata.shiftSelect = false;
-  rdata.shiftSelectAll = false;
-  rdata.nextId = 1;
-  rdata.searchIndex = 1;
-  rdata.defaultCollapseIcons[0] = new Fl_Pixmap( (char*const*)plus_xpm );
-  rdata.defaultCollapseIcons[1] = new Fl_Pixmap( (char*const*)minus_xpm );
-  rdata.defaultBranchIcons[0] = new Fl_Pixmap( (char*const*)folder_closed_xpm );
-  rdata.defaultBranchIcons[1] = new Fl_Pixmap( (char*const*)folder_open_xpm );
-
-  end();
-
-  // set the default values for the tree
-  selection_follows_hilight( false );
-  select_under_mouse( false );
-  open_without_children( true );
-  auto_branches( false );
-  double_click_opens( true );
-  move_only_same_group( false );
-  allow_leaf_duplication( true );
-  shaded_entry_colors( FL_WHITE, FL_WHITE );
-  collapse_icons( NULL, NULL );
-  //branch_icons( NULL, NULL );
-  rdata.branchIcons[0] = rdata.defaultBranchIcons[0];
-  rdata.branchIcons[1] = rdata.defaultBranchIcons[1];
-  leaf_icon( NULL );
-  branch_text( FL_BLACK, FL_HELVETICA_BOLD, 12 );
-  leaf_text( FL_BLACK, FL_HELVETICA, 12 );
-  //callback( NULL );
-  when( FL_WHEN_CHANGED );
-  color( FL_WHITE );
-  selection_color( FL_SELECTION_COLOR );
-  box( FL_FLAT_BOX );
-  connector_style( FL_DARK2, FL_DOT );
-  selection_mode( FLU_MULTI_SELECT );
-  selection_drag_mode( FLU_DRAG_TO_SELECT );
-  insertion_mode( FLU_INSERT_SORTED );
-  show_connectors( true );
-  show_root( true );
-  show_leaves( true );
-  show_branches( true );
-  open_on_select( false );
-  //root_always_open( false );
-  horizontal_gap( 2 );
-  vertical_gap( 0 );
-  widget_gap( 2 );
-  set_root( l );
-
-  resize( x, y, w, h );
-}
-
-Flu_Tree_Browser :: ~Flu_Tree_Browser()
-{
-  delete rdata.defaultCollapseIcons[0];
-  delete rdata.defaultCollapseIcons[1];
-
-  delete rdata.defaultBranchIcons[0];
-  delete rdata.defaultBranchIcons[1];
-}
-
-void Flu_Tree_Browser :: auto_branches( bool b )
-{
-  rdata.autoBranches = b;
-}
-
-void Flu_Tree_Browser :: collapse_icons( Fl_Image *closed, Fl_Image *open )
-{
-  if( closed )
-    rdata.collapseIcons[0] = closed;
-  else
-    rdata.collapseIcons[0] = rdata.defaultCollapseIcons[0];
-
-  if( open )
-    rdata.collapseIcons[1] = open;
-  else
-    rdata.collapseIcons[1] = rdata.defaultCollapseIcons[1];
-}
-
-void Flu_Tree_Browser :: branch_icons( Fl_Image *closed, Fl_Image *open )
-{
-  //if( closed )
-  rdata.branchIcons[0] = closed;
-  //else
-  //rdata.branchIcons[0] = rdata.defaultBranchIcons[0];
-
-  //if( open )
-  rdata.branchIcons[1] = open;
-  //else
-  //rdata.branchIcons[1] = rdata.defaultBranchIcons[1];
-}
-
-void Flu_Tree_Browser :: set_default_branch_icons()
-{
-  rdata.branchIcons[0] = rdata.defaultBranchIcons[0];
-  rdata.branchIcons[1] = rdata.defaultBranchIcons[1];
-}
-
-void Flu_Tree_Browser :: leaf_icon( Fl_Image *icon )
-{
-  rdata.leafIcon = icon;
-}
-
-bool Flu_Tree_Browser :: inside_entry_area( int x, int y )
-{
-  if( scrollH->visible() && scrollV->visible() )
-    return( x > _box->x() && y > _box->y() &&
-	    x < (_box->x()+_box->w()-scrollV->w()) &&
-	    y < (_box->y()+_box->h()-scrollH->h()) );
-  else if( !scrollH->visible() && !scrollV->visible() )
-    return( x > _box->x() && y > _box->y() &&
-	    x < (_box->x()+_box->w()) &&
-	    y < (_box->y()+_box->h()) );
-  else if( scrollH->visible() )
-    return( x > _box->x() && y > _box->y() &&
-	    x < (_box->x()+_box->w()) &&
-	    y < (_box->y()+_box->h()-scrollH->h()) );
-  else
-    return( x > _box->x() && y > _box->y() &&
-	    x < (_box->x()+_box->w()-scrollV->w()) &&
-	    y < (_box->y()+_box->h()) );
-}
-
-void Flu_Tree_Browser :: resize( int X, int Y, int W, int H )
-{
-  Fl_Group::resize( X, Y, W, H );
-
-  int dx = Fl::box_dx(box()), dy = Fl::box_dy(box()), dw = Fl::box_dw(box()), dh = Fl::box_dh(box());
-
-  rdata.x = X+dx; rdata.y = Y+dy; rdata.totalW = rdata.x;
-  root.recurse( rdata, Node::MEASURE );
-  rdata.totalW -= X-dx;
-  rdata.totalH = rdata.y - Y-dy;
-
-  // if the size of the tree is bigger than the window, turn on the scrollbars
-  bool hOn = false, vOn = false;
-  if( rdata.totalW > W-dw )
-    hOn = true;
-  if( rdata.totalH > H-dh )
-    vOn = true;
-
-  // check if turning on one scrollbar actually forces the other to turn on
-  if( hOn && ( rdata.totalH > H-SCROLL_SIZE ) )
-    vOn = true;
-  if( vOn && ( rdata.totalW > W-SCROLL_SIZE ) )
-    hOn = true;
-
-  // now resize the other kids depending on the state of the scrollbars
-
-  _box->resize( X, Y, W, H );
-  if( hOn && vOn )  // both scrollbars on
-    {
-      scrollH->resize( X+dx, Y+H-SCROLL_SIZE-dy, W-SCROLL_SIZE-dw, SCROLL_SIZE );
-      scrollH->show();
-      scrollV->resize( X+W-SCROLL_SIZE-dx, Y+dy, SCROLL_SIZE, H-SCROLL_SIZE-dh );
-      scrollV->show();
-      scrollBox->resize( X+W-SCROLL_SIZE-dx, Y+H-SCROLL_SIZE-dy, SCROLL_SIZE, SCROLL_SIZE );
-      scrollBox->show();
-
-      // set the scrollbar sizes and values
-      int hDelta = rdata.totalW - W+dw + SCROLL_SIZE, scrollHW = scrollH->w()-SCROLL_SIZE-SCROLL_SIZE;
-      hDelta = MAX( hDelta, 0 );
-      scrollH->value( MIN( scrollH->value(), hDelta ), 1, 0, hDelta );
-      scrollH->slider_size( MAX( (float)SCROLL_SIZE/float(scrollHW), float(scrollHW-hDelta)/float(scrollHW) ) );
-
-      int vDelta = rdata.totalH - H+dh + SCROLL_SIZE, scrollVH = scrollV->h()-SCROLL_SIZE-SCROLL_SIZE;
-      vDelta = MAX( vDelta, 0 );
-      scrollV->value( MIN( scrollV->value(), vDelta ), 1, 0, vDelta );
-      scrollV->slider_size( MAX( (float)SCROLL_SIZE/float(scrollVH), float(scrollVH-vDelta)/float(scrollVH) ) );
-      _box->resize( X, Y, W-SCROLL_SIZE, H-SCROLL_SIZE );
-    }
-  else if( !hOn && !vOn )  // neither on
-    {
-      scrollH->hide();
-      scrollV->hide();
-      scrollBox->hide();
-    }
-  else if( hOn )  // just horizontal on
-    {
-      scrollH->resize( X+dx, Y+H-SCROLL_SIZE-dy, W-dw, SCROLL_SIZE );
-      scrollH->show();
-      scrollV->hide();
-      scrollBox->hide();
-
-      // set the scrollbar size and value
-      int hDelta = rdata.totalW - W+dw, scrollHW = scrollH->w()-SCROLL_SIZE-SCROLL_SIZE;
-      hDelta = MAX( hDelta, 0 );
-      scrollH->value( MIN( scrollH->value(), hDelta ), 1, 0, hDelta );
-      scrollH->slider_size( MAX( (float)SCROLL_SIZE/float(scrollHW), float(scrollHW-hDelta)/float(scrollHW) ) );
-      _box->resize( X, Y, W, H-SCROLL_SIZE );
-    }
-  else if( vOn )  // just vertical on
-    {
-      scrollH->hide();
-      scrollV->resize( X+W-SCROLL_SIZE-dx, Y+dy, SCROLL_SIZE, H-dh );
-      scrollV->show();
-      scrollBox->hide();
-
-      // set the scrollbar size and value
-      int vDelta = rdata.totalH - H+dh, scrollVH = scrollV->h()-SCROLL_SIZE-SCROLL_SIZE;
-      vDelta = MAX( vDelta, 0 );
-      scrollV->value( MIN( scrollV->value(), vDelta ), 1, 0, vDelta );
-      scrollV->slider_size( MAX( (float)SCROLL_SIZE/float(scrollVH), float(scrollVH-vDelta)/float(scrollVH) ) );
-      _box->resize( X, Y, W-SCROLL_SIZE, H );
-    }
-
-  rdata.browserX = _box->x() + dx;
-  rdata.browserY = _box->y() + dy;
-  rdata.browserW = _box->w() - dw;
-  rdata.browserH = _box->h() - dh;
-
-  redraw();
-
-  rdata.forceResize = true;  // weird hack to get the scrollbars to turn on right the first time
-}
-
-int Flu_Tree_Browser :: handle( int event )
-{
-  if( event == FL_NO_EVENT )//|| event == FL_MOVE )
-    return 0;
-
-  if( event == FL_FOCUS )//&& rdata.lastHilighted )
-    {
-      //set_hilighted( rdata.lastHilighted );
-      //lastEvent = event;
-      //Fl_Group::handle( event );
-      redraw();
-      return 1;
-    }
-
-  if( event == FL_UNFOCUS )
-    {
-      //if( lastEvent != FL_LEAVE )
-      //{
-	  //rdata.lastHilighted = rdata.hilighted;
-      //}
-      //set_hilighted( NULL );
-      //lastEvent = event;
-      Fl_Group::handle( event );
-      redraw();
-      return 1;
-    }
-
-  if( !rdata.dragging && !( event == FL_MOVE && rdata.selectUnderMouse ) )
-    {
-      if( ! (event == FL_MOVE || event == FL_ENTER || event == FL_LEAVE ) )
-	_box->redraw();
-
-      if( Fl_Group::handle( event ) )
-	{
-	  //if( event == FL_KEYDOWN || event == FL_KEYUP )
-	  // redraw();
-	  return 1;
-	}
-      //if (scrollV && Fl::event_inside(scrollV) && scrollV->handle(event)) return 1;
-      //if (scrollH && Fl::event_inside(scrollH) && scrollH->handle(event)) return 1;
-    }
-
-  if( event == FL_RELEASE )
-    {
-      //Fl::focus(this);
-      rdata.dragging = false;
-      rdata.grabbed = 0;
-      rdata.dragNode = 0;
-      //redraw();
-    }
-
-  int dx = Fl::box_dx(box()), dy = Fl::box_dy(box());
-
-  // set some initial values for the recursive data structure
-  // account for the scrollbar positions
-  rdata.x = x()+dx; rdata.y = y()+dy;
-  if( scrollH->visible() )
-    rdata.x -= scrollH->value();
-  if( scrollV->visible() )
-    rdata.y -= scrollV->value();
-
-  rdata.previous = NULL;
-  rdata.delta = 0;
-  rdata.visibilityChanged = false;
-
-  // catch cursor keys for moving the hilighted entry or selecting all entries
-  if( event == FL_KEYDOWN )
-    {
-      // move hilighted entry up
-      if( Fl::event_key() == FL_Up )
-	{
-	  rdata.delta = -1;
-	  Fl::focus(this);
-	  redraw();
-	}
-
-      // move hilighted entry down
-      else if( Fl::event_key() == FL_Down )
-	{
-	  rdata.delta = 1;
-	  Fl::focus(this);
-	  redraw();
-	}
-
-      // select all
-      else if( Fl::event_state(FL_CTRL) && Fl::event_key() == 'a' )
-	{
-	  select_all();
-	  Fl::focus(this);
-	  redraw();
-	  return 1;
-	}
-
-      // check for the Home key
-      else if( Fl::event_key() == FL_Home )
-	{
-	  // set the hilighted entry to be the first entry
-	  if( rdata.showRoot || ( rdata.root->_children.size() == 0 ) )
-	    set_hilighted( rdata.root );
-	  else if( rdata.root->_children.size() > 0 )
-	    set_hilighted( rdata.root->_children.child(0) );
-	  redraw();
-	}
-
-      // check for the End key
-      else if( Fl::event_key() == FL_End )
-	{
-	  // set the hilighted entry to be the last visible entry
-	  if( rdata.showRoot && ( rdata.root->_children.size() == 0 ) )
-	    set_hilighted( rdata.root );
-	  else
-	    {
-	      // find the last node by repeatedly looking for the last child until there are no more branches
-	      Node *n = &root;
-	      while( n->_children.size() && n->open() )
-		n = n->_children.child( n->_children.size()-1 );
-	      set_hilighted( n );
-	    }
-	  redraw();
-	}
-    }
-
-  // pass the event down the tree
-  int val = root.recurse( rdata, Node::HANDLE, event );
-  if( val )
-    {
-      //redraw();
-      if( rdata.visibilityChanged )
-	root.determineVisibility();
-      if( val == 1 )
-	return 1;
-    }
-  // special case: if multi-select or single-select and user clicks on no items, unselect all items
-  else if( (rdata.selectionMode != FLU_NO_SELECT) && (event == FL_PUSH) && (!Fl::event_state(FL_CTRL)) )
-    {
-      unselect_all();
-      set_hilighted( NULL );
-      rdata.forceResize = true;
-      redraw();
-
-      return 1;
-    }
-
-  if( event == FL_SHOW || event == FL_HIDE )
-    root.determineVisibility();
-
-  return Fl_Group::handle( event );
-  //return 0;
-}
-
-void Flu_Tree_Browser :: insertion_mode( int m )
-{
-  rdata.insertionMode = m;
-  root.sort();
-}
-
-void Flu_Tree_Browser :: set_hilighted( Flu_Tree_Browser::Node* n )
-{
-  if( rdata.hilighted == n  &&  when() != FL_WHEN_NOT_CHANGED )
-    return;
-
-  if( rdata.hilighted )
-    rdata.hilighted->do_callback( FLU_UNHILIGHTED );
-  rdata.hilighted = n;
-  if( rdata.hilighted )
-    rdata.hilighted->do_callback( FLU_HILIGHTED );
-
-  if( rdata.hilighted )
-    {
-      if( rdata.selectionFollowsHilight )
-	{
-	  if( rdata.selectionMode == FLU_SINGLE_SELECT )
-	    unselect_all();
-	  rdata.hilighted->select( true );
-	}
-
-      int extraH = scrollH->visible() ? scrollH->h() : 0;
-
-      // if the hilighted entry is below the visible bounds of the browser, move the vertical scrollbar
-      // so the hilighted entry is the last visible entry
-      if( rdata.hilighted->currentY-y()+rdata.hilighted->currentH > scrollV->value()+h()-extraH )
-	((Fl_Valuator*)scrollV)->value( rdata.hilighted->currentY-y() - h()+extraH + rdata.hilighted->currentH );
-
-      // if the hilighted entry is above the visible bounds of the browser, move the vertical scrollbar
-      // so the hilighted entry is the first visible entry
-      if( rdata.hilighted->currentY-y() < scrollV->value() )
-	((Fl_Valuator*)scrollV)->value( rdata.hilighted->currentY-y() );
-    }
-  redraw();
-}
-
-int Flu_Tree_Browser :: num_selected()
-{
-  return root.recurse( rdata, Node::COUNT_SELECTED );
-}
-
-int Flu_Tree_Browser :: Node :: num_selected()
-{
-  return recurse( tree->rdata, COUNT_SELECTED );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: get_selected( int index )
-{
-  return root.get_selected( index );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: get_selected( int index )
-{
-  tree->rdata.counter = 0;
-  tree->rdata.searchIndex = index;
-  Node *n = modify( 0, GET_SELECTED, tree->rdata );
-  tree->rdata.searchIndex = 1;
-  return n;
-}
-
-Flu_Tree_Browser :: Node :: Node( const char *lbl )
-{
-  flags = 0;
-  userData = 0;
-  _parent = 0;
-  _widget = 0;
-  _group = 0;
-  SET(ACTIVE);
-  CLEAR(LEAF);
-  _id = 0;
-  CLEAR(ALWAYS_OPEN);
-  SET(COLLAPSED);
-  SET(MOVABLE);
-  SET(DROPPABLE);
-  currentY = currentH = 0;
-  CLEAR(SELECTED);
-  CLEAR(EXPAND_TO_WIDTH);
-  SET(SHOW_LABEL);
-  if( lbl == 0 )
-    text = "";
-  else
-    text = lbl;
-
-  cIcon[0] = cIcon[1] = bIcon[0] = bIcon[1] = lIcon = 0;
-}
-
-Flu_Tree_Browser :: Node :: Node( bool l, const char* n, Node *p, RData &rdata, Fl_Widget *w, bool showLbl )
-{
-  _group = 0;
-  flags = 0;
-  userData = 0;
-  SET(LEAF,l);
-  text = n;
-  _id = 0;
-  SET(ACTIVE);
-  _parent = p;
-  CLEAR(ALWAYS_OPEN);
-  SET(COLLAPSED);
-  CLEAR(SELECTED);
-  CLEAR(EXPAND_TO_WIDTH);
-  SET(MOVABLE);
-  SET(DROPPABLE);
-  _widget = 0;
-  currentY = currentH = 0;
-  cIcon[0] = cIcon[1] = bIcon[0] = bIcon[1] = lIcon = 0;
-  SET( SHOW_LABEL, showLbl );
-  tree = rdata.tree;
-
-  initType();
-
-  _id = rdata.nextId++;
-  widget( w );
-}
-
-void Flu_Tree_Browser :: Node :: initType()
-{
-  if( is_leaf() )
-    {
-      lIcon = tree->rdata.leafIcon;
-      textColor = tree->rdata.defLeafColor;
-      textFont = tree->rdata.defLeafFont;
-      textSize = tree->rdata.defLeafSize;
-    }
-  else
-    {
-      cIcon[0] = tree->rdata.collapseIcons[0];
-      cIcon[1] = tree->rdata.collapseIcons[1];
-      bIcon[0] = tree->rdata.branchIcons[0];
-      bIcon[1] = tree->rdata.branchIcons[1];
-      textColor = tree->rdata.defBranchColor;
-      textFont = tree->rdata.defBranchFont;
-      textSize = tree->rdata.defBranchSize;
-    }
-}
-
-Flu_Tree_Browser :: Node :: ~Node()
-{
-  // if this node is in a tree, make sure it isn't holding a reference to us
-  if( tree )
-    {
-      if( tree->rdata.hilighted == this ) tree->rdata.hilighted = NULL;
-      //if( tree->rdata.lastHilighted == this ) tree->rdata.lastHilighted = NULL;
-      if( tree->rdata.grabbed == this ) tree->rdata.grabbed = NULL;
-      if( tree->rdata.dragNode == this ) tree->rdata.dragNode = NULL;
-    }
-  clear();
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: first()
-{
-  return this;
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: first_branch()
-{
-  Node *n = first();
-  while( n )
-    {
-      if( n->is_branch() )
-	return n;
-      else
-	n = n->next();
-    }
-  return NULL;
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: first_leaf()
-{
-  Node *n = first();
-  while( n )
-    {
-      if( n->is_leaf() )
-	return n;
-      else
-	n = n->next();
-    }
-  return NULL;
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: last()
-{
-  if( children() == 0 )
-    return this;
-  else
-    return( child( children() - 1 )->last() );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: last_branch()
-{
-  Node *n = last();
-  while( n )
-    {
-      if( n->is_branch() )
-	return n;
-      else
-	n = n->previous();
-    }
-  return NULL;
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: last_leaf()
-{
-  Node *n = last();
-  while( n )
-    {
-      if( n->is_leaf() )
-	return n;
-      else
-	n = n->previous();
-    }
-  return NULL;
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: next_sibling()
-{
-  if( is_root() )
-    return NULL;
-  int index;
-  for( index = 0; index < _parent->children(); index++ )
-    if( _parent->child(index) == this )
-      break;
-  // if we are the last child of our parent, then we have no next sibling
-  if( index == _parent->children()-1 )
-    return NULL;
-  // otherwise return our next sibling
-  else
-    return( _parent->child(index+1) );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: previous_sibling()
-{
-  if( is_root() )
-    return NULL;
-  int index;
-  for( index = 0; index < _parent->children(); index++ )
-    if( _parent->child(index) == this )
-      break;
-  // if we are the first child of our parent, then we have no previous sibling
-  if( index == 0 )
-    return NULL;
-  // otherwise return our previous sibling
-  else
-    return( _parent->child(index-1) );
-}
-
-int Flu_Tree_Browser :: Node :: index() const
-{
-  if( is_root() )
-    return -1;
-  int index;
-  for( index = 0; index < _parent->children(); index++ )
-    if( _parent->child(index) == this )
-      return index;
-  return -1;
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: next()
-{
-  // take care of the root node as a special case
-  if( is_root() )
-    {
-      if( children() )
-	return child(0);
-      else
-	return NULL;
-    }
-
-  // if we are a branch, then the next node is our first child, unless we don't have any children
-  if( is_branch() && _children.size() )
-    return _children.child(0);
-  else
-    {
-      // otherwise, the next node is our next sibling. if there is no next sibling (because we
-      // are the last child of our parent), then the next node is the next sibling of our parent (and so on...)
-      Node *p = parent(), *n = next_sibling();
-      while( p )
-	{
-	  if( n )
-	    return n;
-	  else
-	    {
-	      n = p->next_sibling();
-	      p = p->parent();
-	    }
-	}
-      return NULL;
-    }
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: next_branch()
-{
-  Node *n = next();
-  while( n )
-    {
-      if( n->is_branch() )
-	return n;
-      else
-	n = n->next();
-    }
-  return NULL;
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: next_leaf()
-{
-  Node *n = next();
-  while( n )
-    {
-      if( n->is_leaf() )
-	return n;
-      else
-	n = n->next();
-    }
-  return NULL;
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: previous()
-{
-  // take care of the root node as a special case
-  if( is_root() )
-    return NULL;
-
-  // the previous node is either our parent's
-  // previous sibling (if that sibling exists and is a leaf or a branch with no children),
-  // or the last child of our parent's previous sibling (if that sibling exists and is
-  // a branch with children). if there is no previous sibling, then the previous node
-  // is our parent
-  Node *n = previous_sibling();
-  if( !n )
-    return _parent;
-  else
-    {
-      if( n->is_leaf() )  // is leaf, so that is the previous node
-	return n;
-      else if( n->children() )  // is branch with some children, so previous node is last child
-	return( n->last() );
-      else  // is branch with no children, so that is the previous node
-	return n;
-    }
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: previous_branch()
-{
-  Node *n = previous();
-  while( n )
-    {
-      if( n->is_branch() )
-	return n;
-      else
-	n = n->previous();
-    }
-  return NULL;
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: previous_leaf()
-{
-  Node *n = previous();
-  while( n )
-    {
-      if( n->is_leaf() )
-	return n;
-      else
-	n = n->previous();
-    }
-  return NULL;
-}
-
-void Flu_Tree_Browser :: Node :: determineVisibility( bool parentVisible )
-{
-  if( _widget )
-    {
-      if( parentVisible )
-	_widget->w->show();
-      else
-	_widget->w->hide();
-    }
-  for( int i = 0; i < _children.size(); i++ )
-    _children.child(i)->determineVisibility( parentVisible && open() );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: child( int i ) const
-{
-  if( i < 0 || i >= _children.size() )
-    return 0;
-  else
-    return _children.child(i);
-}
-
-void Flu_Tree_Browser :: Node :: clear()
-{
-  widget(NULL);
-  for( int i = 0; i < _children.size(); i++ )
-    {
-      //if( tree->rdata.cbNode == _children.child(i) )
-      //tree->rdata.cbNode = NULL;
-      delete _children.child(i);
-    }
-  _children.clear();
-  if( _group )
-    {
-      if( _group->parent() )
-	_group->parent()->remove( *_group );
-      while( _group->children() )
-	_group->remove( *_group->child(0) );
-      delete _group;
-      _group = NULL;
-    }
-}
-
-void Flu_Tree_Browser :: Node :: print( int spaces )
-{
-  for( int s = 0; s < spaces; s++ )
-    printf( " " );
-  if( is_leaf() )
-    printf( "  %s\n", text.c_str() );
-  else
-    printf( "[%s]\n", text.c_str() );
-
-  for( int i = 0; i < _children.size(); i++ )
-    _children.child(i)->print( spaces+2 );
-}
-
-void Flu_Tree_Browser :: draw()
-{
-  if( rdata.forceResize )
-    {
-      resize( x(), y(), w(), h() );
-      rdata.forceResize = false;
-    }
-
-  // draw the background color
-  //fl_draw_box( _box->box(), _box->x(), _box->y(), _box->w(), _box->h(), _box->color() );
-  fl_draw_box( box(), x(), y(), w(), h(), color() );
-
-  int dx = Fl::box_dx(box()), dy = Fl::box_dy(box()),
-    dw = Fl::box_dw(box()), dh = Fl::box_dh(box());
-
-  // set up the recursive data structure
-  rdata.x = x()+dx; rdata.y = y()+dy;
-  // account for the positions of the scrollbars
-  if( scrollH->visible() )
-    rdata.x -= scrollH->value();
-  if( scrollV->visible() )
-    rdata.y -= scrollV->value();
-
-  rdata.last = true;
-  rdata.bgColor = _box->color();
-  rdata.shadedIndex = 0;
-
-  // pick the connector line and selection colors depending on the active state
-  if( active() )
-    {
-      rdata.lineColor = rdata.defLineColor;
-      rdata.selectionColor = rdata.defSelectionColor;
-    }
-  else
-    {
-      rdata.lineColor = fl_inactive( rdata.defLineColor );
-      rdata.selectionColor = fl_inactive( rdata.defSelectionColor );
-    }
-
-  // draw the tree
-  fl_push_clip( x()+dx, y()+dy, w()-dw, h()-dh );
-  root.recurse( rdata, Node::DRAW );
-
-  fl_pop_clip();
-
-  // draw the kids
-  draw_child( *scrollBox );
-  draw_child( *scrollH );
-  draw_child( *scrollV );
-
-  // draw the box last so it's on top
-  //fl_draw_box( _box->box(), _box->x(), _box->y(), _box->w(), _box->h(), _box->color() );
-}
-
-inline void draw_T( int x, int y, int w, int h )
-{
-  int w2 = w >> 1;
-  int h2 = h >> 1;
-  fl_line( x+w2, y, x+w2, y+h );
-  fl_line( x+w2, y+h2, x+w, y+h2 );
-}
-
-inline void draw_L( int x, int y, int w, int h )
-{
-  int w2 = w >> 1;
-  int h2 = h >> 1;
-  fl_line( x+w2, y, x+w2, y+h2 );
-  fl_line( x+w2, y+h2, x+w, y+h2 );
-}
-
-inline void draw_Lflip( int x, int y, int w, int h )
-{
-  int w2 = w >> 1;
-  int h2 = h >> 1;
-  fl_line( x+w2, y+h, x+w2, y+h2 );
-  fl_line( x+w2, y+h2, x, y+h2 );
-}
-
-inline void draw_Lflop( int x, int y, int w, int h )
-{
-  int w2 = w >> 1;
-  int h2 = h >> 1;
-  fl_line( x+w2, y+h, x+w2, y+h2 );
-  fl_line( x+w2, y+h2, x+w, y+h2 );
-}
-
-inline void draw_Ldash( int x, int y, int w, int h )
-{
-  w = w >> 1;
-  h = h >> 1;
-  fl_line( x, y+h, x+w, y+h );
-}
-
-inline void draw_vert_dash( int x, int y, int w, int h )
-{
-  w = w >> 1;
-  fl_line( x+w, y+(h>>1), x+w, y+h );
-}
-
-inline void draw_Rdash( int x, int y, int w, int h )
-{
-  h = h >> 1;
-  fl_line( x+w, y+h, x+(w>>1), y+h );
-}
-
-void Flu_Tree_Browser :: Node :: draw( RData &rdata, bool measure )
-{
-  int which = open(); // i.e. which icon: open or closed?
-  bool skipCollapser = is_root() && rdata.showRoot && ( CHECK(ALWAYS_OPEN) || rdata.allBranchesAlwaysOpen );
-  int halfHGap = rdata.hGap >> 1, halfVGap = rdata.vGap >> 1;
-  bool doDraw = !measure;
-
-  int X = rdata.x;
-  int Y = rdata.y;
-
-  Fl_Color bgColor = rdata.shadedColors[rdata.shadedIndex], tColor = textColor, hilightColor = rdata.selectionColor;
-
-  // pick the text color depending on the active state
-  if( !rdata.tree->active() || !CHECK(ACTIVE))
-    tColor = fl_inactive( tColor );
-
-  if( doDraw )
-    {
-      // draw the background for the entry using the entry background color
-      fl_draw_box( FL_FLAT_BOX, rdata.browserX, Y, rdata.browserW, currentH, bgColor );
-
-      // if dragging to the inside of a branch, hilight that branch
-      if( CHECK(SELECTED) )
-	{
-	  bgColor = rdata.selectionColor;
-	  tColor = fl_contrast( tColor, bgColor );
-	  hilightColor = rdata.bgColor;
-	  fl_draw_box( FL_FLAT_BOX, rdata.browserX, Y, rdata.browserW, currentH, bgColor );
-	}
-
-      fl_color( rdata.lineColor );
-      fl_line_style( rdata.lineStyle, rdata.lineWidth );
-    }
-
-  if( is_leaf() ) // draw leaves one way...
-    {
-      // draw the connectors
-      if( doDraw && rdata.showConnectors && rdata.showBranches )
-	{
-	  if( parent()->is_root() && !rdata.showRoot && rdata.first )
-	    {
-	      if( rdata.last )
-		draw_Rdash( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap );
-	      else
-		draw_Lflop( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap );
-	    }
-	  else if( rdata.last )
-	    draw_L( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap );
-	  else
-	    draw_T( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap );
-	}
-
-      // account for leaf icon spacing
-      if( rdata.showBranches )
-	{
-	  if( lIcon )
-	    X += rdata.collapseIcons[which]->w() + rdata.hGap;
-	  else
-	    X += rdata.collapseIcons[which]->w() + rdata.wGap;
-	}
-      else 
-	X += rdata.wGap;
-
-      // draw some more connectors
-      if( doDraw && rdata.showConnectors && lIcon && rdata.showBranches )
-	draw_Ldash( X-halfHGap, Y-halfVGap, lIcon->w()+rdata.hGap, currentH+rdata.vGap );
-
-      // draw the leaf icon
-      if( lIcon && !CHECK(ICON_AT_END) )
-	{
-	  if( doDraw )
-	    lIcon->draw( X, Y+(currentH>>1)-(lIcon->h()>>1) );
-	  X += lIcon->w() + rdata.wGap;
-	}
-    }
-  else // ...and branches another
-    {
-      // force the root to the left if it has no visible children
-      if( is_root() && !CHECK(SOME_VISIBLE_CHILDREN) )
-	{
-	  skipCollapser = true;
-	  which = 0;
-	}
-
-      if( !CHECK(SOME_VISIBLE_CHILDREN) && !rdata.showLeaves )
-	which = 0;
-
-      // draw the connectors
-      if( doDraw && !skipCollapser && rdata.showConnectors && rdata.showBranches )
-	{
-	  if( is_root() )
-	    {
-	      if( CHECK(SOME_VISIBLE_CHILDREN) )
-		draw_Rdash( X-halfHGap, Y-halfVGap, rdata.collapseIcons[which]->w()+4+rdata.hGap, currentH+rdata.vGap );
-	    }
-	  else if( parent()->is_root() && !rdata.showRoot && rdata.first )
-	    {
-	      if( rdata.last )
-		draw_Rdash( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap );
-	      else
-		draw_Lflop( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap );
-	    }
-	  else if( rdata.last )
-	    draw_L( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap );
-	  else
-	    draw_T( X-halfHGap, Y-halfVGap, rdata.branchIconW+rdata.hGap, currentH+rdata.vGap );
-	}
-
-      // draw the collapsed icons
-      if( doDraw && !skipCollapser && !CHECK(ALWAYS_OPEN) && !rdata.allBranchesAlwaysOpen )
-	{
-	  if( CHECK(SOME_VISIBLE_CHILDREN) || rdata.showLeaves )
-	    {
-	      if( !rdata.openWOChildren && !CHECK(SOME_VISIBLE_CHILDREN) )
-		which = 0;
-	      if( rdata.openWOChildren || CHECK(SOME_VISIBLE_CHILDREN) )
-		{
-		  if( _parent==0 )
-		    cIcon[which]->draw( X, Y+(currentH>>1)-(cIcon[which]->h()>>1) );
-		  else
-		    cIcon[which]->draw( X+(rdata.branchIconW>>1)-(cIcon[which]->w()>>1), Y+(currentH>>1)-(cIcon[which]->h()>>1) );
-		}
-	    }
-	}
-
-      if( !skipCollapser )
-	{
-	  X += cIcon[which]->w();
-	  if( bIcon[which] )
-	    X += rdata.hGap;
-	  else
-	    X += rdata.wGap;
-	}
-
-      // draw some more connectors
-      if( doDraw && rdata.showConnectors && rdata.showBranches )
-	{
-	  int hGap = rdata.hGap;
-	  if( bIcon[which] )
-	    hGap += bIcon[which]->w();
-	  if( skipCollapser && CHECK(SOME_VISIBLE_CHILDREN) )
-	    draw_vert_dash( X-halfHGap, Y-halfVGap, hGap, currentH+rdata.vGap );
-	  else if( !which || !CHECK(SOME_VISIBLE_CHILDREN) )
-	    draw_Ldash( X-halfHGap, Y-halfVGap, hGap, currentH+rdata.vGap );
-	  else
-	    draw_Lflip( X-halfHGap, Y-halfVGap, hGap, currentH+rdata.vGap );
-	}
-
-      // draw the branch icon
-      if( bIcon[which] )
-	{
-	  if( doDraw )
-	    bIcon[which]->draw( X, Y+(currentH>>1)-(bIcon[which]->h()>>1) );
-	  X += bIcon[which]->w() + rdata.wGap;
-	}
-      else
-	X += rdata.wGap;
-    }
-
-  if( doDraw )
-    fl_line_style( 0 );
-
-  // draw the entry
-  if( CHECK(SHOW_LABEL) && !CHECK(SWAP_LABEL_AND_WIDGET) )
-    {
-      if( doDraw )
-	{
-	  fl_draw_box( FL_FLAT_BOX, X, Y+(currentH>>1)-(textH>>1), textW, textH, bgColor );
-	  fl_color( tColor );
-	  fl_font( textFont, textSize );
-	  fl_draw( text.c_str(), X, Y+(currentH>>1)-(textH>>1), textW, textH, FL_ALIGN_LEFT );
-	}
-      X += textW;
-    }
-
-  if( _widget )
-    {
-      int widgetW = _widget->w->w();
-      int widgetH = _widget->w->h();
-      if( doDraw )
-	{
-	  if( CHECK(AUTO_COLOR) )
-	    _widget->w->color( bgColor );
-	  if( CHECK(AUTO_LABEL_COLOR) )
-	    _widget->w->labelcolor( tColor );
-	  if( CHECK(AUTO_LABEL) )
-	    _widget->w->label( text.c_str() );
-	  _widget->w->redraw();
-	  _widget->w->position( X, Y+(currentH>>1)-(widgetH>>1) );
-	  if( CHECK(EXPAND_TO_WIDTH) )
-	    _widget->w->size( MAX( _widget->defaultW, rdata.browserW - (X-rdata.browserX) ), _widget->w->h() );
-	  _widget->w->draw();
-	}
-      if( CHECK(EXPAND_TO_WIDTH) )
-	{
-	  if( _widget->w->w() == _widget->defaultW )
-	    X += _widget->defaultW;
-	}
-      else
-	X += widgetW;
-    }
-
-  if( CHECK(SHOW_LABEL) && CHECK(SWAP_LABEL_AND_WIDGET) )
-    {
-      if( doDraw )
-	{
-	  fl_draw_box( FL_FLAT_BOX, X, Y+(currentH>>1)-(textH>>1), textW, textH, bgColor );
-	  fl_color( tColor );
-	  fl_font( textFont, textSize );
-	  fl_draw( text.c_str(), X, Y+(currentH>>1)-(textH>>1), textW, textH, FL_ALIGN_LEFT );
-	}
-      X += textW;
-    }
-
-  // draw the leaf icon to the right of the label and widget
-  if( is_leaf() && lIcon && CHECK(ICON_AT_END) )
-    {
-      if( doDraw )
-	lIcon->draw( X, Y+(currentH>>1)-(lIcon->h()>>1) );
-      X += lIcon->w() + rdata.wGap;
-    }
-
-  // if hilighted, draw a box outlining the entry
-  if( Fl::focus() == tree && rdata.hilighted == this && doDraw )
-    {
-      fl_color( hilightColor );
-      fl_line_style( FL_DOT, 1 );
-      fl_rect( rdata.browserX, Y, rdata.browserW, currentH, hilightColor );
-      fl_line_style( 0 );
-    }
-
-  rdata.totalW = MAX( rdata.totalW, X );
-}
-
-void Flu_Tree_Browser :: Node :: select( bool b )
-{
-  if( (CHECK(SELECTED)==b) && (tree->when() != FL_WHEN_NOT_CHANGED) )
-    return;
-  SET(SELECTED,b);
-  tree->redraw();
-  if( tree->when() == FL_WHEN_RELEASE )
-    return;
-  if( b )
-    do_callback( FLU_SELECTED );
-  else
-    do_callback( FLU_UNSELECTED );
-}
-
-void Flu_Tree_Browser :: Node :: open( bool b )
-{
-  if( is_leaf() )
-    return;
-
-  if( CHECK(ALWAYS_OPEN) || tree->rdata.allBranchesAlwaysOpen )
-    return;
-
-  if( (open() == b) && (tree->when() != FL_WHEN_NOT_CHANGED) )
-    return;
-
-  tree->rdata.justOpenedClosed = true;
-
-  SET(COLLAPSED,!b);
-
-  if( open() && (_parent != 0) ) // root node doesn't count as a single open branch
-    {
-      if( ( tree->rdata.lastOpenBranch != this ) && tree->rdata.singleBranchOpen )
-	tree->rdata.lastOpenBranch->close();
-      tree->rdata.lastOpenBranch = this;
-    }
-
-  tree->rdata.forceResize = true;
-  tree->rdata.visibilityChanged = true;
-  if( b )
-    do_callback( FLU_OPENED );
-  else
-    do_callback( FLU_CLOSED );
-}
-
-void Flu_Tree_Browser :: Node :: active( bool b )
-{
-  if( CHECK(ACTIVE) == b  &&  tree->when() != FL_WHEN_NOT_CHANGED )
-    return;
-  SET( ACTIVE, b );
-  if( _widget )
-    {
-      if( b )
-	_widget->w->activate();
-      else
-	_widget->w->deactivate();
-    }
-  if( !CHECK(ACTIVE) )
-    {
-      if( tree->rdata.hilighted == this )
-	tree->set_hilighted( NULL );
-      select( false );
-      open( false );
-    }
-}
-
-void Flu_Tree_Browser :: Node :: unselect_all( Node* except )
-{
-  if( this != except )
-    select( false );
-  for( int i = 0; i < _children.size(); i++ )
-    _children.child(i)->unselect_all( except );
-}
-
-void Flu_Tree_Browser :: Node :: select_all()
-{
-  select( true );
-  for( int i = 0; i < _children.size(); i++ )
-    _children.child(i)->select_all();
-}
-
-bool Flu_Tree_Browser :: Node :: isMoveValid( Node* &n1, int &where, Node* &n2 )
-{
-  // if n1 is NULL, then check it as if it were a node being moved from another tree
-
-  if( n2 == NULL )
-    return false;
-
-  // check the validity of the move:
-  // 1) the source and destination nodes can't be the same
-  // 2) you can't move before the root node
-  // 3) you can't move an unmovable node or move a branch node such that it would become a descendent of itself
-  // 4) if moving only within the same group, check that the parents are the same
-  // 5) if moving into a sorted tree, the destination node MUST be a branch
-  // 6) a move AFTER an OPEN branch is a move BEFORE its first child
-  // 7) you can't move a node into a non-droppable branch node
-
-  if( n1 == n2 )
-    return false;
-
-  if( where==MOVE_BEFORE && n2->is_root() )
-    return false;
-
-  if( n1 )
-    {
-      if( !n1->movable() )
-	return false;
-      if( n1->is_branch() )
-	if( n1->is_descendent( n2 ) )
-	  return false;
-    }
-
-  bool sameGroup = n2->tree->move_only_same_group();
-  if( sameGroup && n1 )
-    {
-      if( n1->parent() != n2->parent() || where==MOVE_INSIDE )
-	return false;
-    }
-
-  int iMode = n2->tree->insertion_mode();
-  if( iMode == FLU_INSERT_SORTED || iMode == FLU_INSERT_SORTED_REVERSE )
-    {
-      if( n2->is_branch() )
-	{
-	  where = MOVE_INSIDE;
-	  return true;
-	}
-      else
-	return false;
-    }
-
-  if( where==MOVE_AFTER && n2->is_branch() && n2->open() )
-    {
-      // can't move inside a branch if within the same group, unless the first node is dragged 
-      // from outside the tree (in which case n1 is NULL)
-      if( sameGroup && n1 )
-	{
-	  if( n2->_children.size() > 0 )
-	    return false;
-	}
-      else if( n2->_children.size() > 0 )
-	{
-	  where = MOVE_BEFORE;
-	  n2 = n2->_children.child(0);
-	}
-      else
-	where = MOVE_INSIDE;
-    }
-
-  if( where==MOVE_INSIDE )
-    {
-      if( !n2->droppable() )
-	return false;
-    }
-  else if( n2->parent() )
-    if( !n2->parent()->droppable() )
-      return false;
-
-  return true;
-}
-
-int Flu_Tree_Browser :: Node :: recurse( RData &rdata, int type, int event )
-{
-  int i;
-
-  if( is_root() )
-    rdata.first = true;
-
-  if( type == COUNT_SELECTED )
-    {
-      if( is_leaf() )
-	return (int)CHECK(SELECTED);
-      else
-	{
-	  int total = (int)CHECK(SELECTED);
-	  for( i = 0; i < _children.size(); i++ )
-	    total += _children.child(i)->recurse( rdata, type, event );
-	  return total;
-	}
-    }
-
-  // see if this entry is even visible
-  if( rdata.y > rdata.browserY+rdata.browserH )
-    {
-      if( type == DRAW )
-	return 1;
-      else if( type == HANDLE )
-	return 0;
-    }
-
-  int which = open();
-  bool skipEntry = ( is_root() && !rdata.showRoot ) || ( is_leaf() && !rdata.showLeaves ) || ( is_branch() && !rdata.showBranches );
-  bool skipCollapser = is_root() && rdata.showRoot && ( CHECK(ALWAYS_OPEN) || rdata.allBranchesAlwaysOpen );
-
-  // find the size of the entry label
-  if( (type == MEASURE) || (type == MEASURE_THIS_OPEN) )
-    {
-      if( CHECK(SHOW_LABEL) )
-	{
-	  int W = 0, H;
-	  fl_font( textFont, textSize );
-	  fl_measure( text.c_str(), W, H );
-	  W += 4; H += 4;  // hack - it looks better
-	  textW = W;
-	  textH = H;
-	}
-      else
-	{
-	  textW = textH = 0;
-	}
-
-      // remember vertically where this node is w.r.t the browser
-      currentY = rdata.y;
-
-      currentH = textH;
-
-      // find the total size of the entry, depending on if there's a widget
-      if( _widget )
-	currentH = MAX( _widget->w->h(), currentH );
-
-      // find the total height of this entry by taking the max height of the entry and icons
-      if( is_leaf() )
-	{
-	  if( lIcon )
-	    currentH = MAX( currentH, lIcon->h() );
-	}
-      else
-	{
-	  currentH = MAX( currentH, cIcon[which]->h() );
-	  if( bIcon[which] )
-	    currentH = MAX( currentH, bIcon[which]->h() );
-	}
-    }
-
-  bool skipAhead = (rdata.y + currentH) < rdata.browserY;
-
-  // process the entry
-  switch( type )
-    {
-    case DRAW:
-      {
-	if( skipEntry || skipAhead ) break;
-
-	draw( rdata, false );
-
-	// draw any vertical connectors connecting our parents, grandparents, etc.,
-	if( rdata.showBranches )
-	  {
-	    int d = depth()-1;
-	    for( i = 0; i < rdata.branchConnectors.size(); i++ )
-	      {
-		if( i != d )
-		  {
-		    fl_color( rdata.lineColor );
-		    fl_line_style( rdata.lineStyle, rdata.lineWidth );
-		    fl_line( rdata.branchConnectors[i], rdata.y, rdata.branchConnectors[i], rdata.y+currentH );
-		    fl_line_style( 0 );
-		  }
-	      }
-	  }
-
-	rdata.shadedIndex = 1 - rdata.shadedIndex;  // toggle the even/odd entry for shading
-      }
-      break;
-
-    case MEASURE:
-      if( is_leaf() )
-	CLEAR( SOME_VISIBLE_CHILDREN );
-      else
-	{
-	  // find out whether the branch has any children that could be visible
-	  bool someVisibleChildren = rdata.showLeaves && ( _children.size() > 0 );
-	  for( i = 0; i < _children.size(); i++ )
-	    {
-	      if( _children.child(i)->is_branch() )
-		{
-		  someVisibleChildren = true;
-		  break;
-		}
-	    }
-	  SET( SOME_VISIBLE_CHILDREN, someVisibleChildren );
-	}
-
-    case MEASURE_THIS_OPEN:
-      if( skipEntry ) break;
-      draw( rdata, true );
-      break;
-
-    case HANDLE:
-      {
-	if( skipEntry || skipAhead || !CHECK(ACTIVE) ) break;
-
-	if( event != FL_DRAG && event != FL_NO_EVENT )
-	  rdata.justOpenedClosed = false;
-
-	// if we are trying to select all entries between 2 widgets due to a shift-select...
-	if( rdata.shiftSelect )
-	  {
-	    if( (rdata.hilighted == this) || (rdata.grabbed == this) )
-	      {
-		if( !rdata.shiftSelectAll )
-		  {
-		    rdata.shiftSelectAll = true;
-		    select( true );
-		    if( is_branch() && rdata.openOnSelect )
-		      {
-			open( true );
-		      }
-		  }
-		else
-		  {
-		    rdata.shiftSelect = false;
-		    rdata.shiftSelectAll = false;
-		    rdata.grabbed = 0;
-		    select( true );
-		    if( is_branch() && rdata.openOnSelect )
-		      {
-			open( true );
-		      }
-		  }
-	      }
-	    else if( rdata.shiftSelectAll )
-	      {
-		select( true );
-		if( is_branch() && rdata.openOnSelect )
-		  {
-		    open( true );
-		  }
-	      }
-	    break;
-	  }
-
-	// check for the keyboard event
-	if( event == FL_KEYDOWN )
-	  {
-	    // check for the spacebar selecting this entry
-	    if( Fl::event_key() == ' ' && rdata.hilighted == this )
-	      {
-		if( Fl::event_state(FL_CTRL) )
-		  select( !CHECK(SELECTED) );
-		else
-		  {
-		    rdata.root->unselect_all( this );
-		    select( true );
-		  }
-		if( is_branch() && rdata.openOnSelect )
-		  {
-		    open( true );
-		  }
-		return 1;		
-	      }
-
-	    // check for the enter key opening/closing this entry
-	    else if( (Fl::event_key() == FL_Enter) && (rdata.hilighted == this) )
-	      {
-		open( !open() );
-		return 1;
-	      }
-
-	    // check for the left/right cursor keys opening/closing this entry
-	    else if( (Fl::event_key() == FL_Left) && (rdata.hilighted == this) )
-	      {
-		open( false );
-		return 1;
-	      }
-	    else if( (Fl::event_key() == FL_Right) && (rdata.hilighted == this) )
-	      {
-		open( true );
-		return 1;
-	      }
-	  }
-
-	// check for the "up" cursor key moving the hilighted entry
-	if( rdata.delta == -1 && rdata.hilighted == this && rdata.previous != NULL )
-	  {
-	    tree->set_hilighted( rdata.previous );
-	    rdata.delta = 0;
-	    return 1;
-	  }
-
-	// check for the "down" cursor key moving the hilighted entry
-	if( rdata.delta == 1 && rdata.hilighted == rdata.previous )
-	  {
-	    tree->set_hilighted( this );
-	    rdata.delta = 0;
-	    return 1;
-	  }
-
-	rdata.previous = this;
-
-	// the event is not ours to use
-	//if( _widget && !rdata.dragging )
-	//if( Fl::event_inside( _widget->w ) )
-	//  return 2;
-
-	bool inExpander = false;
-	if( is_branch() )
-	  {
-	    int which = open();
-	    if( _parent==0 )
-	      inExpander = Fl::event_inside( rdata.x, rdata.y+(currentH>>1)-(cIcon[which]->h()>>1),
-					     cIcon[which]->w(), cIcon[which]->h() );
-	    else
-	      inExpander = Fl::event_inside( rdata.x+(rdata.branchIconW>>1)-(cIcon[which]->w()>>1),
-					     rdata.y+(currentH>>1)-(cIcon[which]->h()>>1),
-					     cIcon[which]->w(), cIcon[which]->h() );
-	  }
-
-	if( event == FL_PUSH )
-	  {	
-	    // check for expand/collapse
-	    if( Fl::event_button() == FL_LEFT_MOUSE && inExpander )
-	      {
-		if( rdata.openWOChildren || CHECK(SOME_VISIBLE_CHILDREN) )
-		  {
-		    open( !open() );
-		    rdata.dragging = false;
-		    rdata.dragNode = 0;
-		    return 1;
-		  }
-	      }
-	  }
-
-	if( event == FL_DRAG && rdata.justOpenedClosed )
-	  return 0;
-
-	// if no selections, return
-	if( rdata.selectionMode == FLU_NO_SELECT )
-	  break;
-
-	// if the event is not inside us, return
-	if( !Fl::event_inside( rdata.browserX, rdata.y, rdata.browserW, currentH ) )
-	  break;
-
-	// single selection
-	if( rdata.selectionMode == FLU_SINGLE_SELECT )
-	  {
-	    if( event == FL_MOVE && rdata.selectUnderMouse )
-	      {
-		//select_only();
-		rdata.root->unselect_all( this );
-		SET(SELECTED,true);
-		tree->redraw();
-	      }
-	    else if( event == FL_PUSH )
-	      {
-		//rdata.dragging = true;
-		rdata.grabbed = this;
-
-		if( rdata.selectUnderMouse )
-		  rdata.root->unselect_all();
-		else
-		  rdata.root->unselect_all( this );
-		tree->set_hilighted( this );
-		if( Fl::event_state(FL_CTRL) )
-		  select( !CHECK(SELECTED) );
-		else
-		  select( true );
-
-		if( is_leaf() )
-		  {
-		    if( Fl::event_clicks() > 0 )
-		      {
-			Fl::event_clicks(0);
-			do_callback( FLU_DOUBLE_CLICK );
-		      }
-		  }
-		else
-		  {
-		    if( Fl::event_clicks() > 0 )
-		      {
-			Fl::event_clicks(0);
-			if( rdata.doubleClickToOpen )
-			  {
-			    if( rdata.openWOChildren || CHECK(SOME_VISIBLE_CHILDREN) )
-			      open( !open() );
-			  }
-			else
-			  do_callback( FLU_DOUBLE_CLICK );
-		      }
-		    else if( rdata.openOnSelect )
-		      {
-			open( true );
-		      }
-		  }
-		Fl::focus(tree);
-		return 1;
-	      }
-	    else if( event == FL_DRAG )
-	      {
-		if( rdata.selectionDragMode == FLU_DRAG_IGNORE )
-		  return 1;
-		rdata.dragging = true;
-		//if( ( rdata.selectionDragMode == FLU_DRAG_IGNORE || rdata.selectionDragMode == FLU_DRAG_TO_MOVE) && ( tree->insertion_mode() == FLU_INSERT_FRONT || tree->insertion_mode() == FLU_INSERT_BACK ) )
-		//return 1;
-		rdata.root->unselect_all( this );
-		tree->set_hilighted( this );
-		select( true );
-		return 1;
-	      }
-	    else if( event == FL_RELEASE && tree->when() == FL_WHEN_RELEASE && selected() && !inExpander )
-	      {
-		do_callback( FLU_SELECTED );
-		return 1;
-	      }
-	  }
-
-	// multiple selection
-	else if( rdata.selectionMode == FLU_MULTI_SELECT )
-	  {
-	    if( event == FL_PUSH )
-	      {
-		//rdata.dragging = true;
-		rdata.grabbed = this;
-
-		if( Fl::event_state(FL_CTRL) )
-		  {
-		    select( !CHECK(SELECTED) );
-		    tree->set_hilighted( this );
-		  }
-		else if( Fl::event_state(FL_SHIFT) )
-		  {
-		    // select everything from the last selected entry to this one
-		    if( rdata.hilighted == this )
-		      {
-			select( true );
-			if( is_branch() )
-			  {
-			    if( Fl::event_clicks() > 0 )
-			      {
-				Fl::event_clicks(0);
-				if( rdata.doubleClickToOpen )
-				  {
-				    if( rdata.openWOChildren || CHECK(SOME_VISIBLE_CHILDREN) )
-				      open( !open() );
-				  }
-				else
-				  do_callback( FLU_DOUBLE_CLICK );
-			      }
-			    else if( rdata.openOnSelect )
-			      {
-				open( !open() );
-			      }
-			  }
-		      }
-		    else
-		      {
-			rdata.shiftSelectAll = false;
-			rdata.shiftSelect = true;
-			rdata.grabbed = this;
-			rdata.root->recurse( rdata, HANDLE, 0 );
-			tree->set_hilighted( this );
-		      }
-		  }
-		else
-		  {
-		    rdata.root->unselect_all( this );
-		    select( true );
-		    if( is_leaf() )
-		      {
-			if( Fl::event_clicks() > 0 )
-			  {
-			    Fl::event_clicks(0);
-			    do_callback( FLU_DOUBLE_CLICK );
-			  }
-		      }
-		    else
-		      {
-			if( Fl::event_clicks() > 0 )
-			  {
-			    Fl::event_clicks(0);
-			    if( rdata.doubleClickToOpen )
-			      {
-				if( rdata.openWOChildren || CHECK(SOME_VISIBLE_CHILDREN) )
-				  open( !open() );
-			      }
-			    else
-			      do_callback( FLU_DOUBLE_CLICK );
-			  }
-			else if( rdata.openOnSelect )
-			  {
-			    open( true );
-			  }
-		      }
-		    tree->set_hilighted( this );
-		  }
-		Fl::focus(tree);
-		return 1;
-	      }
-	    else if( event == FL_DRAG )
-	      {
-		if( rdata.selectionDragMode == FLU_DRAG_IGNORE )
-		  return 1;
-		rdata.dragging = true;
-		//if( ( rdata.selectionDragMode == FLU_DRAG_IGNORE || rdata.selectionDragMode == FLU_DRAG_TO_MOVE) && ( tree->insertion_mode() == FLU_INSERT_FRONT || tree->insertion_mode() == FLU_INSERT_BACK ) )
-		//return 1;
-		select( true );
-		tree->set_hilighted( this );
-		return 1;
-	      }
-	    else if( event == FL_RELEASE && tree->when() == FL_WHEN_RELEASE && selected() && !inExpander )
-	      {
-		do_callback( FLU_SELECTED );
-		return 1;
-	      }
-	  }
-      }
-      break;
-    }
-
-  // advance the counters vertically to the next entry
-  if( !skipEntry )
-    rdata.y += currentH + rdata.vGap;
-
-  if( !is_root() && rdata.first && !skipEntry )
-    rdata.first = false;
-
-  // if we're a leaf, no need to process further
-  if( is_leaf() )
-    return 0;
-
-  // should we bail out already if we're done processing?
-  if( closed() && !skipEntry && !skipCollapser && ( type != MEASURE_THIS_OPEN ) )
-    return 0;
-
-  if( !CHECK(SOME_VISIBLE_CHILDREN) )
-    return 0;
-
-  // advance the counters horizontally to the next entry
-  if( rdata.showBranches )
-    {
-      if( !skipEntry && !skipCollapser )
-	rdata.x += cIcon[which]->w() + rdata.hGap;
-    }
-  rdata.totalW = MAX( rdata.totalW, rdata.x );
-
-  // the branchIconW is the width of the branch icon at this level
-  // it is used to center all children icons under the branch icon
-  int lastBranchIconW = rdata.branchIconW;
-  if( rdata.showBranches )
-    {
-      if( bIcon[which] )
-	rdata.branchIconW = bIcon[which]->w();
-      else
-	rdata.branchIconW = cIcon[which]->w();
-    }
-  else
-    rdata.branchIconW = 0;
-
-  // process all children
-  int val;
-  int tempW = rdata.branchIconW >> 1;
-  for( i = 0; i < _children.size(); i++ )
-    {
-      // prepare the recursive data structure for the next level
-      if( i == 0 )
-	rdata.first = true;
-      rdata.last = (i == _children.size()-1 );
-
-      // if child "i" is not the last child,
-      // then there is a long connector that needs drawn between this node and the last child.
-      // push the horizontal position of the connector onto the stack
-      if( (type == DRAW) && rdata.showConnectors && ( i < _children.size()-1 ) )
-	{
-	  rdata.branchConnectors.push_back( rdata.x+tempW );
-	  val = _children.child(i)->recurse( rdata, type, event );
-	  rdata.branchConnectors.pop_back();
-	}
-      else
-	val = _children.child(i)->recurse( rdata, type, event );
-
-      if( val )
-	return val;
-    }
-
-  // set the branch icon width back to what it was before we changed it
-  rdata.branchIconW = lastBranchIconW;
-
-  // move back horizontally from the last entry
-  if( rdata.showBranches )
-    {
-      if( !skipEntry && !skipCollapser )
-	rdata.x -= cIcon[which]->w() + rdata.hGap;
-    }
-
-  return 0;
-}
-
-void Flu_Tree_Browser :: print()
-{
-  root.print();
-}
-
-void Flu_Tree_Browser :: clear()
-{
-  root.clear();
-  root.text = "";
-
-  while( _box->children() )
-    _box->remove( *_box->child(0) );
-
-  rdata.cbNode = NULL;
-  rdata.cbReason = FLU_NOTHING;
-  rdata.hilighted = NULL;
-  rdata.dragging = false;
-  rdata.forceResize = true;
-  rdata.lastOpenBranch = NULL;
-  rdata.shiftSelect = false;
-  rdata.shiftSelectAll = false;
-  rdata.nextId = 1;
-  rdata.searchIndex = 1;
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: set_root( const char *label, Fl_Widget *w, bool showLabel )
-{
-  if( label == 0 )
-    label = "";
-  root.text = label;
-  root.widget( w );
-  root.SET(Node::SHOW_LABEL,showLabel);
-  root.cIcon[0] = rdata.collapseIcons[0];
-  root.cIcon[1] = rdata.collapseIcons[1];
-  root.bIcon[0] = rdata.branchIcons[0];
-  root.bIcon[1] = rdata.branchIcons[1];
-  root.textColor = rdata.defBranchColor;
-  root.textFont = rdata.defBranchFont;
-  root.textSize = rdata.defBranchSize;
-  rdata.forceResize = true;
-
-  return &root;
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: add( const char* fullpath, Fl_Widget *w, bool showLabel )
-{
-  return( root.modify( fullpath, Node::ADD, rdata, w, showLabel ) );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: add( const char* path, const char* text, Fl_Widget *w, bool showLabel )
-{
-  // if the path does not end in '/', add it
-  std::string s = path;
-  if( path[strlen(path)-1] != '/' )
-    s += "/";
-  s += text;
-
-  return add( s.c_str(), w, showLabel );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: add_branch( const char* fullpath, Fl_Widget *w, bool showLabel )
-{
-  std::string p( fullpath );
-  if( p.size() && p[p.size()-1] != '/' && p[p.size()-1] != '\\' ) p += "/";
-  return add( p.c_str(), w, showLabel );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: add_branch( const char* path, const char* name, Fl_Widget *w, bool showLabel )
-{
-  std::string p( name );
-  if( p.size() && p[p.size()-1] != '/' && p[p.size()-1] != '\\' ) p += "/";
-  return add( path, p.c_str(), w, showLabel );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: add_leaf( const char* fullpath, Fl_Widget *w, bool showLabel )
-{
-  std::string p( fullpath );
-  if( p.size() && ( p[p.size()-1] == '/' || p[p.size()-1] == '\\' ) ) p[p.size()-1] = '\0';
-  return add( p.c_str(), w, showLabel );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: add_leaf( const char* path, const char* name, Fl_Widget *w, bool showLabel )
-{
-  std::string p( name );
-  if( p.size() && ( p[p.size()-1] == '/' || p[p.size()-1] == '\\' ) ) p[p.size()-1] = '\0';
-  return add( path, p.c_str(), w, showLabel );
-}
-
-size_t Flu_Tree_Browser :: remove( const char *fullpath )
-{
-  return( (size_t)root.modify( fullpath, Node::REMOVE, rdata ) );
-}
-
-size_t Flu_Tree_Browser :: remove( const char *path, const char *text )
-{
-  // if the path does not end in '/', add it
-  std::string s = path;
-  if( path[strlen(path)-1] != '/' )
-    s += "/";
-  s += text;
-  return remove( s.c_str() );
-}
-
-size_t Flu_Tree_Browser :: remove( size_t id )
-{
-  return root.remove( id );
-}
-
-size_t Flu_Tree_Browser :: Node :: remove( size_t id )
-{
-  if( id == 0 )
-    return 0;
-
-  for( int i = 0; i < _children.size(); i++ )
-    {
-      Node *n = _children.child(i);
-      if( n->id() == id )
-	{
-	  _children.erase( i );
-	  tree->rdata.forceResize = true;
-	  //if( tree->rdata.cbNode == n )
-	  //tree->rdata.cbNode = NULL;
-	  delete n;
-	  if( tree->rdata.autoBranches )
-	    initType();
-	  tree->redraw();
-	  return id;
-	}
-      else if( n->remove( id ) )
-	return id;
-    }
-
-  return 0;
-}
-
-size_t Flu_Tree_Browser :: remove( Fl_Widget *w )
-{
-  return root.remove( w );
-}
-
-size_t Flu_Tree_Browser :: Node :: remove( Fl_Widget *w )
-{
-  if( !w )
-    return 0;
-  for( int i = 0; i < _children.size(); i++ )
-    {
-      Node *n = _children.child(i);
-      if( n->_widget )
-	{
-	  if( n->_widget->w == w )
-	    {
-	      int id = n->id();
-	      _children.erase( i );
-	      tree->rdata.forceResize = true;
-	      //if( tree->rdata.cbNode == n )
-	      //tree->rdata.cbNode = NULL;
-	      delete n;
-	      if( tree->rdata.autoBranches )
-		initType();
-	      tree->redraw();
-	      return id;
-	    }
-	}
-
-      int id = n->remove( w );
-      if( id )
-	return id;
-    }
-
-  return 0;
-}
-
-int Flu_Tree_Browser :: find_number( const char *fullpath )
-{
-  rdata.counter = 0;
-  root.modify( fullpath, Node::FIND_NUMBER, rdata );
-  return rdata.counter;
-}
-
-int Flu_Tree_Browser :: find_number( const char *path, const char *text )
-{
-  // if the path does not end in '/', add it
-  std::string s = path;
-  if( path[strlen(path)-1] != '/' )
-    s += "/";
-  s += text;
-  return find_number( s.c_str() );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: find_next( const char *fullpath, Node* startNode )
-{
-  // degenerate case: root node
-  if( strcmp( fullpath, "/" ) == 0 )
-    return &root;
-  rdata.previous = startNode;
-  return( root.modify( fullpath, Node::FIND, rdata ) );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: find_next( const char *path, const char *text )
-{
-  // if the path does not end in '/', add it
-  std::string s = path;
-  if( path[strlen(path)-1] != '/' )
-    s += "/";
-  s += text;
-  return find_next( s.c_str() );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: find( const char *path, const char *text )
-{
-  // if the path does not end in '/', add it
-  std::string s = path;
-  if( path[strlen(path)-1] != '/' )
-    s += "/";
-  s += text;
-  return find( s.c_str() );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: find( size_t id )
-{
-  return root.find( id );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: find( size_t id )
-{
-  if( id == 0 )
-    return NULL;
-
-  if( _id == id )
-    return this;
-
-  for( int i = 0; i < _children.size(); i++ )
-    {
-      Node *n = _children.child(i)->find( id );
-      if( n )
-	return n;
-    }
-
-  return NULL;
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: find( Fl_Widget *w )
-{
-  return root.find( w );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: find( Fl_Widget *w )
-{
-  if( _widget )
-    if( _widget->w == w )
-      return this;
-
-  for( int i = 0; i < _children.size(); i++ )
-    {
-      Node *n = _children.child(i)->find( w );
-      if( n )
-	return n;
-    }
-
-  return NULL;
-}
-
-
-bool Flu_Tree_Browser :: Node :: findPath( size_t id, RData &rdata )
-{
-  if( _id == id )
-    {
-      if( is_leaf() )
-	rdata.path += text;
-      else
-	{
-	  rdata.path += text;
-	  rdata.path += "/";
-	}
-      return true;
-    }
-
-  if( is_leaf() )
-    return false;
-
-  std::string oldPath = rdata.path;
-  if( _parent != 0 )
-    {
-      rdata.path += text;
-      rdata.path += "/";
-    }
-
-  for( int i = 0; i < _children.size(); i++ )
-    {
-      if( _children.child(i)->findPath( id, rdata ) )
-	{
-	  return true;
-	}
-    }
-
-  rdata.path = oldPath;
-  return false;
-}
-
-bool Flu_Tree_Browser :: Node :: findPath( Fl_Widget *w, RData &rdata )
-{
-  if( _widget )
-    if( _widget->w == w )
-      {
-	if( is_leaf() )
-	  rdata.path += text;
-	else
-	  {
-	    rdata.path += text;
-	    rdata.path += "/";
-	  }
-	return true;
-      }
-
-  if( is_leaf() )
-    return false;
-
-  std::string oldPath = rdata.path;
-  if( _parent != 0 )
-    {
-      rdata.path += text;
-      rdata.path += "/";
-    }
-
-  for( int i = 0; i < _children.size(); i++ )
-    {
-      if( _children.child(i)->findPath( w, rdata ) )
-	{
-	  return true;
-	}
-    }
-
-  rdata.path = oldPath;
-
-  return false;
-}
-
-const char* Flu_Tree_Browser :: find_path( size_t id )
-{
-  // degenerate case: the root is always id==0
-  if( id == 0 )
-    return "/";
-  rdata.path = "/";
-  if( root.findPath( id, rdata ) )
-    return rdata.path.c_str();
-  else
-    return "";
-}
-
-const char* Flu_Tree_Browser :: find_path( Fl_Widget *w )
-{
-  rdata.path = "/";
-  if( root.findPath( w, rdata ) )
-    return rdata.path.c_str();
-  else
-    return "";
-}
-
-static std::string remove_escape_chars( const char *str )
-{
-  // remove any escape characters
-  std::string text(str);
-  int tIndex = 0;
-  for( int pIndex = 0; pIndex < (int)strlen( str ); pIndex++ )
-    {
-      if( str[pIndex] != '\\' )
-	text[tIndex++] = str[pIndex];
-    }
-  text.resize(tIndex);
-  return text;
-}
-
-void Flu_Tree_Browser :: Node :: do_callback( int reason )
-{
-  //if( tree->rdata.when == FL_WHEN_NEVER )
-  if( tree->when() == FL_WHEN_NEVER )
-    return;
-  //if( tree->rdata.cb )
-    {
-      tree->rdata.cbReason = reason;
-      tree->rdata.cbNode = this;
-      //tree->rdata.cb( tree, tree->rdata.cbd );
-      ((Fl_Widget*)tree)->do_callback();
-    }
-}
-
-unsigned short Flu_Tree_Browser :: Node :: depth() const
-{
-  int d = 0;
-  Node *p = _parent;
-  while( p )
-    {
-      d++;
-      p = p->_parent;
-    }
-  return d;
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: add_branch( const char* fullpath, Fl_Widget *w, bool showLabel )
-{
-  std::string p( fullpath );
-  if( p.size() && p[p.size()-1] != '/' && p[p.size()-1] != '\\' ) p += "/";
-  return add( p.c_str(), w, showLabel );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: add_leaf( const char* fullpath, Fl_Widget *w, bool showLabel )
-{
-  std::string p( fullpath );
-  if( p.size() && ( p[p.size()-1] == '/' || p[p.size()-1] == '\\' ) ) p[p.size()-1] = '\0';
-  return add( p.c_str(), w, showLabel );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: add( const char* path, const char* name, Fl_Widget *w, bool showLabel )
-{
-  std::string p( path );
-  if( p.size() && p[p.size()-1] != '/' && p[p.size()-1] != '\\' ) p += "/";
-  p += name;
-  return add( p.c_str(), w, showLabel );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: add_branch( const char* path, const char* name, Fl_Widget *w, bool showLabel )
-{
-  std::string p( path );
-  if( p.size() && p[p.size()-1] != '/' && p[p.size()-1] != '\\' ) p += "/";
-  p += name;
-  return add_branch( p.c_str(), w, showLabel );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: add_leaf( const char* path, const char* name, Fl_Widget *w, bool showLabel )
-{
-  std::string p( path );
-  if( p.size() && p[p.size()-1] != '/' && p[p.size()-1] != '\\' ) p += "/";
-  p += name;
-  return add_leaf( p.c_str(), w, showLabel );
-}
-
-Flu_Tree_Browser::Node* Flu_Tree_Browser :: Node :: modify( const char* path, int what, RData &rdata, Fl_Widget *w, bool showLabel )
-{
-  // find the selected entry at rdata.searchIndex among all selected entries
-  if( what == GET_SELECTED )
-    {
-      if( CHECK(SELECTED) )
-	{
-	  rdata.counter++;
-	  if( rdata.counter == rdata.searchIndex )
-	    return this;
-	}
-      for( int i = 0; i < _children.size(); i++ )
-	{
-	  Node *n = _children.child(i)->modify( path, what, rdata, w );
-	  if( n )
-	    return n;
-	}
-      return NULL;
-    }
-
-  // trivial test for a bogus empty path
-  if( path == 0 )
-    return NULL;
-
-  // if the path starts with '/', skip the '/'
-  if( path[0] == '/' )
-    path++;
-
-  // trivial test for a bogus empty path
-  if( path[0] == '\0' )
-    return NULL;
-
-  const char *remainingPath;
-  std::string nodeName;
-  bool lastNode, branchNode;
-  Node *retNode = NULL;
-
-  ///////////// extract the next node name from the path ///////////////////
-
-  // find the next '/' that is not preceded by the escape character '\'
-  const char *slash = strchr( path, '/' );
-  for(;;)
-    {
-      // find the next '/'
-      if( slash == NULL ) // there isn't one, so we're done
-	break;
-      // test for escape character
-      else if( slash[-1] == '\\' ) // path[0] can never be '/', so this is a safe test
-	slash = strchr( slash+1, '/' );
-      // we have it
-      else
-	break;
-    }
-
-  // if there is no slash, then the node name is the path and it is a leaf and the last node in the path
-  if( slash == NULL )
-    {
-      branchNode = false;
-      nodeName = remove_escape_chars(path); // remove the escape characters
-      lastNode = true;
-      remainingPath = NULL;
-    }
-  // otherwise the node name is the path up to the slash, it is also a branch and may not be the last node in the path
-  else
-    {
-      branchNode = true;
-      nodeName = path;
-      nodeName.resize(slash-path);
-      nodeName = remove_escape_chars(nodeName.c_str()); // remove the escape characters
-
-      lastNode = ( slash[1] == '\0' ); // this is the last node if there is nothing after the slash
-      if( lastNode )
-	{
-	  //if( rdata.autoBranches )
-	  //branchNode = false;
-	  remainingPath = NULL;
-	}
-      else
-	remainingPath = slash+1;
-    }
-
-  ///////////// process the node ///////////////////
-
-  switch( what )
-    {
-    case ADD:
-      {
-	// if the new node is a leaf node, add the string as a leaf and return
-	if( !branchNode )
-	  {
-	    // is there already a node with this name?
-            /* CG REMOVED THIS
-	    Node *n = _children.find( nodeName );
-	    if( n )
-	      {
-		// if that node is a branch node, we can't add a new one with the same name
-		if( n->is_branch() )
-		  break;
-
-		// if we are not allowed to add multiple nodes with the same name,
-		// then just return
-		if( !rdata.allowDuplication )
-		  break;
-	      }
-            */
-
-	    // add a new node
-	    retNode = new Node( true, nodeName.c_str(), this, rdata, w, showLabel );
-	    _children.add( retNode );
-	    rdata.forceResize = true;
-	    rdata.visibilityChanged = true;
-
-	    if( tree->rdata.autoBranches )
-	      initType();
-	  }
-	// otherwise make sure the node name exists as a branch and recurse on it
-	else
-	  {
-	    // if there is already a node with this name, just use it
-	    Node *n = NULL;
-            /* CG REMOVED THIS
-	    n = _children.find( nodeName );
-	    if( n )
-	      {
-		// make sure it is a branch
-		if( n->is_leaf() )
-		  break;
-	      }
-            */
-
-	    // else add a new node
-	    if( n == NULL )
-	      {
-		// only add the widget for the last node
-		n = new Node( false, nodeName.c_str(), this, rdata, lastNode?w:NULL, lastNode?showLabel:true );
-		_children.add( n );
-		rdata.forceResize = true;
-		rdata.visibilityChanged = true;
-	      }
-
-	    if( tree->rdata.autoBranches )
-	      initType();
-
-	    // recurse on the remainder of the path, if not the last node
-	    if( lastNode )
-	      retNode = n;
-	    else
-	      retNode = n->modify( remainingPath, what, rdata, w, showLabel );
-	  }
-      }
-      break;
-
-    case REMOVE:
-      {
-	// try to find the indicated node. if we can't find it, just return
-	Node *n = _children.find( nodeName.c_str() );
-	if( !n )
-	  break;
-
-	// if this is the last node, remove it.
-	if( lastNode )
-	  {
-	    int ID = n->id();
-	    _children.erase( n );
-	    //if( tree->rdata.cbNode == n )
-	    //tree->rdata.cbNode = NULL;
-	    delete n;
-	    retNode = (Node*)ID; // non-null return value means remove was successful
-	    rdata.forceResize = true;
-	    rdata.visibilityChanged = true;
-
-	    if( tree->rdata.autoBranches )
-	      initType();
-	    tree->redraw();
-	  }
-	// otherwise recurse on the remainder of the path
-	else
-	  retNode = n->modify( remainingPath, what, rdata, w, showLabel );
-      }
-      break;
-
-    case FIND:
-      {
-	// if this node equals the starting node for a find_next,
-	// then by clearing rdata.previous we flag that we are allowed to return the next match
-	if( rdata.previous == this )
-	  rdata.previous = NULL;
-
-	Node *n = NULL;
-
-	if( !lastNode )
-	  {
-	    // if, according to the path, this is not the last node, then just recursively
-	    // search for the named node
-	    n = _children.find( nodeName.c_str() );
-	    if( !n )
-	      break;
-	    retNode = n->modify( remainingPath, what, rdata, w, showLabel );
-	  }
-	else
-	  {
-	    // otherwise, according to the path, this is the last node (i.e. a leaf).
-	    // since only leaves can have multiple identical entries,
-	    // try to find the indicated node, accounting for the possibility
-	    // that it may not be the one we're after
-	    int next = 1;
-	    for(;;)
-	      {
-		// look for the named node
-		n = _children.find( nodeName.c_str(), next++ );
-
-		// if we can't find it, just return, because it's not here
-		if( !n )
-		  break;
-
-		// we are only allowed to return a match if the previous node is NULL,
-		// indicating we have passed the starting node for a find_next
-		if( rdata.previous == NULL )
-		  {
-		    retNode = n;
-		    break;
-		  }
-
-		// if the found node equals the starting node for a find_next,
-		// then by clearing rdata.previous we flag that we are allowed to return the next match
-		if( rdata.previous == n )
-		  rdata.previous = NULL;
-	      }
-	  }
-      }
-      break;
-
-    case FIND_NUMBER:
-      {
-	if( lastNode )  // can only match multiple leaves if the path says this is the last node
-	  {
-	    rdata.counter += _children.findNum( nodeName.c_str() );
-	  }
-	else  // otherwise recurse down the remaining path
-	  {
-	    Node *n = _children.find( nodeName.c_str() );
-	    n->modify( remainingPath, what, rdata, w, showLabel );
-	  }
-      }
-      break;
-    }
-
-  return retNode;
-}
-
-void Flu_Tree_Browser :: Node :: widgetCB()
-{
-  if( _widget )
-    {
-      if( _widget->CB )
-	_widget->CB( _widget->w, _widget->CBData );
-    }
-  do_callback( FLU_WIDGET_CALLBACK );
-}
-
-void Flu_Tree_Browser :: Node :: widget( Fl_Widget *w )
-{
-  tree->rdata.forceResize = true;
-
-  if( _widget )
-    {
-      Fl_Group *p = _widget->w->parent();
-      if( p )
-	p->remove( *(_widget->w) );
-      delete _widget->w;
-      delete _widget;
-      _widget = NULL;
-    }
-
-  if( !w )
-    return;
-
-  _widget = new WidgetInfo;
-  _widget->w = w;
-  _widget->defaultW = _widget->w->w();
-  if( USE_FLU_WIDGET_CALLBACK )
-    {
-      _widget->CB = _widget->w->callback();
-      _widget->CBData = _widget->w->user_data();
-      _widget->w->callback( _widgetCB, this );
-    }
-
-  {
-    Fl_Group *p = w->parent();
-    if( p )
-      p->remove( *w );
-  }
-
-  if( is_root() )
-    tree->_box->add( w );
-  else
-    {
-      Node *p = parent();
-      if( !p->_group )
-	{
-	  p->_group = new Fl_Group( tree->_box->x(), tree->_box->y(), tree->_box->w(), tree->_box->h() );
-	  p->_group->end();
-	  tree->_box->add( p->_group );
-	}
-      p->_group->add( w );
-    }
-}
-
-void Flu_Tree_Browser :: Node :: branch_icons( Fl_Image *closed, Fl_Image *open )
-{
-  if( is_branch() )
-    {
-      bIcon[0] = closed;
-      bIcon[1] = open;
-      tree->rdata.forceResize = true;
-    }
-}
-
-void Flu_Tree_Browser :: Node :: collapse_icons( Fl_Image *closed, Fl_Image *open )
-{
-  if( is_branch() )
-    {
-      if( !closed || !open )
-	{
-	  cIcon[0] = tree->rdata.defaultCollapseIcons[0];
-	  cIcon[1] = tree->rdata.defaultCollapseIcons[1];
-	}
-      else
-	{
-	  cIcon[0] = closed;
-	  cIcon[1] = open;
-	}
-      tree->rdata.forceResize = true;
-    }
-}
-
-void Flu_Tree_Browser :: Node :: leaf_icon( Fl_Image *icon )
-{
-  if( is_leaf() )
-    {
-      lIcon = icon;
-      tree->rdata.forceResize = true;
-    }
-}
-
-bool Flu_Tree_Browser :: Node :: is_branch() const
-{
-  if( tree->rdata.autoBranches )
-    return( _children.size() != 0 );
-  else
-    return !CHECK(LEAF);
-}
-
-bool Flu_Tree_Browser :: Node :: is_leaf() const
-{
-  if( tree->rdata.autoBranches )
-    return( _children.size() == 0 && !is_root() );
-  else
-    return CHECK(LEAF);
-}
-
-
-#if 0 // CG test code: set to 1 and run "fltk-config --compile Flu_Tree_Browser.cpp"
-
-#include <FL/Fl.H>
-#include <FL/Fl_Window.H>
-#include <FL/Fl_Box.H>
-#include <FL/Fl_Input.H>
-#include <FL/Fl_Choice.H>
-#include <FL/Fl_Check_Button.H>
-#include "Flu_Tree_Browser.h"
-
-void add_points(Flu_Tree_Browser::Node *n)
-{
-  char str[128];
-  for(int i = 0; i < 2; i++){
-    sprintf(str, "Point %d", i);
-    n->add(str);
-  }
-}
-
-void add_lines(Flu_Tree_Browser::Node *n)
-{
-  char str[128];
-  for(int i = 0; i < 10; i++){
-    sprintf(str, "Line %d/", i);
-    Flu_Tree_Browser::Node *n2 = n->add(str);
-    add_points(n2);
-  }
-}
-
-void add_surfaces(Flu_Tree_Browser::Node *n)
-{
-  char str[128];
-  for(int i = 0; i < 100; i++){
-    sprintf(str, "Surface %d/", i);
-    Flu_Tree_Browser::Node *n2 = n->add(str);
-    //add_lines(n2);
-  }
-}
-
-void add_volumes(Flu_Tree_Browser::Node *n)
-{
-  char str[128];
-  for(int i = 0; i < 1000; i++){
-    sprintf(str, "Volume %d/", i);
-    Flu_Tree_Browser::Node *n2 = n->add(str);
-    add_surfaces(n2);
-  }
-}
-
-int main(int argc, char **argv)
-{
-  printf("sizeof Node = %d\n", sizeof(Flu_Tree_Browser :: Node));
-
-  Fl_Window *window = new Fl_Window(300, 600);
-  Flu_Tree_Browser *tree = new Flu_Tree_Browser(0, 0, 300, 600);
-  tree->show_root(false);
-  tree->insertion_mode(FLU_INSERT_BACK);
-  tree->branch_icons(0, 0);
-  //tree->open(true);
-  char str[128];    
-  for(int i = 0; i < 2; i++){
-    sprintf(str, "Model %d <<DLR_F6>>/", i);
-    Fl_Check_Button *b = new Fl_Check_Button(0, 0, 20, 20);
-    b->tooltip("Set active");
-    Flu_Tree_Browser::Node *n = tree->add(str, b);
-    Flu_Tree_Browser::Node *e = n->add("Elementary entities/");
-    add_volumes(e);
-    //add_surfaces(e);
-    //add_lines(e);
-    //add_points(e);
-    Flu_Tree_Browser::Node *g = n->add("Physical groups/");
-    Flu_Tree_Browser::Node *p = n->add("Mesh partitions/");
-  }
-  Flu_Tree_Browser::Node *p = tree->add("Post-processing views/");
-  for(int i = 0; i < 7; i++){
-    sprintf(str, "View %d", i);
-    p->add(str);
-  }
-  window->end();
-  window->resizable(tree);
-  window->show(argc, argv);
-  return Fl::run();
-}
-
-#endif
diff --git a/contrib/TreeBrowser/Flu_Tree_Browser.h b/contrib/TreeBrowser/Flu_Tree_Browser.h
deleted file mode 100644
index ea91d80747a8f1a61886a6fe896d2c1a59c1e8d2..0000000000000000000000000000000000000000
--- a/contrib/TreeBrowser/Flu_Tree_Browser.h
+++ /dev/null
@@ -1,1163 +0,0 @@
-// This is a modified version of Jason Bryan's Flu_Tree_Browser. See
-// Flu_Tree_Browser.cpp for a list of changes.
-
-/***************************************************************
- *                FLU - FLTK Utility Widgets 
- *  Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University
- *
- * This file and its content is protected by a software license.
- * You should have received a copy of this license with this file.
- * If not, please contact the Ohio Supercomputer Center immediately:
- * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212
- * 
- ***************************************************************/
-
-#ifndef _FLU_TREE_BROWSER_H
-#define _FLU_TREE_BROWSER_H
-
-#include <string>
-#include <vector>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <FL/Fl.H>
-#include <FL/Fl_Box.H>
-#include <FL/Fl_Pixmap.H>
-#include <FL/Fl_Image.H>
-#include <FL/Fl_Scrollbar.H>
-#include <FL/Fl_Group.H>
-#include <FL/Fl_Menu_Button.H>
-
-/*! Selection modes for FLU widgets that select stuff.
-*/
-enum {
-  FLU_NO_SELECT,
-  FLU_SINGLE_SELECT,
-  FLU_MULTI_SELECT
-};
-
-/*! Data insertion modes for FLU widgets that insert stuff.
-*/
-enum {
-  FLU_INSERT_FRONT,
-  FLU_INSERT_BACK,
-  FLU_INSERT_SORTED,
-  FLU_INSERT_SORTED_REVERSE
-};
-
-/*! Selection drag modes for FLU widgets that select stuff (used while
-  the mouse is being dragged).
-*/
-enum {
-  FLU_DRAG_IGNORE,
-  FLU_DRAG_TO_SELECT,
-  FLU_DRAG_TO_MOVE
-};
-
-/*! Callback reasons for FLU widgets that select stuff.
-*/
-enum {
-  FLU_HILIGHTED,
-  FLU_UNHILIGHTED,
-  FLU_SELECTED,
-  FLU_UNSELECTED,
-  FLU_OPENED,
-  FLU_CLOSED,
-  FLU_DOUBLE_CLICK,
-  FLU_WIDGET_CALLBACK,
-  FLU_MOVED_NODE,
-  FLU_NEW_NODE,
-  FLU_NOTHING
-};
-
-//! This class provides a browser for hierarchical data representation (i.e. a "tree")
-class Flu_Tree_Browser : public Fl_Group
-{
-
-  static bool USE_FLU_WIDGET_CALLBACK;
-
- public:
-
-  class Node;
-  friend class Node;
-
-  //! Normal FLTK widget constructor
-  Flu_Tree_Browser( int x, int y, int w, int h, const char *label = 0 );
-
-  //! Default destructor
-  virtual ~Flu_Tree_Browser();
-
-  //! Add the entry specified by \b fullpath to the tree. If \b w is not \c NULL then that widget is the entry and its label is visible depending on the value of \b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor
-  /*! If \b fullpath ends in a slash ("/"), then the entry is added as a branch, else it is added as a leaf
-    \return a pointer to the Node of the added entry or NULL if the add failed */
-  Node* add( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
-
-  //! Convenience function that is the same as add() except \b path and \b name are concatenated (with a '/' added if necessary) to create the full path
-  Node* add( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
-
-  //! Add entry \b name to node \b n. If \b w is not \c NULL then that widget is the entry and its label is visible depending on the value of \b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor
-  /*! If \b name ends in a slash ("/"), then the entry is added as a branch, else it is added as a leaf
-    \return a pointer to the Node of the added entry or NULL if the add failed */
-  inline Node* add( Node* n, const char* name, Fl_Widget *w = 0, bool showLabel = true )
-    { return n->add( name, w, showLabel ); }
-
-  //! Convenience function that is the same as add() except it appends a '/' to \b fullpath if one does not exist
-  Node* add_branch( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
-
-  //! Convenience function that is the same as add() except \b path and \b name are concatenated (with a '/' added if necessary) to create the full path
-  Node* add_branch( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
-
-  //! Convenience function that is the same as add() except it appends a '/' to \b name if one does not exist
-  inline Node* add_branch( Node* n, const char* name, Fl_Widget *w = 0, bool showLabel = true )
-    { return n->add_branch( name, w, showLabel ); }
-
-  //! Convenience function that is the same as add() except it removes any '/' at the end of \b fullpath
-  Node* add_leaf( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
-
-  //! Convenience function that is the same as add() except \b path and \b name are concatenated (with a '/' added if necessary) to create the full path
-  Node* add_leaf( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
-
-  //! Convenience function that is the same as add() except it removes any '/' at the end of \b fullpath
-  inline Node* add_leaf( Node* n, const char* name, Fl_Widget *w = 0, bool showLabel = true )
-    { return n->add_leaf( name, w, showLabel ); }
-
-  //! Set whether all branches are always open. Default value is \c false
-  inline void all_branches_always_open( bool b )
-    { rdata.allBranchesAlwaysOpen = b; }
-
-  //! Get whether all branches are always open. Default value is \c false
-  inline bool all_branches_always_open()
-    { return rdata.allBranchesAlwaysOpen; }
-
-  //! Set whether multiple leaves with the same path are allowed. Default value is \c true
-  inline void allow_leaf_duplication( bool b )
-    { rdata.allowDuplication = b; }
-
-  //! Get whether multiple leaves with the same path are allowed.
-  inline bool allow_leaf_duplication()
-    { return rdata.allowDuplication; }
-
-  //! Set whether the root node is always open. Shortcut for \c get_root()->always_open(b). Default is \c false
-  inline void always_open( bool b )
-    { root.always_open( b ); }
-
-  //! Get whether the root node is always open
-  inline bool always_open()
-    { return root.always_open(); }
-
-  //! Set whether the tree automatically determines whether a node is a branch or a leaf based on whether it has any children. Default is \c false
-  void auto_branches( bool b );
-
-  //! Get whether the tree automatically determines whether a node is a branch or a leaf based on whether it has any children
-  inline bool auto_branches() const
-    { return rdata.autoBranches; }
-
-  //! Get the default branch text color 
-  inline Fl_Color branch_color() const
-    { return rdata.defBranchColor; }
-
-  //! Get the default branch text font 
-  inline Fl_Font branch_font() const
-    { return rdata.defBranchFont; }
-
-  //! Get the default branch text size 
-  inline int branch_size() const
-    { return rdata.defBranchSize; }
-
-  //! Set the default color, font and size to use for the text of all subsequent branches added to the tree
-  inline void branch_text( Fl_Color color, Fl_Font font, int size )
-    { rdata.defBranchColor = color; rdata.defBranchFont = font; rdata.defBranchSize = size; }
-
-  //! Set the default branch icons to use for all subsequent branches added to the tree
-  /*! Passing in \c NULL for either icon will disable that icon for the branch */
-  void branch_icons( Fl_Image *closed, Fl_Image *open );
-
-  //! Get the type of box to draw the browser in
-  inline Fl_Boxtype box() const
-    { return _box->box(); }
-
-  //! Set the type of box to draw the browser in. Default is FL_FLAT_BOX
-  inline void box( Fl_Boxtype b )
-    { _box->box( b ); }
-
-  //! Override of Fl_Widget::callback
-  //inline void callback( Fl_Callback *c, void *user_data = 0 )
-  //{ rdata.cb = c; rdata.cbd = user_data; }
-
-  //! Get the reason why the last callback happened. This can be one of FLU_UNHILIGHTED, FLU_HILIGHTED, FLU_SELECTED, FLU_UNSELECTED, FLU_OPENED, FLU_CLOSED, FLU_DOUBLE_CLICK, FLU_WIDGET_CALLBACK, FLU_MOVED_CALLBACK, FLU_NEW_NODE_CALLBACK
-  inline int callback_reason() const
-    { return rdata.cbReason; }
-
-  //! Get the node on which the last callback happened.
-  /*! \note this node is only guaranteed to be in the tree \b during the callback. If the callback adds/removes nodes, then this node may have changed */
-  inline Node* callback_node() const
-    { return rdata.cbNode; }
-
-  //! Clear all entries from the tree
-  void clear();
-
-  //! Set the default collapse icons to use for all subsequent branches added to the tree
-  void collapse_icons( Fl_Image *closed, Fl_Image *open );
-
-  //! Get the background color of the browser
-  inline Fl_Color color() const
-    { return _box->color(); }
-
-  //! Set the background color of the browser. Default is FL_WHITE
-  inline void color( Fl_Color c )
-    { _box->color( c ); }
-
-  //! Set the background color of the browser. Default is FL_WHITE
-  inline void color( unsigned c )
-    { _box->color( (Fl_Color)c ); }
-
-  //! Set the color, style, and width of the connector lines. Default is FL_DARK2, FL_DOT, 1
-  inline void connector_style( Fl_Color color, int style, int width = 1 )
-    { rdata.defLineColor = color; rdata.lineStyle = style; rdata.lineWidth = width; }
-
-  //! Get the color of the connector lines
-  inline Fl_Color connector_color() const
-    { return rdata.defLineColor; }
-
-  //! Get the style of the connector lines
-  inline int connector_style() const
-    { return rdata.lineStyle; }
-
-  //! Get the width of the connector lines
-  inline int connector_width() const
-    { return rdata.lineWidth; }
-
-  //! Set whether double-clicking a branch opens/closes it
-  inline void double_click_opens( bool b )
-    { rdata.doubleClickToOpen = b; }
-
-  //! Get whether double-clicking a branch opens/closes it
-  inline bool double_click_opens()
-    { return rdata.doubleClickToOpen; }
-
-  //! Get the color to use for shading even entries
-  inline Fl_Color even_shaded_entry_color() const 
-    { return rdata.shadedColors[0]; }
-
-  //! Find the entry identified by \b fullpath
-  /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */
-  inline Node* find( const char *fullpath )
-    { return find_next( fullpath ); }
-
-  //! Find entry \b name in path \b path
-  /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */
-  Node* find( const char *path, const char *name );
-
-  //! Find the entry identified by unique id \b id
-  /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */
-  Node* find( size_t id );
-
-  //! Search for Node \b n in the tree
-  /*! \return a pointer to \b n if it is found, or NULL if it is not in the tree */
-  inline Node* find( Node *n )
-    { if( !n ) return NULL; else return find( n->id() ); }
-
-  //! Find the entry containing the widget \b w
-  /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */
-  Node* find( Fl_Widget *w );
-
-  //! Find the next entry identified by \b fullpath after \b startNode
-  /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */
-  Node* find_next( const char *fullpath, Node* startNode = NULL );
-
-  //! Find the next entry \b name in path \b path after \b startNode
-  /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */
-  Node* find_next( const char *path, const char *name );
-
-  //! \return the number of discovered nodes matching path \b fullpath
-  int find_number( const char *fullpath );
-
-  //! \return the number of discovered nodes with name \b name in path \b path
-  int find_number( const char *path, const char *name );
-
-  //! \return the full path of the entry identified by unique id \b id, or the empty string if no matching entry was found
-  /*! \note the returned value is only valid until the next time find_path() is called */
-  const char* find_path( size_t id );
-
-  //! \return the full path of the entry containing the widget \b w, or the empty string if no matching entry was found
-  /*! \note the returned value is only valid until the next time find_path() is called */
-  const char* find_path( Fl_Widget *w );
-
-  //! \return the full path of Node \b n, or the empty string if \b n is not in the tree
-  /*! \note the returned value is only valid until the next time find_path() is called */
-  inline const char* find_path( Node *n )
-    { if( !n ) return ""; else return find_path( n->id() ); }
-
-  //! \return the first node in the tree (i.e. the root)
-  inline Node* first() { return root.first(); }
-
-  //! \return the first branch encountered in a depth-first traversal of the tree. NULL means there are no branches
-  inline Node* first_branch() { return root.first_branch(); }
-
-  //! \return the first leaf encountered in a depth-first traversal of the tree. NULL means there are no leaves
-  inline Node* first_leaf() { return root.first_leaf(); }
-
-  //! \return the currently highlighted node
-  inline Node* get_hilighted()
-    { return rdata.hilighted; }
-
-  //! \return a pointer to the root node of the tree
-  inline Node *get_root() { return &root; }
-
-  //! \return the selected Node that is at \b index among all selected nodes, or \c NULL if no Node is selected
-  /*! For example, \c get_selected(1) will return the first selected node. */
-  Node* get_selected( int index );
-
-  //! Override of Fl_Widget::handle
-  int handle( int event );
-
-  //! Set the horizontal icon gap for each entry. Default is 2
-  inline void horizontal_gap( int g )
-    { rdata.hGap = g; rdata.forceResize = true; }
-
-  //! Get the horizontal icon gap for each entry
-  inline int horizontal_gap() const
-    { return rdata.hGap; }
-
-  //! Set how entries are inserted into the tree. This can be one of FLU_INSERT_FRONT, FLU_INSERT_BACK, FLU_INSERT_SORTED, FLU_INSERT_SORTED_REVERSE. Default is FLU_INSERT_SORTED
-  void insertion_mode( int m );
-
-  //! Get how entries are inserted into the tree.
-  inline int insertion_mode()
-    { return rdata.insertionMode; }
-
-  //! \return whether the point \c (x,y) is inside the entry area (not on the scrollbars)
-  bool inside_entry_area( int x, int y );
-
-  //! Set the title of the Tree (also the label for the root entry)
-  inline void label( const char *l )
-    { root.text = l; }
-
-  //! Get the title of the Tree (also the label for the root entry)
-  inline const char* label() const
-    { return root.text.c_str(); }
-
-  //! \return the last node in the tree
-  inline Node* last() { return root.last(); }
-
-  //! \return the last branch encountered in a depth-first traversal of the tree. NULL means there are no branches
-  inline Node* last_branch() { return root.last_branch(); }
-
-  //! \return the last leaf encountered in a depth-first traversal of the tree. NULL means there are no leaves
-  inline Node* last_leaf() { return root.last_leaf(); }
-
-  //! Get the default leaf text color 
-  inline Fl_Color leaf_color() const
-    { return rdata.defLeafColor; }
-
-  //! Get the default leaf text font 
-  inline Fl_Font leaf_font() const
-    { return rdata.defLeafFont; }
-
-  //! Get the default leaf text size 
-  inline int leaf_size() const
-    { return rdata.defLeafSize; }
-
-  //! Set the default leaf icon to use for all subsequent leaves added to the tree
-  void leaf_icon( Fl_Image *icon );
-
-  //! Set the default color, font and size to use for the text of all subsequent leaves added to the tree, Default is FL_BLACK, FL_HELVETICA, 12
-  inline void leaf_text( Fl_Color color, Fl_Font font, int size )
-    { rdata.defLeafColor = color; rdata.defLeafFont = font; rdata.defLeafSize = size; }
-
-  //! Set whether items can be moved only within their group ( \c true ) or can be moved anywhere in the tree ( \c false ). Default is \c false. Used only when selection_drag_mode() is FLU_DRAG_TO_MOVE.
-  inline void move_only_same_group( bool b )
-    { rdata.moveOnlySameGroup = b; }
-
-  //! Get whether items can be moved only within their group ( \c true ) or can be moved anywhere in the tree ( \c false ). Used only when selection_drag_mode() is FLU_DRAG_TO_MOVE.
-  inline bool move_only_same_group()
-    { return rdata.moveOnlySameGroup; }
-
-  //! \return the number of selected entries
-  int num_selected();
-
-  //! Get the color to use for shading odd entries
-  inline Fl_Color odd_shaded_entry_color() const 
-    { return rdata.shadedColors[1]; }
-
-  //! Set whether only a single branch (except the root branch) is allowed open at a time. Default is \c false
-  inline void only_one_open_branch( bool b )
-    { rdata.singleBranchOpen = b; }
-
-  //! Get whether only a single branch (except the root branch) is allowed open at a time
-  inline bool only_one_open_branch()
-    { return rdata.singleBranchOpen; }
-
-  //! Open or close the root node
-  inline void open( bool b )
-    { root.open( b ); }
-
-  //! Is the root node open or closed?
-  inline bool open() const
-    { return root.open(); }
-
-  //! Set whether you can open/close a branch even if it has no children. Default is \c false
-  inline void open_without_children( bool b )
-    { rdata.openWOChildren = b; }
-
-  //! Get whether you can open/close a branch even if it has no children.
-  inline bool open_without_children() const
-    { return rdata.openWOChildren; }
-
-  //! Set whether selecting a branch also opens it. Default is \c false
-  inline void open_on_select( bool b )
-    { rdata.openOnSelect = b; }
-
-  //! Get whether selecting a branch also opens it
-  inline bool open_on_select() const
-    { return rdata.openOnSelect; }
-
-  //! Print the tree to stdout
-  void print();
-
-  //! Remove the entry identified by path \b fullpath from the tree
-  /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */
-  size_t remove( const char *fullpath );
-
-  //! Remove entry \b name in path \b path from the tree
-  /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */
-  size_t remove( const char *path, const char *name );
-
-  //! Remove the entry identified by unique id \b id from the tree
-  /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */
-  size_t remove( size_t id );
-
-  //! Remove the entry containing the widget \b w from the tree. Note that the widget is automatically destroyed
-  /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */
-  size_t remove( Fl_Widget *w );
-
-  //! Remove Node \b n from the tree
-  /*! \return the id of \b n on successful removal, or \c 0 if \b n is not in the tree */
-  inline size_t remove( Node* n )
-    { if( !n ) return 0; else return remove( n->id() ); }
-
-  //! Override of Fl_Widget::resize
-  void resize( int X, int Y, int W, int H );
-
-  //! Convenience routine to set the root label color. See Flu_Tree_Browser::Node::label_color()
-  inline void root_color( Fl_Color c )
-    { get_root()->label_color( c ); }
-
-  //! Convenience routine to set the root label color. See Flu_Tree_Browser::Node::label_color()
-  inline Fl_Color root_color()
-    { return get_root()->label_color(); }
-
-  //! Convenience routine to set the root label font. See Flu_Tree_Browser::Node::label_font()
-  inline void root_font( Fl_Font f )
-    { get_root()->label_font( f ); }
-
-  //! Convenience routine to set the root label font. See Flu_Tree_Browser::Node::label_font()
-  inline Fl_Font root_font()
-    { return get_root()->label_font(); }
-
-  //! Convenience routine to set the root label size. See Flu_Tree_Browser::Node::label_size()
-  inline void root_size( unsigned char s )
-    { get_root()->label_size( s ); }
-
-  //! Convenience routine to set the root label size. See Flu_Tree_Browser::Node::label_size()
-  inline unsigned char root_size()
-    { return get_root()->label_size(); }
-
-  //! Select all entries in the tree
-  inline void select_all()
-    { root.select_all(); }
-
-  //! Get the color to use when hilighting selected entries
-  inline Fl_Color selection_color() const
-    { return rdata.defSelectionColor; }
-
-  //! Set the color to use when hilighting selected entries. Default is FL_SELECTION_COLOR
-  inline void selection_color( Fl_Color c )
-    { rdata.defSelectionColor = c; }
-
-  //! Set the color to use when hilighting selected entries. Default is FL_SELECTION_COLOR
-  inline void selection_color( unsigned c )
-    { selection_color( (Fl_Color)c ); }
-
-  //! Set how selection is affected when the mouse is dragged. This can be one of FLU_DRAG_IGNORE, FLU_DRAG_TO_SELECT, FLU_DRAG_TO_MOVE. Default is FLU_DRAG_TO_SELECT.
-  inline void selection_drag_mode( int m )
-    { rdata.selectionDragMode = m; }
-
-  //! Get how selection is affected when the mouse is dragged
-  inline int selection_drag_mode() const
-    { return rdata.selectionDragMode; }
-
-  //! Set whether the hilighted node is always selected. Default is \c false
-  inline void selection_follows_hilight( bool b )
-    { rdata.selectionFollowsHilight = b; if( b && rdata.hilighted ) rdata.hilighted->select(true); }
-
-  //! Get whether the hilighted node is always selected
-  inline bool selection_follows_hilight()
-    { return rdata.selectionFollowsHilight; }
-
-  //! Set how individual entries are selected using the mouse. This can be one of FLU_NO_SELECT, FLU_SINGLE_SELECT, FLU_MULTI_SELECT. Default is FLU_MULTI_SELECT
-  inline void selection_mode( int m )
-    { rdata.selectionMode = m; root.unselect_all(); }
-
-  //! Get how individual entries are selected using the mouse
-  inline int selection_mode() const
-    { return rdata.selectionMode; }
-
-  //! If selection_mode() is \c FLU_SINGLE_SELECT, then whichever node is under the mouse will always be selected, with all others unselected. Default is \c false
-  inline void select_under_mouse( bool b )
-    { rdata.selectUnderMouse = b; }
-
-  //! If selection_mode() is \c FLU_SINGLE_SELECT, then whichever node is under the mouse will always be selected, with all others unselected. Default is \c false
-  inline bool select_under_mouse() const
-    { return rdata.selectUnderMouse; }
-
-  //! Calling this will cause any newly added branches to use the default branch icon
-  void set_default_branch_icons();
-
-  //! Set which node is hilighted and ready to be selected or unselected. This also scrolls the browser so \b n is visible.
-  void set_hilighted( Node* n );
-
-  //! Set the title of the root of the tree to \b label. If \b w is not \c NULL then that widget is the entry and its label is visible depending on the value of \b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor
-  /*! The root icons, color, font and size are set to the current branch icons and text color, font and size */
-  Node* set_root( const char *label, Fl_Widget *w = 0, bool showLabel = true );
-
-  //! Set the colors to use for shading every other entry. Default is FL_WHITE, FL_WHITE
-  inline void shaded_entry_colors( Fl_Color even, Fl_Color odd )
-    { rdata.shadedColors[0] = even; rdata.shadedColors[1] = odd; }
-
-  //! Set whether branch entries are visible. Default is \c true
-  inline void show_branches( bool b )
-    { rdata.showBranches = b; rdata.forceResize = true; }
-
-  //! Get whether branch entries are visible
-  inline bool show_branches() const
-    { return rdata.showBranches; }
-
-  //! Set whether the connectors between entries are visible. Default is \c true
-  inline void show_connectors( bool b )
-    { rdata.showConnectors = b; }
-
-  //! Get whether the connectors between entries are visible
-  inline bool show_connectors() const
-    { return rdata.showConnectors; }
-
-  //! Set whether the root branch (i.e. the name of the tree) is visible. Default is \c true
-  inline void show_root( bool b )
-    { rdata.showRoot = b; rdata.forceResize = true; }
-
-  //! Get whether the root branch (i.e. the name of the tree) is visible
-  inline bool show_root() const
-    { return rdata.showRoot; }
-
-  //! Set whether leaf entries are visible. Default is \c true
-  inline void show_leaves( bool b )
-    { rdata.showLeaves = b; rdata.forceResize = true; }
-
-  //! Get whether leaf entries are visible
-  inline bool show_leaves() const
-    { return rdata.showLeaves; }
-
-  //! Sort the tree according to insertion_mode()
-  inline void sort()
-    { root.sort(); }
-
-  //! Unselect all entries in the tree
-  inline void unselect_all()
-    { root.unselect_all(); }
-
-  inline static void use_FLU_WIDGET_CALLBACK( bool b )
-    { USE_FLU_WIDGET_CALLBACK = b; }
-
-  //! Set the vertical gap between tree entries. Default is 0
-  inline void vertical_gap( int g )
-    { rdata.vGap = g; rdata.forceResize = true; }
-
-  //! Get the vertical gap between tree entries
-  inline int vertical_gap() const
-    { return rdata.vGap; }
-
-  //! Override of Fl_Widget::when. Currently only FL_WHEN_NEVER, FL_WHEN_CHANGED, and FL_WHEN_NOT_CHANGED are supported. Default value is FL_WHEN_CHANGED
-  /*! When the callback occurs, you can use callback_reason() to determine exactly what cause the callback and callback_node()
-    to get the node that was affected. */
-  //inline void when( size_t w )
-  //{ rdata.when = w; }
-
-  //! Override of Fl_Widget::when
-  //inline size_t when() const
-  //{ return rdata.when; }
-
-  //! Set the gap between the widget and the icon that precedes it. Default is 2
-  inline void widget_gap( int g )
-    { rdata.wGap = g; rdata.forceResize = true; }
-
-  //! Get the gap between the widget and the icon that precedes it 
-  inline int widget_gap() const
-    { return rdata.wGap; }
-
- protected:
-
-  class RData;
-
-  //! Internal class holding an (alphabetically) ordered list of nodes
-  class NodeList
-    {
-    public:
-      NodeList();
-      ~NodeList();
-      void add( Node* n, int position = -1 );
-      inline Node* child( int n ) const { return _nodes[n]; }
-      int erase( Node* n );
-      int erase( const char* n );
-      void erase( int n );
-      void clear();
-      int findNum( const char *n );  // find the number of nodes in the list with name n
-      Node* find( const char* n, int which = 1 );  // find the which'th node in the list with name n
-      inline int size() const { return _nNodes; };
-      void sort();
-      static bool move( Node* n1, int where, Node* n2 );
-    private:
-      friend class Node;
-      static int compareNodes( const void *arg1, const void* arg2 );
-      static int reverseCompareNodes( const void *arg1, const void* arg2 );
-      bool search( Node *n, int &index );
-      bool search( const char *n, int &index );
-      bool linSearch( Node *n, int &index );
-      bool linSearch( const char *n, int &index );
-      bool binSearch( Node *n, int &index );
-      bool binSearch( const char *n, int &index );
-      Node **_nodes;
-      int _nNodes, _size;
-    };
-
-  public:
-  enum { MOVE_BEFORE, MOVE_INSIDE, MOVE_AFTER }; // where to move a dragged node?
- protected:
-
-  //! Recursive data structure passed down through the node tree
-  class RData {
-  public:
-    // volatile objects (from the perspective of each node during a recursive descent)
-    int x, y, totalW, totalH;
-    bool first, last, dragging, shiftSelect, shiftSelectAll, visibilityChanged, selectionFollowsHilight;
-    Node *hilighted, /**lastHilighted, */ *previous, *grabbed, *dragNode;
-    int delta, shadedIndex, counter, searchIndex, branchIconW, dragPos, dragWhere;
-    Fl_Color lineColor, bgColor, selectionColor;
-    bool forceResize;  // force the browser to resize on the next draw (which forces a recalculation of the tree layout)
-    size_t nextId;  // monotonically increasing id of each entry
-    std::string path;  // used to construct the full path during a findPath() operation
-    std::vector<int> branchConnectors;
-
-    // static objects (from the perspective of each node during a recursive descent)
-    int insertionMode;
-    Fl_Image *defaultCollapseIcons[2], *defaultBranchIcons[2];
-    Fl_Image *collapseIcons[2], *branchIcons[2], *leafIcon;
-    int hGap, vGap, wGap;
-    int lineStyle, lineWidth, selectionMode, selectionDragMode;
-    bool showRoot, showConnectors, showLeaves, showBranches, openOnSelect,
-      allowDuplication, singleBranchOpen, moveOnlySameGroup, justOpenedClosed,
-      isMoveValid, doubleClickToOpen, allBranchesAlwaysOpen, autoBranches, openWOChildren,
-      selectUnderMouse;
-    Fl_Color defLineColor, defSelectionColor, shadedColors[2];
-    Fl_Color defLeafColor, defBranchColor;
-    Fl_Font defLeafFont, defBranchFont;
-    int defLeafSize, defBranchSize;
-    int browserX, browserY, browserW, browserH;
-    Node *root;
-    Flu_Tree_Browser *tree;
-    size_t cbReason;
-    Node *cbNode, *lastOpenBranch;
-  };
-
- public:
-
-  //! This class holds a single entry in the tree
-  class Node
-    {
-
-    protected:
-
-      enum { ADD, REMOVE, FIND, FIND_NUMBER, GET_SELECTED };  // parameters for modify()
-      enum { DRAW, MEASURE, MEASURE_THIS_OPEN, HANDLE, COUNT_SELECTED };  // parameters for recurse()
-
-      // flags
-      enum { SELECTED = 0x0001, COLLAPSED = 0x0002, LEAF = 0x0004, SHOW_LABEL = 0x0008,
-	     ACTIVE = 0x0010, EXPAND_TO_WIDTH = 0x0020, ALWAYS_OPEN = 0x0040,
-	     SOME_VISIBLE_CHILDREN = 0x0080, MOVABLE = 0x0100, DROPPABLE = 0x0200,
-	     AUTO_LABEL_COLOR = 0x0400, AUTO_COLOR = 0x0800, AUTO_LABEL = 0x1000, 
-	     SWAP_LABEL_AND_WIDGET = 0x2000, ICON_AT_END = 0x4000 };
-
-      // flag manipulator functions
-      inline bool CHECK( unsigned short flag ) const { return flags & flag; }
-      inline void SET( unsigned short flag ) { flags |= flag; }
-      inline void SET( unsigned short flag, bool b ) { if(b) SET(flag); else CLEAR(flag); }
-      inline void CLEAR( unsigned short flag ) { flags &= ~flag; }
-
-    public:
-
-      //! Is this node currently active?
-      inline bool active() const
-	{ return CHECK(ACTIVE); }
-
-      //! Activate or deactivate this node
-      void active( bool b );
-
-      //! Activate this node
-      inline void activate()
-	{ active(true); }
-
-      //! Add the entry specified by \b fullpath to this node. If \b w is not \c NULL then that widget is the entry and the label (as specified in \b fullPath) is visible depending on the value of \b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor
-      /*! \return a pointer to the Node of the added entry or NULL if the add failed */
-      inline Node* add( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true )
-	{ return( modify( fullpath, ADD, tree->rdata, w, showLabel ) ); }
-
-      //! Convenience function that is the same as add() except it appends a '/' to \b fullpath if one does not exist
-      Node* add_branch( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
-
-      //! Convenience function that is the same as add() except it removes any '/' at the end of \b fullpath
-      Node* add_leaf( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
-
-      //! Convenience function that is the same as add() except \b path and \b name are concatenated (with a '/' added if necessary) to create the full path
-      Node* add( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
-
-      //! Convenience function that is the same as add_branch() except \b path and \b name are concatenated (with a '/' added if necessary) to create the full path
-      Node* add_branch( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
-
-      //! Convenience function that is the same as add_leaf() except \b path and \b name are concatenated (with a '/' added if necessary) to create the full path
-      Node* add_leaf( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
-
-      //! Set whether a branch node is always open (only for branch nodes). Default is \c false
-      inline void always_open( bool b )
-	{ if( b ) open(true); SET(ALWAYS_OPEN,b); tree->rdata.forceResize = true; }
-
-      //! Get whether this branch node is always open (only for branches)
-      inline bool always_open() const
-	{ return CHECK(ALWAYS_OPEN); }
-
-      //! Set whether the color of the widget in this node tracks the color of the node itself. This is useful for changing the color of the widget when the node is selected. Default is \c false
-      inline void auto_color( bool b )
-	{ SET(AUTO_COLOR,b); }
-
-      //! Get whether the color of the widget in this node tracks the color of the node itself
-      inline bool auto_color()
-	{ return CHECK(AUTO_COLOR); }
-
-      //! Set whether the label of the widget in this node tracks the label of the node itself. This is useful for when the label of the node changes and you want the widget to reflect the change
-      inline void auto_label( bool b )
-	{ SET(AUTO_LABEL,b); }
-
-      //! Set whether the label of the widget in this node tracks the label of the node itself.
-      inline bool auto_label()
-	{ return CHECK(AUTO_LABEL); }
-
-      //! Set whether the label color of the widget in this node tracks the label color of the node itself. This is useful for changing the label color of the widget when the node is selected. Default is \c false
-      inline void auto_label_color( bool b )
-	{ SET(AUTO_LABEL_COLOR,b); }
-
-      //! Get whether the label color of the widget in this node tracks the label color of the node itself
-      inline bool auto_label_color()
-	{ return CHECK(AUTO_LABEL_COLOR); }
-
-      //! Set the branch icons to use for this node (only for branch nodes)
-      void branch_icons( Fl_Image *closed, Fl_Image *open );
-
-      //! Convenience routine to set both branch icons at once
-      inline void branch_icon( Fl_Image *icon )
-	{ branch_icons( icon, icon ); }
-
-      //! \return child \b i of this node (base 0). Bounds checking is performed and NULL is returned if the child cannot be found
-      Node* child( int i ) const;
-
-      //! \return the number of child nodes beneath this node
-      inline int children() const
-	{ return _children.size(); }
-
-      //! Clear all child entries from this node (does not change the entry of this node)
-      void clear();
-
-      //! Close this node (only for branches)
-      inline void close()
-	{ open( false ); }
-
-      //! Is this node closed? (only for branches)
-      inline bool closed()
-	{ return !open(); }
-
-       //! Set the collapse icons to use for this node (only for branch nodes)
-      /*! \note if a NULL icon is passed, the default plus/minus icons are chosen */
-      void collapse_icons( Fl_Image *closed, Fl_Image *open );
-
-      //! Deactivate this node
-      inline void deactivate()
-	{ active(false); }
-
-      //! Get the depth of this node in the tree
-      unsigned short depth() const;
-
-      //! Do the tree browser callback. \b reason should be one of FLU_HILIGHTED, FLU_UNHILIGHTED, FLU_SELECTED, FLU_UNSELECTED, FLU_OPENED, FLU_CLOSED, FLU_DOUBLE_CLICK, FLU_WIDGET_CALLBACK
-      void do_callback( int reason );
-
-      //! Set whether this node can receive new nodes as a result of dragging-and-dropping (only for branch nodes). Default is \c true
-      inline void droppable( bool b )
-	{ SET(DROPPABLE,b); }
-
-      //! Get whether this node can receive new nodes as a result of dragging-and-dropping (only for branch nodes).
-      inline bool droppable()
-	{ return CHECK(DROPPABLE); }
-
-      //! Set whether to force the size of the embedded widget to expand to fill the visible width of the browser. Default is \c false
-      inline void expand_to_width( bool b )
-	{ SET(EXPAND_TO_WIDTH,b); tree->rdata.forceResize = true; }
-
-      //! Get whether to force the size of the embedded widget to expand to fill the visible width of the browser
-      inline bool expand_to_width() const
-	{ return CHECK(EXPAND_TO_WIDTH); }
-
-      //! Find the entry identified by \b fullpath
-      /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */
-      inline Node* find( const char *fullpath )
-	{ return( modify( fullpath, FIND, tree->rdata ) ); }
-
-      //! Find the entry identified by unique id \b id
-      /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */
-      Node* find( size_t id );
-
-      //! Find the entry containing the widget \b w
-      /*! \return a pointer to the Node of the found entry, or NULL if no matching entry was found */
-      Node* find( Fl_Widget *w );
-
-      //! Search for Node \b n
-      /*! \return a pointer to \b n if it is found, or NULL if it is not present */
-      inline Node* find( Node *n )
-	{ if( !n ) return NULL; else return find( n->id() ); }
-
-      //! \return the full path of this node
-      /*! \note the returned value is only valid until the next time find_path() is called */
-      inline const char* find_path()
-	{ return tree->find_path( this ); }
-
-      //! \return the first node in this hierarchy (i.e. this node)
-      Node* first();
-
-      //! \return the first branch encountered in a depth-first traversal (or this node if it is a branch). NULL means there are no branches
-      Node* first_branch();
-
-      //! \return the first leaf encountered in a depth-first traversal (or this node if it is a leaf). NULL means there are no leaves
-      Node* first_leaf();
-
-      //! Set whether this node draws the label to the left of the widget (\c false, default) or to the right of the widget (\c true)
-      inline void swap_label_and_widget( bool b )
-	{ SET(SWAP_LABEL_AND_WIDGET,b); }
-
-      //! Get whether this node draws the label to the left of the widget (\c false, default) or to the right of the widget (\c true)
-      inline bool swap_label_and_widget()
-	{ return CHECK(SWAP_LABEL_AND_WIDGET); }      
-
-      //! \return the selected Node that is at \b index among all selected nodes, or \c NULL if no Node is selected
-      /*! For example, \c get_selected(1) will return the first selected node. */
-      Node* get_selected( int index );
-
-      //! Set whether the icon for this node is drawn after the label and widget (\c true) or before (\c false, default) (only for leaf nodes)
-      inline void icon_at_end( bool b )
-	{ SET(ICON_AT_END,b); }
-
-      //! Get whether the icon for this node is drawn after the label and widget (\c true) or before (\c false, default) (only for leaf nodes)
-      inline bool icon_at_end()
-	{ return CHECK(ICON_AT_END); }
-
-      //! Get the unique ID of this node
-      inline size_t id() const
-	{ return _id; }
-
-      //! Get the index this node is (as a child) in its parent's list
-      /*! \return -1 if this node has no parent, else its index in its parent's list of children */
-      int index() const;
-
-      //! Insert a new node at position \b pos
-      Node* insert( const char* fullpath, int pos );
-
-      //! Insert a new branch at position \b pos
-      Node* insert_branch( const char* fullpath, int pos );
-
-      //! Insert a new leaf at position \b pos
-      Node* insert_leaf( const char* fullpath, int pos );
-
-      //! Is node \b n an ancestor of this node?
-      bool is_ancestor( Node* n );
-
-      //! Is this node a branch node?
-      bool is_branch() const;
-
-      //! Is node \b n a descendent of this node?
-      bool is_descendent( Node* n );
-
-      //! Is this node a leaf node?
-      bool is_leaf() const;
-
-      //! Is this node the root node?
-      inline bool is_root() const
-	{ return( _parent == 0 ); }
-
-      //! Set the label for this node. Note that setting the label may invalidate a sorted tree. Fix by calling Flu_Tree_Browser::sort() 
-      inline void label( const char *l )
-	{ text = l; tree->redraw(); }
-
-      //! Get the label for this node
-      inline const char* label() const
-	{ return text.c_str(); }
-
-      //! Set the label color for this node
-      inline void label_color( Fl_Color c )
-	{ textColor = c; }
-
-      //! Get the label color for this node
-      inline Fl_Color label_color() const
-	{ return textColor; }
-
-      //! Set the label font for this node
-      inline void label_font( Fl_Font f )
-	{ textFont = f; tree->rdata.forceResize = true; }
-
-      //! Get the label font for this node
-      inline Fl_Font label_font() const
-	{ return textFont; }
-
-      //! Set the label size for this node
-      inline void label_size( unsigned char s )
-	{ textSize = s; tree->rdata.forceResize = true; }
-
-      //! Get the label size for this node
-      inline unsigned char label_size() const
-	{ return textSize; }
-
-      //! Is the label for this node visible?
-      inline bool label_visible() const
-	{ return CHECK(SHOW_LABEL); }
-
-      //! Set whether the label for this node is visible
-      inline void label_visible( bool b )
-	{ SET(SHOW_LABEL,b); tree->rdata.forceResize = true; }
-
-      //! \return the last node in this hierarchy
-      Node* last();
-
-      //! \return the last branch encountered in a depth-first traversal (or this node if it is a branch and has no children). NULL means there are no branches
-      Node* last_branch();
-
-      //! \return the last leaf encountered in a depth-first traversal (or this node if it is a leaf). NULL means there are no leaves
-      Node* last_leaf();
-
-      //! Set the leaf icon to use for this node (only for leaf nodes)
-      void leaf_icon( Fl_Image *icon );
-
-      //! Set whether this node can be moved (either via move() or by dragging with the mouse). Default is \c true
-      inline void movable( bool b )
-	{ SET(MOVABLE,b); }
-
-      //! Get whether this node can be moved (either via move() or by dragging with the mouse)
-      inline bool movable()
-	{ return CHECK(MOVABLE); }
-
-      //! Move this node to absolute position \b pos within its parent
-      /*! \return \c true if the move was successful, or \c false if the move is not allowed
-       */
-      bool move( int pos );
-
-      //! Move this node to a position before, after, or inside node \b n
-      /*! \param where can be one of MOVE_BEFORE, MOVE_AFTER, or MOVE_INSIDE
-	\return \c true if the move was successful, or \c false if the move is not allowed
-       */
-      inline bool move( int where, Node* n )
-	{ return( move( this, where, n ) ); }
-
-      //! Move node \b n1 to a position before, after, or inside node \b n2
-      /*! \param where can be one of MOVE_BEFORE, MOVE_AFTER, or MOVE_INSIDE
-	\return \c true if the move was successful, or \c false if the move is not allowed
-       */
-      static bool move( Node* n1, int where, Node* n2 );
-
-      //! \return the next node (after this node) in this hierarchy (depth-first traversal)
-      Node* next();
-
-      //! \return the next branch (after this node) encountered in a depth-first traversal. NULL means there are no more branches
-      Node* next_branch();
-
-      //! \return the next leaf (after this node) encountered in a depth-first traversal. NULL means there are no more leaves
-      Node* next_leaf();
-
-      //! \return the next sibling (after this node) encountered in a depth-first traversal. NULL means this node is the last child w.r.t. its parent
-      Node* next_sibling();
-
-      //! \return the number of selected entries
-      int num_selected();
-
-      //! Is this node currently open? (only for branch nodes)
-      inline bool open() const
-	{ return( !CHECK(COLLAPSED) || tree->rdata.allBranchesAlwaysOpen ); }
-
-      //! Open or close this node (only for branch nodes)
-      void open( bool b );
-
-      //! Get the node that is the parent of this node, or NULL if there is no parent
-      inline Node* parent() const
-	{ return _parent; }
-
-      //! \return the previous node (before this node) in this hierarchy (depth-first traversal)
-      Node* previous();
-
-      //! \return the previous branch (before this node) encountered in a depth-first traversal. NULL means there are no more branches
-      Node* previous_branch();
-
-      //! \return the previous leaf (before this node) encountered in a depth-first traversal. NULL means there are no more leaves
-      Node* previous_leaf();
-
-      //! \return the previous sibling (before this node) encountered in a depth-first traversal. NULL means this node is the first child w.r.t. its parent
-      Node* previous_sibling();
-
-      //! Print this node and its children to stdout
-      void print( int spaces = 0 );
-
-      //! Remove the entry identified by path \b fullpath from this node
-      /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */
-      inline size_t remove( const char *fullpath )
-	{ return( (size_t)modify( fullpath, REMOVE, tree->rdata ) ); }
-
-      //! Remove the entry identified by unique id \b id from this node
-      /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */
-      size_t remove( size_t id );
-
-      //! Remove the node containing the widget \b w from this node. Note that the widget is automatically destroyed
-      /*! \return the unique id of the removed entry, or \c 0 if no matching entry was found */
-      size_t remove( Fl_Widget *w );
-
-      //! Remove Node \b n
-      /*! \return the id of \b n on successful removal, or \c 0 if \b n is present */
-      inline size_t remove( Node* n )
-	{ if( !n ) return 0; else return remove( n->id() ); }
-
-      //! Select this entry and all child entries
-      void select_all();
-
-      //! Is this node currently selected?
-      inline bool selected() const
-	{ return CHECK(SELECTED); }
-
-      //! Select or unselect this node
-      void select( bool b );
-
-      //! Select only this node
-      inline void select_only()
-	{ tree->unselect_all(); select(true); }
-
-      //! Sort this node's children according to Flu_Tree_Browser::insertion_mode()
-      inline void sort_children()
-	{ sort(); }
-
-      //! Swap this node and node \b n in their respective trees
-      /*! \return \c true if the swap was successful, else \c false */
-      inline bool swap( Node* n )
-	{ return swap( this, n ); }
-
-      //! Swap nodes \b n1 and \b n2 in their respective trees
-      /*! \return \c true if the swap was successful, else \c false */
-      static bool swap( Node* n1, Node* n2 );
-
-      //! Unselect this entry and all child entries (except for Node \b except )
-      void unselect_all( Node* except = NULL );
-
-      //! Get the user-specific data stored in this node
-      inline void* user_data()
-	{ return userData; }
-
-      //! Set the user-specific data stored in this node
-      inline void user_data( void *d )
-	{ userData = d; }
-
-      //! Get the widget in this node, or NULL if there is no widget. Note that the widget is destroyed by the tree/node on clear() or the destructor
-      inline Fl_Widget* widget() const
-	{ return( _widget ? _widget->w : NULL ); }
-
-      //! Set the widget in this node. Note that the widget is destroyed by the tree/node on clear() or the destructor
-      void widget( Fl_Widget *w );
-
-    protected:
-
-      friend class Flu_Tree_Browser;
-      friend class NodeList;
-
-      // Root node constructor
-      Node( const char *lbl = 0 );
-
-      // Non-root constructor
-      Node( bool l, const char* n, Node *p, RData &rdata, Fl_Widget *w, bool showLabel );
-
-      ~Node();
-
-      // add/remove/find/get
-      Node* modify( const char* path, int what, RData &rdata, Fl_Widget *w = 0, bool showLabel = true );
-
-      void initType();
-
-      void sort();
-
-      void determineVisibility( bool parentVisible = true );
-
-      static bool isMoveValid( Node* &n1, int &where, Node* &n2 );
-
-      // handle/draw/measure/count
-      int recurse( RData &rdata, int type, int event = 0 );
-
-      void draw( RData &rdata, bool measure );
-
-      // recursively finding the full path of the node identified by id
-      bool findPath( size_t id, RData &rdata );
-
-      // recursively finding the full path of the node containing w
-      bool findPath( Fl_Widget *w, RData &rdata );
-
-      class WidgetInfo
-	{
-	public:
-	  Fl_Widget *w;
-	  int defaultW;  // the initial width of the widget
-	  void (*CB)(Fl_Widget*,void*);
-	  void *CBData;
-	};
-
-      size_t _id; // the unique id of this node
-      unsigned short flags;
-      NodeList _children;
-      Node *_parent;
-      Flu_Tree_Browser *tree;
-      std::string text;
-      WidgetInfo *_widget;  // memory overhead deferred to WidgetInfo. present only if widget is
-      Fl_Group *_group;
-      void *userData;
-      Fl_Image *cIcon[2], *bIcon[2], *lIcon;
-      Fl_Color textColor;
-      Fl_Font textFont;
-      unsigned char textSize;  // the font size of the entry label text
-      unsigned short textW, textH;  // how big the entry label actually is (stored within the node for performance reasons)
-      int currentY; // needed for animation
-      unsigned short currentH;
-
-      inline static void _widgetCB( Fl_Widget* w, void* arg )
-	{ ((Node*)arg)->widgetCB(); }
-      void widgetCB();
-     };
-
- protected:
-
-  inline static void _scrollCB( Fl_Widget* w, void* arg )
-    { ((Flu_Tree_Browser*)arg)->redraw(); }
-
-  /* override of Fl_Double_Window::draw() */
-  void draw();
-
-  Fl_Group *scrollBox;
-  Fl_Scrollbar *scrollH, *scrollV;
-  Fl_Group *_box;
-  Node root;
-  RData rdata;
-};
-
-#endif
diff --git a/utils/api_demos/mainAntTweakBar.cpp b/utils/api_demos/mainAntTweakBar.cpp
index c6455bbac65c0ec1df4640614e3799bcd7b59ccf..6492dd0217e1d7f947cf2a9ec4cf2d18cf66bc43 100644
--- a/utils/api_demos/mainAntTweakBar.cpp
+++ b/utils/api_demos/mainAntTweakBar.cpp
@@ -19,7 +19,6 @@ drawContext *ctx = 0;
 // Gmsh redefinitions (reimplement stuff in Fltk/Draw.h)
 void Draw(){ ctx->draw3d(); ctx->draw2d(); }
 void DrawCurrentOpenglWindow(bool make_current){}
-void DrawPlugin(void (*draw)(void *context)){}
 int GetFontIndex(const char *fontname){ return 0; }
 int GetFontEnum(int index){ return 0; }
 const char *GetFontName(int index){ return "Helvetica"; }
diff --git a/utils/api_demos/mainGlut.cpp b/utils/api_demos/mainGlut.cpp
index ef648d5644ffc1c61c514e394ccd771f767a920c..8f303953894d629a3806294125cd2c0cdc94f761 100644
--- a/utils/api_demos/mainGlut.cpp
+++ b/utils/api_demos/mainGlut.cpp
@@ -17,7 +17,6 @@ drawContext *ctx = 0;
 // reimplement functions in Fltk/Draw.h
 void Draw(){ ctx->draw3d(); ctx->draw2d(); }
 void DrawCurrentOpenglWindow(bool make_current){}
-void DrawPlugin(void (*draw)(void *context)){}
 int GetFontIndex(const char *fontname){ return 0; }
 int GetFontEnum(int index){ return 0; }
 const char *GetFontName(int index){ return "Helvetica"; }