diff --git a/Fltk/GUI_Extras.cpp b/Fltk/GUI_Extras.cpp
index a45f8d227f99cf9b4c3815c42c9390c583fcf28c..3c13af19bb5ca396e36c25480eefbba4f41c43a8 100644
--- a/Fltk/GUI_Extras.cpp
+++ b/Fltk/GUI_Extras.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI_Extras.cpp,v 1.38 2008-01-07 21:32:58 geuzaine Exp $
+// $Id: GUI_Extras.cpp,v 1.39 2008-01-07 22:59:29 geuzaine Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -76,6 +76,11 @@ int file_chooser(int multi, int create, const char *message,
   default: if(fc->filename()) ret = fc->count(); break;
   }
   thefilterindex = fc->filter_value();
+#if defined(__APPLE__)
+  // FIXME: hack to clear the KEYDOWN state that remains when calling
+  // the file chooser on Mac using a keyboard shortcut
+  Fl::e_state = 0;
+#endif
   return ret;
 #else
   Fl_File_Chooser::show_label = "Format:";
diff --git a/contrib/NativeFileChooser/CHANGES b/contrib/NativeFileChooser/CHANGES
new file mode 100644
index 0000000000000000000000000000000000000000..2c32501d2cda5a4fca10b4954ddbd008eedc6368
--- /dev/null
+++ b/contrib/NativeFileChooser/CHANGES
@@ -0,0 +1,129 @@
+# WARNING: Makefile automatically derives version number from the first line
+# of this file that starts with x.x
+#  |
+# \|/
+#  v
+
+0.84
+-----------------------------------------------------
+	o FLTK2 SUPPORT!
+	  Merged in Frederic Hoerni's mods for fltk2 support, 
+	  converted to fltk2 style namespace.
+
+	o Makefile fix for IMGLIB from Gonzalo Garramuno (fltk.general 09/30/07)
+
+	o Incorporated Ian MacArthur's Makefile for fltk-config
+
+	o 80 column compliance
+
+	o Build: 
+	    > Tar file now extracts with version number in the directory name,
+	    > 'make tar' logic now moved into separate shell script
+
+	o Windows:
+            > Fixed memory leak with lpstrFile (alloc'ed twice)
+	    > Removed unused strfree() code in ClearOFN()
+	    > Small code formatting fixes
+
+
+0.83d
+-----------------------------------------------------
+	o Linux:
+	    > Added Shane Hill's #include <sys/stat.h> to Fl_Native_File_Chooser_FLTK.cxx
+
+	o Windows:
+	    > Added OFN_NOCHANGEDIR flag to prevent GetOpenFileName() from changing the CWD
+	    > Added Andreas Sch?mann's fix for _nfilters++ to the add_filter() method
+	    > Fixed showfile() GetCurrentDirectory() call
+
+	o Copyright fixes and README.txt brought up to date
+
+
+0.83c -- 02/03/2006 fix release
+-----------------------------------------------------
+        o Windows: 
+	    > Fixed behavior of BROWSE_SAVE_FILE
+	    > Fixed SAVEAS_CONFIRM 
+	    > Mods to getcwd() macros in test-browser.cxx for MINGW
+	    > Fixes to test-browser.cxx for MinGW compiles (removed #ifdef VISUAL_STUDIO)
+
+	o Linux:
+	    > "Save File" now has working "Show SaveAs Confirm" dialog
+	    > "Save File" under linux wasn't letting user type in a filename
+            > 'int type()' method wasn't implemented, added _btype
+	    > Removed ifeq() cruft from Makefile.LINUX
+
+	o Applied Ian's fixes to Makefile.fltkconfig
+	o Makefile was sourcing user's ~/.cshrc, added '-f' to SHELL=/bin/csh -f
+
+0.83b -- 01/07/2006 erco: small patches from Ian
+------------------------------------------------
+	o Makefile.fltkconfig WINDOWS -> WIN32
+	o Tar forces owner/group to 0/0, fixed perms on images dir
+
+0.83a -- 01/06/2006 erco: small patches from Ian
+------------------------------------------------
+	o Makefile.fltkconfig patch
+	o Enforce correct perms on files in tar file
+
+0.83 -- 12/06/2005 erco: misc 
+-----------------------------------------------
+        o Windows: Added preset_file() support
+	o Linux: missing filters() method
+	o All: Added options() to API, removed macosx_*()
+	o Added options() to the API with flags:
+		o NEW_FOLDER
+		o PREVIEW
+		o SAVEAS_CONFIRM
+	o Removed macosx_*() stuff -- bad idea
+
+0.82 -- 12/05/2005 erco: misc fixes after merge
+-----------------------------------------------
+	o win32 filter fixes for Alessandro's 11/29 report
+	o Rellocated Macos reference links from code to REFERENCE-MAC.txt
+	o Made sure all #ifdefs use _WIN32 instead of other variants.
+	o Fixed problem with FLTK chooser not showing its icons (natevw)
+	o Added macosx_*() platform specific accessors
+
+    TODO: See ./TODO for outstanding items
+
+0.81 -- 11/28/2005 erco: linux version cleanup
+----------------------------------------------
+        o Support documented filters
+	o free/strdup -> new/delete
+	o added #ifndef at top of FL/Fl_Native_File_Chooser.H to prevent recursion
+
+0.80 -- 11/27/2005 erco+nate: code merge, cleanup
+-------------------------------------------------
+	o Merge in Nathan's changes
+	o Updated docs for all changes noted here
+	o Rewrote mac's filter code to support old "*.a" and new "Desc1\t*.a\nDesc2\t*.b" syntax
+	o Changed Nathan's set_filter() -> filter_value() (consistent with FLTK's own chooser)
+	o Renamed test program to test-browser.cxx
+	o Code cleanup: variable + method naming, 80 column conformance, indents, strdup/malloc -> new
+	TODO: Linux version needs code cleanup (strdup -> new, etc)
+
+0.70 -- 08/04/05 erco: general cleanup
+--------------------------------------
+
+	o Implemented Linux.
+	  This was easy -- just use Fl_File_Chooser.
+
+	o Removed references to non-existant size() method from docs;
+	  the correct method name is total_filenames()
+
+0.62 -- 02/02/2005
+------------------
+
+	o Added Ian's mods to main.cxx to use getcwd() instead of fixed path
+
+	o Added #include/#define's to support getcwd() under Windows VS
+
+0.61 -- 01/26/2005
+------------------
+	o Applied Ian MacArthur's 01/26/2005 fixes,
+	  and Makefile.fltkconfig, including tab fixes and line 90 .obj -> .o fix.
+
+	o Enabled /Wall on Windows VS7.x, and fixed all problems related to Fl_Native*
+	  (mainly, ctor type value was being ignored)
+
diff --git a/contrib/NativeFileChooser/CREDITS b/contrib/NativeFileChooser/CREDITS
new file mode 100644
index 0000000000000000000000000000000000000000..f565f48dff4be683333dcef5e38f8227c8b5830d
--- /dev/null
+++ b/contrib/NativeFileChooser/CREDITS
@@ -0,0 +1,5 @@
+Greg Ercolano      -- initial version for mac + win32, code maintainer
+Ian MacArthur      -- various fixes, additions, Makefile.fltkconfig
+Nathan Vander Wilt -- filter code for WIN32 and Mac, FLTK chooser
+Boris Mayer        -- various debugging
+Frederic Hoerni    -- fltk2 port
diff --git a/contrib/NativeFileChooser/FL/Fl_Native_File_Chooser.H b/contrib/NativeFileChooser/FL/Fl_Native_File_Chooser.H
new file mode 100644
index 0000000000000000000000000000000000000000..88c0acb77a469fa1717141bfd32475f2141ce393
--- /dev/null
+++ b/contrib/NativeFileChooser/FL/Fl_Native_File_Chooser.H
@@ -0,0 +1,40 @@
+//
+// Fl_Native_File_Chooser.H -- FLTK native OS file chooser widget
+//
+// Copyright 2004 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.
+//
+
+#ifndef FL_NATIVE_FILE_CHOOSER_H
+#define FL_NATIVE_FILE_CHOOSER_H
+
+// Use Windows' chooser
+#ifdef _WIN32
+#include <FL/Fl_Native_File_Chooser_WIN32.H>
+#endif
+
+// Use Apple's chooser
+#ifdef __APPLE__
+#include <FL/Fl_Native_File_Chooser_MAC.H>
+#endif
+
+// All else falls back to FLTK's own chooser
+#if ! defined(__APPLE__) && !defined(_WIN32)
+#include <FL/Fl_Native_File_Chooser_FLTK.H>
+#endif
+
+#endif /*FL_NATIVE_FILE_CHOOSER_H*/
diff --git a/contrib/NativeFileChooser/FL/Fl_Native_File_Chooser_FLTK.H b/contrib/NativeFileChooser/FL/Fl_Native_File_Chooser_FLTK.H
new file mode 100644
index 0000000000000000000000000000000000000000..128f36612bb1aad67abac2ec01c60d5af2335bf8
--- /dev/null
+++ b/contrib/NativeFileChooser/FL/Fl_Native_File_Chooser_FLTK.H
@@ -0,0 +1,97 @@
+//
+// Fl_Native_File_Chooser_DEFAULT.H -- FLTK native OS file chooser widget
+//
+// Copyright 2005 by Nathan Vander Wilt.
+// March 2005 - wrapper around Fl_File_Chooser
+//
+// 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.
+//
+
+#include <FL/Fl_File_Chooser.H>
+#include <string.h>
+
+class Fl_Native_File_Chooser {
+public:
+    enum Type {
+	BROWSE_FILE = 0,
+	BROWSE_DIRECTORY,
+	BROWSE_MULTI_FILE,
+	BROWSE_MULTI_DIRECTORY,
+	BROWSE_SAVE_FILE,
+	BROWSE_SAVE_DIRECTORY
+    };
+    enum Option {
+        NO_OPTIONS     = 0x0000,	// no options enabled
+	SAVEAS_CONFIRM = 0x0001,	// Show native 'Save As' overwrite
+					// confirm dialog (if supported)
+	NEW_FOLDER     = 0x0002,	// Show 'New Folder' icon
+					// (if supported)
+	PREVIEW        = 0x0004		// enable preview mode
+    };
+private:
+    int   _btype;			// kind-of browser to show()
+    int   _options;			// general options
+    char *_filter;			// user supplied filter
+    char *_parsedfilt;			// parsed filter
+    int   _filtvalue;			// selected filter
+    char *_preset_file;
+    char *_prevvalue;			// Returned filename
+    char *_directory;
+    char *_errmsg;			// error message
+    Fl_File_Chooser *file_chooser;
+
+    int exist_dialog() {
+	return(fl_choice("File exists. Are you sure you want to overwrite?", 
+			 "Cancel", "   OK   ", NULL));
+    }
+    void load_system_icons() {
+	Fl_File_Icon::load_system_icons();
+    }
+
+    int _nfilters;
+
+    // Private methods
+    void errmsg(const char *msg);
+    int type_fl_file(int);
+    void parse_filter();
+    void keeplocation();
+
+public:
+    Fl_Native_File_Chooser(int val=BROWSE_FILE);
+    ~Fl_Native_File_Chooser();
+
+    // Public methods
+    void type(int);
+    int type() const;
+    void options(int);
+    int options() const;
+    int count() const;
+    const char *filename() const;
+    const char *filename(int i) const;
+    void directory(const char *val);
+    const char *directory() const;
+    void title(const char *);
+    const char* title() const;
+    const char *filter() const;
+    void filter(const char *);
+    int filters() const { return(_nfilters); }
+    void filter_value(int i);
+    int filter_value() const;
+    void preset_file(const char*);
+    const char* preset_file() const;
+    const char *errmsg() const;
+    int show();
+};
diff --git a/contrib/NativeFileChooser/FL/Fl_Native_File_Chooser_MAC.H b/contrib/NativeFileChooser/FL/Fl_Native_File_Chooser_MAC.H
new file mode 100644
index 0000000000000000000000000000000000000000..49577c40748f126b2d2c3547f55616bcdbddaec1
--- /dev/null
+++ b/contrib/NativeFileChooser/FL/Fl_Native_File_Chooser_MAC.H
@@ -0,0 +1,138 @@
+//
+// Fl_Native_File_Chooser_MAC.H -- FLTK native OS file chooser widget
+//
+// Copyright 2004 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.
+//
+//      10        20        30        40        50        60        70
+//       |         |         |         |         |         |         |
+// 4567890123456789012345678901234567890123456789012345678901234567890123456789
+
+// OSX-SPECIFIC NATIVE BROWSER
+#ifdef __APPLE_CC__
+#include <Carbon/Carbon.h>
+#else
+#include <Carbon.h>
+#endif
+
+#include <FL/filename.H>
+#define MAXFILTERS	80
+
+class Fl_Native_File_Chooser {
+public:
+    enum Type {
+	BROWSE_FILE = 0,
+	BROWSE_DIRECTORY,
+	BROWSE_MULTI_FILE,
+	BROWSE_MULTI_DIRECTORY,
+	BROWSE_SAVE_FILE,
+	BROWSE_SAVE_DIRECTORY
+    };
+    enum Option {
+        NO_OPTIONS     = 0x0000,	// no options enabled
+	SAVEAS_CONFIRM = 0x0001,	// Show native 'Save As' overwrite
+					// confirm dialog (if supported)
+	NEW_FOLDER     = 0x0002,	// Show 'New Folder' icon
+					// (if supported)
+	PREVIEW        = 0x0004,	// enable preview mode
+    };
+protected:
+    NavDialogCreationOptions _opts;	// file navigation options
+private:
+    int             _btype;		// kind-of browser to show()
+    int             _options;		// general options
+    NavDialogRef    _ref;		// file navigation reference
+    NavActionState  _keepstate;		// holds button permissions
+    NavMenuItemSpec _tempitem;   	// Popup menu selection
+    char          **_pathnames;		// array of pathnames
+    int             _tpathnames;	// total pathnames
+    char           *_directory;		// default pathname to use
+    char           *_title;		// title for window
+    char           *_preset_file;	// the 'save as' filename
+
+    char           *_filter;		// user-side search filter, eg:
+					// C Files\t*.[ch]\nText Files\t*.txt"
+
+    char           *_filt_names;	// filter names (tab delimited)
+    					// eg. "C Files\tText Files"
+
+    char           *_filt_patt[MAXFILTERS];
+                                        // array of filter patterns, eg:
+					//     _filt_patt[0]="*.{cxx,h}"
+					//     _filt_patt[1]="*.txt"
+
+    int             _filt_total;	// parse_filter() # of filters loaded
+    int             _filt_value;	// index of the selected filter
+    char           *_errmsg;		// error message
+
+    // PRIVATE CLASS TO HANDLE NAVIGATION DIALOG REPLY STRUCT
+    //     Class-ified, mainly to ensure proper cleanup.
+    //
+    class NavReply {
+        int _valid_reply;
+	NavReplyRecord _reply;
+    public:
+        NavReply();
+	~NavReply();
+	int get_reply(NavDialogRef& ref);
+	int get_saveas_basename(char *s, int slen);
+	int get_dirname(char *s, int slen);
+	int get_pathnames(char **&pathnames, int& tpathnames);
+    };
+
+    // Private methods
+    void errmsg(const char *msg);
+    void clear_pathnames();
+    void set_single_pathname(const char *s);
+    int get_saveas_basename(NavDialogRef& ref);
+    int get_pathnames(NavDialogRef& ref);
+    static void event_handler(NavEventCallbackMessage callBackSelector, 
+    					     NavCBRecPtr cbparm, void *data);
+
+    void clear_filters();
+    void add_filter(const char *, const char *);
+    void parse_filter(const char *from);
+    static Boolean filter_proc_cb(AEDesc *, void *, void *, NavFilterModes);
+    Boolean filter_proc_cb2(AEDesc*, void*, void*, NavFilterModes);
+    int post();
+    
+public:
+    Fl_Native_File_Chooser(int val = BROWSE_FILE);
+    ~Fl_Native_File_Chooser();
+
+    // Public methods
+    void type(int);
+    int type() const;
+    void options(int);
+    int options() const;
+    int count() const;
+    const char *filename() const;
+    const char *filename(int i) const;
+    void directory(const char *);
+    const char *directory() const;
+    void title(const char *);
+    const char *title() const;
+    const char *filter() const;
+    void filter(const char *);
+    void filter_value(int i) { _filt_value = i; }
+    int filter_value() { return(_filt_value); }
+    int filters() { return(_filt_total); }
+    void preset_file(const char *);
+    const char *preset_file();
+    const char *errmsg() const;
+    int show();
+};
diff --git a/contrib/NativeFileChooser/FL/Fl_Native_File_Chooser_WIN32.H b/contrib/NativeFileChooser/FL/Fl_Native_File_Chooser_WIN32.H
new file mode 100644
index 0000000000000000000000000000000000000000..889b4842433c76c38f4e6dfede8dcbd1f6b2c8dd
--- /dev/null
+++ b/contrib/NativeFileChooser/FL/Fl_Native_File_Chooser_WIN32.H
@@ -0,0 +1,108 @@
+//
+// Fl_Native_File_Chooser_WINDOWS.H -- FLTK native OS file chooser widget
+//
+// Copyright 2004 by Greg Ercolano.
+// April 2005 - API changes, improved filter processing by Nathan Vander Wilt
+//
+// 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.
+//
+
+// #define _WIN32_WINNT	0x0501	// needed for OPENFILENAME's 'FlagsEx'
+#include <stdio.h>
+#include <stdlib.h>		// malloc
+#include <windows.h>
+#include <commdlg.h>		// OPENFILENAME, GetOpenFileName()
+#include <shlobj.h>		// BROWSEINFO, SHBrowseForFolder()
+
+class Fl_Native_File_Chooser {
+public:
+    enum Type {
+	BROWSE_FILE = 0,
+        BROWSE_DIRECTORY,
+	BROWSE_MULTI_FILE,
+	BROWSE_MULTI_DIRECTORY,
+	BROWSE_SAVE_FILE,
+	BROWSE_SAVE_DIRECTORY
+    };
+    enum Option {
+        NO_OPTIONS     = 0x0000,	// no options enabled
+	SAVEAS_CONFIRM = 0x0001,	// Show native 'Save As' overwrite
+					// confirm dialog (if supported)
+	NEW_FOLDER     = 0x0002,	// Show 'New Folder' icon
+					// (if supported)
+	PREVIEW        = 0x0004,	// enable preview mode
+    };
+private:
+    int  _btype;		// kind-of browser to show()
+    int  _options;		// general options
+    OPENFILENAME _ofn;		// GetOpenFileName() & GetSaveFileName() struct
+    BROWSEINFO   _binf;		// SHBrowseForFolder() struct
+    char  **_pathnames;		// array of pathnames
+    int     _tpathnames;	// total pathnames
+    char   *_directory;		// default pathname to use
+    char   *_title;		// title for window
+    char   *_filter;		// user-side search filter
+    char   *_parsedfilt;	// filter parsed for Windows dialog
+    int     _nfilters;		// number of filters parse_filter counted
+    char   *_preset_file;	// the file to preselect
+    char   *_errmsg;		// error message
+
+    // Private methods
+    void errmsg(const char *msg);
+
+    void clear_pathnames();
+    void set_single_pathname(const char *s);
+    void add_pathname(const char *s);
+
+    void FreePIDL(ITEMIDLIST *pidl);
+    void ClearOFN();
+    void ClearBINF();
+    void Win2Unix(char *s);
+    void Unix2Win(char *s);
+    int showfile();
+    static int CALLBACK Dir_CB(HWND win, UINT msg, LPARAM param, LPARAM data);
+    int showdir();
+
+    void parse_filter(const char *);
+    void clear_filters();
+    void add_filter(const char *, const char *);
+
+public:
+    Fl_Native_File_Chooser(int val = BROWSE_FILE);
+    ~Fl_Native_File_Chooser();
+
+    // Public methods
+    void type(int val);
+    int type() const;
+    void options(int);
+    int options() const;
+    int count() const;
+    const char *filename() const;
+    const char *filename(int i) const;
+    void directory(const char *val);
+    const char *directory() const;
+    void title(const char *val);
+    const char *title() const;
+    const char *filter() const;
+    void filter(const char *val);
+    int filters() const { return _nfilters; }
+    void filter_value(int i);
+    int filter_value() const;
+    void preset_file(const char *);
+    const char *preset_file() const;
+    const char *errmsg() const;
+    int show();
+};
diff --git a/contrib/NativeFileChooser/Fl_Native_File_Chooser.cxx b/contrib/NativeFileChooser/Fl_Native_File_Chooser.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..5c851cb20118105993a4e96066497ee7141dce6a
--- /dev/null
+++ b/contrib/NativeFileChooser/Fl_Native_File_Chooser.cxx
@@ -0,0 +1,36 @@
+//
+// Fl_Native_File_Chooser.cxx -- FLTK native OS file chooser widget
+//
+// Copyright 2004 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.
+//
+
+// Use Windows' chooser
+#ifdef _WIN32
+#include "Fl_Native_File_Chooser_WIN32.cxx"
+#endif
+
+// Use Apple's chooser
+#ifdef __APPLE__
+#include "Fl_Native_File_Chooser_MAC.cxx"
+#endif
+
+// All else falls back to FLTK's own chooser
+#if ! defined(__APPLE__) && !defined(_WIN32)
+#include "Fl_Native_File_Chooser_FLTK.cxx"
+#endif
+
diff --git a/contrib/NativeFileChooser/Fl_Native_File_Chooser_FLTK.cxx b/contrib/NativeFileChooser/Fl_Native_File_Chooser_FLTK.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0244c530842ea18bf0f62e2d03bd70c46e866a69
--- /dev/null
+++ b/contrib/NativeFileChooser/Fl_Native_File_Chooser_FLTK.cxx
@@ -0,0 +1,374 @@
+//
+// Fl_Native_File_Chooser_FLTK.cxx -- FLTK native OS file chooser widget
+//
+// Copyright 2004 by Greg Ercolano.
+// API changes + filter improvements by Nathan Vander Wilt 2005
+//
+// 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.
+//
+// Please keep code 80 column compliant.
+//
+//      10        20        30        40        50        60        70
+//       |         |         |         |         |         |         |
+// 4567890123456789012345678901234567890123456789012345678901234567890123456789
+//
+
+#ifdef FLTK1
+//
+// FLTK1
+//
+#include <FL/Fl_Native_File_Chooser.H>
+#define FNFC_CLASS Fl_Native_File_Chooser
+#define FNFC_CTOR  Fl_Native_File_Chooser
+#define FLTK_CHOOSER_SINGLE    Fl_File_Chooser::SINGLE
+#define FLTK_CHOOSER_DIRECTORY Fl_File_Chooser::DIRECTORY
+#define FLTK_CHOOSER_MULTI     Fl_File_Chooser::MULTI
+#define FLTK_CHOOSER_CREATE    Fl_File_Chooser::CREATE
+#else
+//
+// FLTK2
+//
+#include <fltk/NativeFileChooser.h>
+#include <fltk/run.h>
+#define FNFC_CTOR  NativeFileChooser
+#define FNFC_CLASS fltk::FNFC_CTOR
+#define FLTK_CHOOSER_SINGLE    fltk::FileChooser::SINGLE
+#define FLTK_CHOOSER_DIRECTORY fltk::FileChooser::DIRECTORY
+#define FLTK_CHOOSER_MULTI     fltk::FileChooser::MULTI
+#define FLTK_CHOOSER_CREATE    fltk::FileChooser::CREATE
+#endif
+
+#include "common.cxx"
+#include <sys/stat.h>
+
+// CTOR
+FNFC_CLASS::FNFC_CTOR(int val) {
+    static int init = 0;		// 'first time' initialize flag
+    if ( init == 0 ) {
+        // Initialize when instanced for first time
+	load_system_icons();
+	init = 1;
+    }
+    _btype       = val;
+    _options     = NO_OPTIONS;
+    _filter      = NULL;
+    _filtvalue   = 0;
+    _parsedfilt  = NULL;
+    _preset_file = NULL;
+    _prevvalue   = NULL;
+    _directory   = NULL;
+    _errmsg      = NULL;
+#ifdef FLTK1
+    file_chooser = new Fl_File_Chooser(NULL, NULL, 0, NULL);
+#else
+    file_chooser = new fltk::FileChooser(NULL, NULL, 0, NULL);
+#endif
+    type(val);		// do this after file_chooser created
+    _nfilters    = 0;
+}
+
+// DTOR
+FNFC_CLASS::~FNFC_CTOR() {
+    delete file_chooser;
+    _filter      = strfree(_filter);
+    _parsedfilt  = strfree(_parsedfilt);
+    _preset_file = strfree(_preset_file);
+    _prevvalue   = strfree(_prevvalue);
+    _directory   = strfree(_directory);
+    _errmsg      = strfree(_errmsg);
+}
+
+// PRIVATE: SET ERROR MESSAGE
+void FNFC_CLASS::errmsg(const char *msg) {
+    _errmsg = strfree(_errmsg);
+    _errmsg = strnew(msg);
+}
+
+// PRIVATE: translate Native types to Fl_File_Chooser types
+int FNFC_CLASS::type_fl_file(int val) {
+    switch (val) {
+        case BROWSE_FILE:
+	    return(FLTK_CHOOSER_SINGLE);
+        case BROWSE_DIRECTORY:
+	    return(FLTK_CHOOSER_SINGLE | FLTK_CHOOSER_DIRECTORY);
+        case BROWSE_MULTI_FILE:
+	    return(FLTK_CHOOSER_MULTI);
+        case BROWSE_MULTI_DIRECTORY:
+	    return(FLTK_CHOOSER_DIRECTORY | FLTK_CHOOSER_MULTI);
+        case BROWSE_SAVE_FILE:
+	    return(FLTK_CHOOSER_SINGLE | FLTK_CHOOSER_CREATE);
+        case BROWSE_SAVE_DIRECTORY:
+	    return(FLTK_CHOOSER_DIRECTORY | FLTK_CHOOSER_MULTI | FLTK_CHOOSER_CREATE);
+        default:
+	    return(FLTK_CHOOSER_SINGLE);
+    }
+}
+
+void FNFC_CLASS::type(int val) {
+    _btype = val;
+    file_chooser->type(type_fl_file(val));
+}
+
+int FNFC_CLASS::type() const {
+    return(_btype);
+}
+
+// SET OPTIONS
+void FNFC_CLASS::options(int val) {
+    _options = val;
+}
+
+// GET OPTIONS
+int FNFC_CLASS::options() const {
+    return(_options);
+}
+
+// Show chooser, blocks until done.
+// RETURNS:
+//    0 - user picked a file
+//    1 - user cancelled
+//   -1 - failed; errmsg() has reason
+//
+int FNFC_CLASS::show() {
+    // FILTER
+    if ( _parsedfilt ) {
+        file_chooser->filter(_parsedfilt);
+    }
+
+    // FILTER VALUE
+    //     Set this /after/ setting the filter
+    //
+    file_chooser->filter_value(_filtvalue);
+
+    // DIRECTORY
+    if ( _directory && _directory[0] ) {
+        file_chooser->directory(_directory);
+    } else {
+        file_chooser->directory(_prevvalue);
+    }
+
+    // PRESET FILE
+    if ( _preset_file ) {
+        file_chooser->value(_preset_file);
+    }
+
+    // OPTIONS: PREVIEW
+    file_chooser->preview( (options() & PREVIEW) ? 1 : 0);
+
+    // OPTIONS: NEW FOLDER
+    if ( options() & NEW_FOLDER )
+        file_chooser->type(file_chooser->type() |
+	                   FLTK_CHOOSER_CREATE);		// on
+
+    // SHOW
+    file_chooser->show();
+
+#ifdef FLTK1
+    // FLTK1: BLOCK WHILE BROWSER SHOWN
+    while ( file_chooser->shown() ) {
+        Fl::wait();
+    }
+#else
+    // FLTK2: BLOCK WHILE BROWSER SHOWN
+    while ( file_chooser->visible() ) {
+        fltk::wait();
+    }
+#endif
+
+    if ( file_chooser->value() && file_chooser->value()[0] ) {
+        _prevvalue = strfree(_prevvalue);
+	_prevvalue = strnew(file_chooser->value());
+	_filtvalue = file_chooser->filter_value();	// update filter value
+
+	// HANDLE SHOWING 'SaveAs' CONFIRM
+	if ( options() & SAVEAS_CONFIRM && type() == BROWSE_SAVE_FILE ) {
+	    struct stat buf;
+	    if ( stat(file_chooser->value(), &buf) != -1 ) {
+		if ( buf.st_mode & S_IFREG ) {		// Regular file + exists?
+		     if ( exist_dialog() == 0 ) {
+		         return(1);
+		     }
+		}
+	    }
+	}
+    }
+
+    if ( file_chooser->count() ) return(0);
+    else return(1);
+}
+
+// RETURN ERROR MESSAGE
+const char *FNFC_CLASS::errmsg() const {
+    return(_errmsg ? _errmsg : "No error");
+}
+
+// GET FILENAME
+const char* FNFC_CLASS::filename() const {
+    if ( file_chooser->count() > 0 ) return(file_chooser->value());
+    return("");
+}
+
+// GET FILENAME FROM LIST OF FILENAMES
+const char* FNFC_CLASS::filename(int i) const {
+    if ( i < file_chooser->count() )
+        return(file_chooser->value(i+1));	// convert fltk 1 based to our 0 based
+    return("");
+}
+
+// SET TITLE
+//     Can be NULL if no title desired.
+//
+void FNFC_CLASS::title(const char *val) {
+    file_chooser->label(val);
+}
+
+// GET TITLE
+//    Can return NULL if none set.
+//
+const char *FNFC_CLASS::title() const {
+    return(file_chooser->label());
+}
+
+// SET FILTER
+//     Can be NULL if no filter needed
+//
+void FNFC_CLASS::filter(const char *val) {
+    _filter = strfree(_filter);
+    _filter = strnew(val);
+    parse_filter();
+}
+
+// GET FILTER
+const char *FNFC_CLASS::filter() const {
+    return(_filter);
+}
+
+// SET SELECTED FILTER
+void FNFC_CLASS::filter_value(int val) {
+    _filtvalue = val;
+}
+
+// RETURN SELECTED FILTER
+int FNFC_CLASS::filter_value() const {
+    return(_filtvalue);
+}
+
+// GET TOTAL FILENAMES CHOSEN
+int FNFC_CLASS::count() const {
+    return(file_chooser->count());
+}
+
+// PRESET PATHNAME
+//     Can be NULL if no preset is desired.
+//
+void FNFC_CLASS::directory(const char *val) {
+    _directory = strfree(_directory);
+    _directory = strnew(val);
+}
+
+// GET PRESET PATHNAME
+//    Can return NULL if none set.
+//
+const char *FNFC_CLASS::directory() const {
+    return(_directory);
+}
+
+// Convert our filter format to fltk's chooser format
+//     FROM                                     TO (FLTK)
+//     -------------------------                --------------------------
+//     "*.cxx"                                  "*.cxx Files(*.cxx)"
+//     "C Files\t*.{cxx,h}"                     "C Files(*.{cxx,h})"
+//     "C Files\t*.{cxx,h}\nText Files\t*.txt"  "C Files(*.{cxx,h})\tText Files(*.txt)"
+//
+//     Returns a modified version of the filter that the caller is responsible
+//     for freeing with strfree().
+//
+void FNFC_CLASS::parse_filter() {
+    _parsedfilt = strfree(_parsedfilt);	// clear previous parsed filter (if any)
+    _nfilters = 0;
+    char *in = _filter;
+    if ( !in ) return;
+
+    int has_name = strchr(in, '\t') ? 1 : 0;
+
+    char mode = has_name ? 'n' : 'w';	// parse mode: n=title, w=wildcard
+    char wildcard[1024] = "";		// parsed wildcard
+    char name[1024] = "";
+
+    // Parse filter user specified
+    for ( ; 1; in++ ) {
+
+        /*** DEBUG
+        printf("WORKING ON '%c': mode=<%c> name=<%s> wildcard=<%s>\n",
+	                    *in, mode,     name,     wildcard);
+	***/
+
+        switch (*in) {
+	    // FINISHED PARSING NAME?
+	    case '\t':
+	        if ( mode != 'n' ) goto regchar;
+		mode = 'w';
+		break;
+
+	    // ESCAPE NEXT CHAR
+	    case '\\':
+	        ++in;
+		goto regchar;
+
+	    // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS?
+	    case '\r':
+	    case '\n':
+	    case '\0':
+		// APPEND NEW FILTER TO LIST
+		if ( wildcard[0] ) {
+		    // OUT: "name(wild)\tname(wild)"
+		    char comp[2048];
+		    sprintf(comp, "%s%.511s(%.511s)", ((_parsedfilt)?"\t":""),
+		    				      name, wildcard);
+		    _parsedfilt = strapp(_parsedfilt, comp);
+		    _nfilters++;
+		    //DEBUG printf("DEBUG: PARSED FILT NOW <%s>\n", _parsedfilt);
+		}
+		// RESET
+		wildcard[0] = name[0] = '\0';
+		mode = strchr(in, '\t') ? 'n' : 'w';
+		// DONE?
+		if ( *in == '\0' ) return;	// done
+		else continue;			// not done yet, more filters
+
+	    // Parse all other chars
+	    default:				// handle all non-special chars
+	    regchar:				// handle regular char
+                switch ( mode ) {
+	            case 'n': chrcat(name, *in);     continue;
+	            case 'w': chrcat(wildcard, *in); continue;
+	        }
+		break;
+	}
+    }
+    //NOTREACHED
+}
+
+// SET PRESET FILENAME
+void FNFC_CLASS::preset_file(const char* val) {
+    _preset_file = strfree(_preset_file);
+    _preset_file = strnew(val);
+}
+
+// GET PRESET FILENAME
+const char* FNFC_CLASS::preset_file() const {
+    return(_preset_file);
+}
diff --git a/contrib/NativeFileChooser/Fl_Native_File_Chooser_MAC.cxx b/contrib/NativeFileChooser/Fl_Native_File_Chooser_MAC.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..5965521acc3d7c5a0adda62ad25567220908651b
--- /dev/null
+++ b/contrib/NativeFileChooser/Fl_Native_File_Chooser_MAC.cxx
@@ -0,0 +1,863 @@
+//
+// Fl_Native_File_Chooser_MAC.cxx -- FLTK native OS file chooser widget
+//
+// Copyright 2004 by Greg Ercolano.
+// FLTK2/MAC port by Greg Ercolano 2007.
+//
+// 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.
+//
+// Please keep code 80 column compliant.
+//
+//      10        20        30        40        50        60        70
+//       |         |         |         |         |         |         |
+// 4567890123456789012345678901234567890123456789012345678901234567890123456789
+//
+// TODO:
+//	o When doing 'open file', only dir is preset, not filename.
+//        Possibly 'preset_file' could be used to select the filename.
+//
+#include "common.cxx"		// strnew/strfree/strapp/chrcat
+
+#ifdef FLTK1
+//
+// FLTK1
+//
+#include <FL/Fl.H>
+#include <FL/Fl_Native_File_Chooser.H>
+#include <FL/filename.H>
+#define FNFC_CLASS Fl_Native_File_Chooser
+#define FNFC_CTOR  Fl_Native_File_Chooser
+#else
+//
+// FLTK2
+//
+#include <fltk/NativeFileChooser.h>
+#include <fltk/run.h>
+#include <fltk/filename.h>
+#define FNFC_CTOR  NativeFileChooser
+#define FNFC_CLASS fltk::FNFC_CTOR
+#define fl_filename_match filename_match		// fltk1 name -> fltk2 name
+#define fl_filename_isdir filename_isdir		// fltk1 name -> fltk2 name
+#endif
+
+// TRY TO CONVERT AN AEDesc TO AN FSSpec
+//     As per Apple Technical Q&A QA1274
+//     eg: http://developer.apple.com/qa/qa2001/qa1274.html
+//     Returns 'noErr' if OK,
+//             or an 'OSX result code' on error.
+//
+static int AEDescToFSSpec(const AEDesc* desc, FSSpec* fsspec) {
+    OSStatus err = noErr;
+    AEDesc coerceDesc;
+    // If AEDesc isn't already an FSSpec, convert it to one
+    if ( desc->descriptorType != typeFSS ) {
+        if ( ( err = AECoerceDesc(desc, typeFSS, &coerceDesc) ) == noErr ) {
+	    // Get FSSpec out of AEDesc
+            err = AEGetDescData(&coerceDesc, fsspec, sizeof(FSSpec));
+            AEDisposeDesc(&coerceDesc);
+        }
+    } else {
+        err = AEGetDescData(desc, fsspec, sizeof(FSSpec));
+    }
+    return( err );
+}
+
+// CONVERT AN FSSpec TO A PATHNAME
+static void FSSpecToPath(const FSSpec &spec, char *buff, int bufflen) {
+    FSRef fsRef;
+    FSpMakeFSRef(&spec, &fsRef);
+    FSRefMakePath(&fsRef, (UInt8*)buff, bufflen);
+}
+
+// CONVERT REGULAR PATH -> FSSpec
+//     If file does not exist, expect fnfErr.
+//     Returns 'noErr' if OK,
+//             or an 'OSX result code' on error.
+//
+static OSStatus PathToFSSpec(const char *path, FSSpec &spec) {
+    OSStatus err;
+    FSRef ref;
+    if ((err = FSPathMakeRef((const UInt8*)path, &ref, NULL)) != noErr) {
+	return(err);
+    }
+    // FSRef -> FSSpec
+    if ((err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, &spec,
+    							     NULL)) != noErr) {
+	return(err);
+    }
+    return(noErr);
+}
+
+// NAVREPLY: CTOR
+FNFC_CLASS::NavReply::NavReply() {
+    _valid_reply = 0;
+}
+
+// NAVREPLY: DTOR
+FNFC_CLASS::NavReply::~NavReply() {
+    if ( _valid_reply ) {
+	NavDisposeReply(&_reply);
+    }
+}
+
+// GET REPLY FROM THE NAV* DIALOG
+int FNFC_CLASS::NavReply::get_reply(NavDialogRef& ref) {
+    if ( _valid_reply ) {
+	NavDisposeReply(&_reply);	// dispose of previous
+	_valid_reply = 0;
+    }
+    if ( ref == NULL || NavDialogGetReply(ref, &_reply) != noErr ) {
+	return(-1);
+    }
+    _valid_reply = 1;
+    return(0);
+}
+
+// RETURN THE BASENAME USER WANTS TO 'Save As'
+int FNFC_CLASS::NavReply::get_saveas_basename(char *s, int slen) {
+    if (CFStringGetCString(_reply.saveFileName, s, slen-1,
+    					kCFStringEncodingUTF8) == false) {
+	s[0] = '\0';
+	return(-1);
+    }
+    return(0);
+}
+
+// RETURN THE DIRECTORY NAME
+//    Returns 0 on success, -1 on error.
+//
+int FNFC_CLASS::NavReply::get_dirname(char *s, int slen) {
+    FSSpec fsspec;
+    if ( AEDescToFSSpec(&_reply.selection, &fsspec) != noErr ) {
+        // Conversion failed? Return empty name
+	s[0] = 0;
+	return(-1);
+    }
+    FSSpecToPath(fsspec, s, slen);
+    return(0);
+}
+
+// RETURN MULTIPLE DIRECTORIES
+//     Returns: 0 on success with pathnames[] containing pathnames selected,
+//             -1 on error
+//
+int FNFC_CLASS::NavReply::get_pathnames(char **&pathnames,
+						    int& tpathnames) {
+    // How many items selected?
+    long count = 0;
+    if ( AECountItems(&_reply.selection, &count) != noErr ) 
+	{ return(-1); }
+
+    // Allocate space for that many pathnames
+    pathnames = new char*[count];
+    memset((void*)pathnames, 0, count*sizeof(char*));
+    tpathnames = count;
+
+    // Walk list of pathnames selected
+    for (short index=1; index<=count; index++) {
+	AEKeyword keyWord;
+	AEDesc    desc;
+	if (AEGetNthDesc(&_reply.selection, index, typeFSS, &keyWord, 
+							   &desc) != noErr) {
+	    pathnames[index-1] = strnew("");
+	    continue;
+	}
+	FSSpec fsspec;
+	if (AEGetDescData(&desc, &fsspec, sizeof(FSSpec)) != noErr ) {
+	    pathnames[index-1] = strnew("");
+	    continue;
+	}
+	char s[4096];
+	FSSpecToPath(fsspec, s, sizeof(s)-1);
+	pathnames[index-1] = strnew(s);
+	AEDisposeDesc(&desc);
+    }
+    return(0);
+}
+
+// FREE PATHNAMES ARRAY, IF IT HAS ANY CONTENTS
+void FNFC_CLASS::clear_pathnames() {
+    if ( _pathnames ) {
+	while ( --_tpathnames >= 0 ) {
+	    _pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]);
+	}
+	delete [] _pathnames;
+	_pathnames = NULL;
+    }
+    _tpathnames = 0;
+}
+
+// SET A SINGLE PATHNAME
+void FNFC_CLASS::set_single_pathname(const char *s) {
+    clear_pathnames();
+    _pathnames = new char*[1];
+    _pathnames[0] = strnew(s);
+    _tpathnames = 1;
+}
+
+// GET THE 'Save As' FILENAME
+//    Returns -1 on error, errmsg() has reason, filename == "".
+//             0 if OK, filename() has filename chosen.
+//
+int FNFC_CLASS::get_saveas_basename(NavDialogRef& ref) {
+    if ( ref == NULL ) {
+        errmsg("get_saveas_basename: ref is NULL");
+	return(-1);
+    }
+    NavReply reply;
+    OSStatus err;
+    if ((err = reply.get_reply(ref)) != noErr ) {
+	errmsg("NavReply::get_reply() failed");
+	clear_pathnames();
+	return(-1);
+    }
+
+    char pathname[4096] = "";
+    // Directory name..
+    //    -2 leaves room to append '/'
+    //
+    if ( reply.get_dirname(pathname, sizeof(pathname)-2) < 0 ) {
+	clear_pathnames();
+	errmsg("NavReply::get_dirname() failed");
+	return(-1);
+    }
+    // Append '/'
+    int len = strlen(pathname);
+    pathname[len++] = '/';
+    pathname[len] = '\0';
+    // Basename..
+    if ( reply.get_saveas_basename(pathname+len, sizeof(pathname)-len) < 0 ) {
+	clear_pathnames();
+	errmsg("NavReply::get_saveas_basename() failed");
+	return(-1);
+    }
+    set_single_pathname(pathname);
+    return(0);
+}
+
+// GET (POTENTIALLY) MULTIPLE FILENAMES
+//     Returns:
+//         -1 -- error, errmsg() has reason, filename == ""
+//          0 -- OK, pathnames()/filename() has pathname(s) chosen
+//
+int FNFC_CLASS::get_pathnames(NavDialogRef& ref) {
+    if ( ref == NULL ) {
+        errmsg("get_saveas_basename: ref is NULL");
+	return(-1);
+    }
+    NavReply reply;
+    OSStatus err;
+    if ((err = reply.get_reply(ref)) != noErr ) { 
+	errmsg("NavReply::get_reply() failed");
+	clear_pathnames();
+	return(-1);
+    }
+    // First, clear pathnames array of any previous contents
+    clear_pathnames();
+    if ( reply.get_pathnames(_pathnames, _tpathnames) < 0 ) {
+	clear_pathnames();
+	errmsg("NavReply::get_dirname() failed");
+	return(-1);
+    }
+    return(0);
+}
+
+// NAV CALLBACK EVENT HANDLER
+void FNFC_CLASS::event_handler(
+				    NavEventCallbackMessage callBackSelector, 
+				    NavCBRecPtr cbparm,
+				    void *data) {
+    OSStatus err;
+    FNFC_CLASS *nfb = (FNFC_CLASS*)data;
+    switch (callBackSelector) {
+	case kNavCBStart:
+	    if ( nfb->directory() || nfb->preset_file() ) {
+	        const char *pathname = nfb->directory() 
+					   ? nfb->directory()
+					   : nfb->preset_file();
+		FSSpec spec;
+		if ( ( err = PathToFSSpec(pathname, spec) ) != noErr ) {
+		    fprintf(stderr, "PathToFSSpec(%s) failed: err=%d\n",
+		        pathname, (int)err);
+                    break;
+		}
+		AEDesc desc;
+		if ((err = AECreateDesc(typeFSS, &spec, sizeof(FSSpec), 
+		                        &desc)) != noErr) {
+		    fprintf(stderr, "AECreateDesc() failed: err=%d\n",
+		        (int)err);
+		}
+		if ((err = NavCustomControl(cbparm->context,
+					    kNavCtlSetLocation, 
+					    &desc)) != noErr) {
+		    fprintf(stderr, "NavCustomControl() failed: err=%d\n",
+		        (int)err);
+		}
+		AEDisposeDesc(&desc);
+	    }
+	    if ( nfb->_btype == BROWSE_SAVE_FILE && nfb->preset_file() ) {
+		 CFStringRef namestr = 
+		     CFStringCreateWithCString(NULL,
+		     			       nfb->preset_file(),
+					       kCFStringEncodingASCII);
+		 NavDialogSetSaveFileName(cbparm->context, namestr);
+		 CFRelease(namestr);
+	    }
+	    NavCustomControl(cbparm->context,
+	                     kNavCtlSetActionState,
+			     &nfb->_keepstate );
+            
+	    // Select the right filter in pop-up menu
+            if ( nfb->_filt_value == nfb->_filt_total ) {
+	        // Select All Documents
+                NavPopupMenuItem kAll = kNavAllFiles;
+                NavCustomControl(cbparm->context, kNavCtlSelectAllType, &kAll);
+            } else if (nfb->_filt_value < nfb->_filt_total) {
+	        // Select custom filter
+                nfb->_tempitem.version = kNavMenuItemSpecVersion;
+                nfb->_tempitem.menuCreator = 'extn';
+                nfb->_tempitem.menuType = nfb->_filt_value;
+		*nfb->_tempitem.menuItemName = '\0';	// needed on 10.3+
+                NavCustomControl(cbparm->context,
+		                 kNavCtlSelectCustomType,
+				 &(nfb->_tempitem));
+            }
+	    break;
+
+	case kNavCBPopupMenuSelect:
+            NavMenuItemSpecPtr ptr;
+	    // they really buried this one!
+            ptr = (NavMenuItemSpecPtr)cbparm->eventData.eventDataParms.param;
+            if ( ptr->menuCreator ) {
+	        // Gets index to filter ( menuCreator = 'extn' )
+	        nfb->_filt_value = ptr->menuType;
+	    } else {
+		// All docs filter selected ( menuCreator = '\0\0\0\0' )
+	        nfb->_filt_value = nfb->_filt_total;
+	    }
+	    break;
+
+	case kNavCBSelectEntry:
+            NavActionState astate;
+            switch ( nfb->_btype ) {
+		// these don't need selection override
+		case BROWSE_MULTI_FILE:
+		case BROWSE_MULTI_DIRECTORY:
+		case BROWSE_SAVE_FILE:
+		    break;
+
+		// These need to allow only one item, so disable
+		// Open button if user tries to select multiple files
+		case BROWSE_SAVE_DIRECTORY:
+		case BROWSE_DIRECTORY:
+		case BROWSE_FILE:
+		    SInt32 selectcount;
+		    AECountItems((AEDescList*)cbparm->
+		  		  eventData.eventDataParms.param,
+				  &selectcount);
+		    if ( selectcount > 1 ) {
+		        NavCustomControl(cbparm->context,
+					 kNavCtlSetSelection,
+					 NULL);
+		        astate = nfb->_keepstate |
+				 kNavDontOpenState |
+				 kNavDontChooseState;
+		        NavCustomControl(cbparm->context,
+					 kNavCtlSetActionState,
+					 &astate );
+		    }
+		    else {
+		        astate= nfb->_keepstate | kNavNormalState;
+		        NavCustomControl(cbparm->context,
+					 kNavCtlSetActionState,
+					 &astate );
+		    }
+		    break;
+	    }
+	    break;
+    }
+}
+
+// CONSTRUCTOR
+FNFC_CLASS::FNFC_CTOR(int val) {
+    _btype          = val;
+    NavGetDefaultDialogCreationOptions(&_opts);
+    _opts.optionFlags |= kNavDontConfirmReplacement;	// no confirms for "save as"
+    _options        = NO_OPTIONS;
+    _ref            = NULL;
+    memset(&_tempitem, 0, sizeof(_tempitem));
+    _pathnames      = NULL;
+    _tpathnames     = 0;
+    _title          = NULL;
+    _filter         = NULL;
+    _filt_names     = NULL;
+    memset(_filt_patt, 0, sizeof(char*) * MAXFILTERS);
+    _filt_total     = 0;
+    _filt_value     = 0;
+    _directory      = NULL;
+    _preset_file    = NULL;
+    _errmsg         = NULL;
+    _keepstate      = kNavNormalState;
+}
+
+// DESTRUCTOR
+FNFC_CLASS::~FNFC_CTOR() {
+    // _opts			// nothing to manage
+    if (_ref) { NavDialogDispose(_ref); _ref = NULL; }
+    // _options			// nothing to manage
+    // _keepstate		// nothing to manage
+    // _tempitem		// nothing to manage
+    clear_pathnames();
+    _directory   = strfree(_directory);
+    _title       = strfree(_title);
+    _preset_file = strfree(_preset_file);
+    _filter      = strfree(_filter);
+    //_filt_names		// managed by clear_filters()
+    //_filt_patt[i]		// managed by clear_filters()
+    //_filt_total		// managed by clear_filters()
+    clear_filters();
+    //_filt_value		// nothing to manage
+    _errmsg = strfree(_errmsg);
+}
+
+// SET THE TYPE OF BROWSER
+void FNFC_CLASS::type(int val) {
+    _btype = val;
+}
+
+// GET TYPE OF BROWSER
+int FNFC_CLASS::type() const {
+    return(_btype);
+}
+
+// SET OPTIONS
+void FNFC_CLASS::options(int val) {
+    _options = val;
+}
+
+// GET OPTIONS
+int FNFC_CLASS::options() const {
+    return(_options);
+}
+
+// SHOW THE BROWSER WINDOW
+//     Returns:
+//         0 - user picked a file
+//         1 - user cancelled
+//        -1 - failed; errmsg() has reason
+//
+int FNFC_CLASS::show() {
+
+    // Make sure fltk interface updates before posting our dialog
+#ifdef FLTK1
+    Fl::flush();
+#else
+    fltk::flush();
+#endif
+
+    // BROWSER TITLE
+    CFStringRef cfs_title;
+    cfs_title = CFStringCreateWithCString(NULL,
+    					  _title ? _title : "No Title",
+					  kCFStringEncodingASCII);
+    _opts.windowTitle = cfs_title;
+
+    _keepstate = kNavNormalState;
+
+    // BROWSER FILTERS
+    CFArrayRef filter_array = NULL;
+    {
+	// One or more filters specified?
+	if ( _filt_total ) {
+	    // NAMES -> CFArrayRef
+	    CFStringRef tab = CFSTR("\t");
+	    CFStringRef tmp_cfs;
+	    tmp_cfs = CFStringCreateWithCString(NULL, _filt_names,
+	    					kCFStringEncodingASCII);
+	    filter_array = CFStringCreateArrayBySeparatingStrings(
+	    					NULL, tmp_cfs, tab);
+	    CFRelease(tmp_cfs);
+	    CFRelease(tab);
+	    _opts.popupExtension = filter_array;
+	    _opts.optionFlags |= kNavAllFilesInPopup;
+	} else {
+	    filter_array = NULL;
+	    _opts.popupExtension = NULL;
+	    _opts.optionFlags |= kNavAllFilesInPopup;
+	}
+    }
+
+    // HANDLE OPTIONS WE SUPPORT
+    if ( _options & SAVEAS_CONFIRM ) {
+        _opts.optionFlags &= ~kNavDontConfirmReplacement;	// enables confirm
+    } else {
+        _opts.optionFlags |= kNavDontConfirmReplacement;	// disables confirm
+    }
+
+    // POST BROWSER
+    int err = post();
+
+    // RELEASE _FILT_ARR
+    if ( filter_array ) CFRelease(filter_array);
+    filter_array = NULL;
+    _opts.popupExtension = NULL;
+    _filt_total = 0;
+
+    // RELEASE TITLE
+    if ( cfs_title ) CFRelease(cfs_title);
+    cfs_title = NULL;
+
+    return(err);
+}
+
+// POST BROWSER
+//     Internal use only.
+//     Assumes '_opts' has been initialized.
+//
+//     Returns:
+//         0 - user picked a file
+//         1 - user cancelled
+//        -1 - failed; errmsg() has reason
+//     
+int FNFC_CLASS::post() {
+
+    // INITIALIZE BROWSER
+    OSStatus err;
+    if ( _filt_total == 0 ) {	// Make sure they match
+	_filt_value = 0;	// TBD: move to someplace more logical?
+    }
+
+    switch (_btype) {
+	case BROWSE_FILE:
+	case BROWSE_MULTI_FILE:
+	    //_keepstate = kNavDontNewFolderState;	
+	    // Prompt user for one or more files
+	    if ((err = NavCreateGetFileDialog(
+			  &_opts,		// options
+			  0, 			// file types
+			  event_handler,	// event handler
+			  0,			// preview callback
+			  filter_proc_cb,	// filter callback
+			  (void*)this,		// callback data
+			  &_ref)) != noErr ) {	// dialog ref
+		errmsg("NavCreateGetFileDialog: failed");
+		return(-1);
+	    }
+	    break;
+
+	case BROWSE_DIRECTORY:
+	case BROWSE_MULTI_DIRECTORY:
+	    _keepstate = kNavDontNewFolderState;
+	    //FALLTHROUGH
+
+	case BROWSE_SAVE_DIRECTORY:
+	    // Prompts user for one or more files or folders
+	    if ((err = NavCreateChooseFolderDialog(
+			  &_opts,		// options
+			  event_handler,	// event callback
+			  0,			// filter callback
+			  (void*)this,		// callback data
+			  &_ref)) != noErr ) {	// dialog ref
+		errmsg("NavCreateChooseFolderDialog: failed");
+		return(-1);
+	    }
+	    break;
+
+	case BROWSE_SAVE_FILE:
+	    // Prompt user for filename to 'save as'
+	    if ((err = NavCreatePutFileDialog(
+			  &_opts,		// options
+			  0,			// file types
+			  0,			// file creator
+			  event_handler,	// event handler
+			  (void*)this,		// callback data
+			  &_ref)) != noErr ) {	// dialog ref
+		errmsg("NavCreatePutFileDialog: failed");
+		return(-1);
+	    }
+	    break;
+    }
+
+    // SHOW THE DIALOG
+    if ( ( err = NavDialogRun(_ref) ) != 0 ) {
+	char msg[80];
+	sprintf(msg, "NavDialogRun: failed (err=%d)", (int)err);
+	errmsg(msg);
+	return(-1);
+    }
+
+    // WHAT ACTION DID USER CHOOSE?
+    NavUserAction act = NavDialogGetUserAction(_ref);
+    if ( act == kNavUserActionNone ) {
+	errmsg("Nothing happened yet (dialog still open)");
+	return(-1);
+    }
+    else if ( act == kNavUserActionCancel ) { 	// user chose 'cancel'
+	return(1);
+    }
+    else if ( act == kNavUserActionSaveAs ) {	// user chose 'save as'
+	return(get_saveas_basename(_ref));
+    }
+
+    // TOO MANY FILES CHOSEN?
+    int ret = get_pathnames(_ref);
+    if ( _btype == BROWSE_FILE && ret == 0 && _tpathnames != 1 ) {
+	char msg[80];
+	sprintf(msg, "Expected only one file to be chosen.. you chose %d.",
+	    (int)_tpathnames);
+	errmsg(msg);
+	return(-1);
+    }
+    return(err);
+}
+
+// SET ERROR MESSAGE
+//     Internal use only.
+//
+void FNFC_CLASS::errmsg(const char *msg) {
+    _errmsg = strfree(_errmsg);
+    _errmsg = strnew(msg);
+}
+
+// RETURN ERROR MESSAGE
+const char *FNFC_CLASS::errmsg() const {
+    return(_errmsg ? _errmsg : "No error");
+}
+
+// GET FILENAME
+const char* FNFC_CLASS::filename() const {
+    if ( _pathnames && _tpathnames > 0 ) return(_pathnames[0]);
+    return("");
+}
+
+// GET FILENAME FROM LIST OF FILENAMES
+const char* FNFC_CLASS::filename(int i) const {
+    if ( _pathnames && i < _tpathnames ) return(_pathnames[i]);
+    return("");
+}
+
+// GET TOTAL FILENAMES CHOSEN
+int FNFC_CLASS::count() const {
+    return(_tpathnames);
+}
+
+// PRESET PATHNAME
+//     Value can be NULL for none.
+//
+void FNFC_CLASS::directory(const char *val) {
+    _directory = strfree(_directory);
+    _directory = strnew(val);
+}
+
+// GET PRESET PATHNAME
+//     Returned value can be NULL if none set.
+//
+const char* FNFC_CLASS::directory() const {
+    return(_directory);
+}
+
+// SET TITLE
+//     Value can be NULL if no title desired.
+//
+void FNFC_CLASS::title(const char *val) {
+    _title = strfree(_title);
+    _title = strnew(val);
+}
+
+// GET TITLE
+//     Returned value can be NULL if none set.
+//
+const char *FNFC_CLASS::title() const {
+    return(_title);
+}
+
+// SET FILTER
+//     Can be NULL if no filter needed
+//
+void FNFC_CLASS::filter(const char *val) {
+    _filter = strfree(_filter);
+    _filter = strnew(val);
+
+    // Parse filter user specified
+    //     IN: _filter = "C Files\t*.{cxx,h}\nText Files\t*.txt"
+    //    OUT: _filt_names   = "C Files\tText Files"
+    //         _filt_patt[0] = "*.{cxx,h}"
+    //         _filt_patt[1] = "*.txt"
+    //         _filt_total   = 2
+    //
+    parse_filter(_filter);
+}
+
+// GET FILTER
+//     Returned value can be NULL if none set.
+//
+const char *FNFC_CLASS::filter() const {
+    return(_filter);
+}
+
+// CLEAR ALL FILTERS
+//    Internal use only.
+//
+void FNFC_CLASS::clear_filters() {
+    _filt_names = strfree(_filt_names);
+    for (int i=0; i<_filt_total; i++) {
+	_filt_patt[i] = strfree(_filt_patt[i]);
+    }
+    _filt_total = 0;
+}
+
+// PARSE USER'S FILTER SPEC
+//    Parses user specified filter ('in'),
+//    breaks out into _filt_patt[], _filt_names, and _filt_total.
+//
+//    Handles:
+//    IN:                                   OUT:_filt_names    OUT: _filt_patt
+//    ------------------------------------  ------------------ ---------------
+//    "*.{ma,mb}"                           "*.{ma,mb} Files"  "*.{ma,mb}"
+//    "*.[abc]"                             "*.[abc] Files"    "*.[abc]"
+//    "*.txt"                               "*.txt Files"      "*.c"
+//    "C Files\t*.[ch]"                     "C Files"          "*.[ch]"
+//    "C Files\t*.[ch]\nText Files\t*.cxx"  "C Files"          "*.[ch]"
+//
+//    Parsing Mode:
+//         IN:"C Files\t*.{cxx,h}"
+//             |||||||  |||||||||
+//       mode: nnnnnnn  wwwwwwwww
+//             \_____/  \_______/
+//              Name     Wildcard
+//
+void FNFC_CLASS::parse_filter(const char *in) {
+    clear_filters();
+    if ( ! in ) return;
+    int has_name = strchr(in, '\t') ? 1 : 0;
+
+    char mode = has_name ? 'n' : 'w';	// parse mode: n=title, w=wildcard
+    char wildcard[1024] = "";		// parsed wildcard
+    char name[1024] = "";
+
+    // Parse filter user specified
+    for ( ; 1; in++ ) {
+
+        //// DEBUG
+        //// printf("WORKING ON '%c': mode=<%c> name=<%s> wildcard=<%s>\n",
+	////                    *in,  mode,     name,     wildcard);
+	
+        switch (*in) {
+	    // FINISHED PARSING NAME?
+	    case '\t':
+	        if ( mode != 'n' ) goto regchar;
+		mode = 'w';
+		break;
+
+	    // ESCAPE NEXT CHAR
+	    case '\\':
+	        ++in;
+		goto regchar;
+
+	    // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS?
+	    case '\r':
+	    case '\n':
+	    case '\0':
+		// TITLE
+		//     If user didn't specify a name, make one
+		//
+		if ( name[0] == '\0' ) {
+		    sprintf(name, "%.*s Files", (int)sizeof(name)-10, wildcard);
+		}
+		// APPEND NEW FILTER TO LIST
+		if ( wildcard[0] ) {
+		    // Add to filtername list
+		    //     Tab delimit if more than one. We later break
+		    //     tab delimited string into CFArray with 
+		    //     CFStringCreateArrayBySeparatingStrings()
+		    //
+		    if ( _filt_total ) {
+			_filt_names = strapp(_filt_names, "\t");
+		    }
+		    _filt_names = strapp(_filt_names, name);
+
+		    // Add filter to the pattern array
+		    _filt_patt[_filt_total++] = strnew(wildcard);
+		}
+		// RESET
+		wildcard[0] = name[0] = '\0';
+		mode = strchr(in, '\t') ? 'n' : 'w';
+		// DONE?
+		if ( *in == '\0' ) return;	// done
+		else continue;			// not done yet, more filters
+
+	    // Parse all other chars
+	    default:				// handle all non-special chars
+	    regchar:				// handle regular char
+                switch ( mode ) {
+	            case 'n': chrcat(name, *in);     continue;
+	            case 'w': chrcat(wildcard, *in); continue;
+	        }
+		break;
+	}
+    }
+    //NOTREACHED
+}
+
+// STATIC: FILTER CALLBACK
+Boolean FNFC_CLASS::filter_proc_cb(AEDesc *theItem,
+				   void *info,
+				   void *callBackUD,
+				   NavFilterModes filterMode) {
+     return((FNFC_CLASS*)callBackUD)->filter_proc_cb2(
+				    theItem, info, callBackUD, filterMode);
+}
+
+// FILTER CALLBACK
+//     Return true if match,
+//            false if no match.
+//
+Boolean FNFC_CLASS::filter_proc_cb2(AEDesc *theItem,
+				    void *info,
+				    void *callBackUD,
+				    NavFilterModes filterMode) {
+    // All files chosen or no filters
+    if ( _filt_value == _filt_total ) return(true);
+    
+    FSSpec fsspec;
+    char pathname[4096];
+    
+    // On fail, filter should return true by default
+    if ( AEDescToFSSpec(theItem, &fsspec) != noErr ) {
+        return(true);
+    }
+    FSSpecToPath(fsspec, pathname, sizeof(pathname)-1);
+
+    if ( fl_filename_isdir(pathname) ) return(true);
+    if ( fl_filename_match(pathname, _filt_patt[_filt_value]) ) return(true);
+    else return(false);
+}
+
+// SET PRESET FILE
+//     Value can be NULL for none.
+//
+void FNFC_CLASS::preset_file(const char* val) {
+    _preset_file = strfree(_preset_file);
+    _preset_file = strnew(val);
+}
+
+// PRESET FILE
+//     Returned value can be NULL if none set.
+//
+const char* FNFC_CLASS::preset_file() {
+    return(_preset_file);
+}
+
diff --git a/contrib/NativeFileChooser/Fl_Native_File_Chooser_WIN32.cxx b/contrib/NativeFileChooser/Fl_Native_File_Chooser_WIN32.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..73f0092d862e762e287a1d2453d6909eaa2afaa7
--- /dev/null
+++ b/contrib/NativeFileChooser/Fl_Native_File_Chooser_WIN32.cxx
@@ -0,0 +1,801 @@
+//
+// Fl_Native_File_Chooser_WIN32.cxx -- FLTK native OS file chooser widget
+//
+// Copyright 2004 by Greg Ercolano.
+// API changes + filter improvements by Nathan Vander Wilt 2005
+// FLTK2/WIN32 port 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.
+//
+// Please keep code 80 column compliant.
+//
+//      10        20        30        40        50        60        70
+//       |         |         |         |         |         |         |
+// 4567890123456789012345678901234567890123456789012345678901234567890123456789
+//
+
+// Any application to multi-folder implementation:
+//     http://www.codeproject.com/dialog/selectfolder.asp
+//
+
+#include <stdio.h>		// debugging
+#include "common.cxx"		// strnew/strfree/strapp/chrcat
+
+#ifdef FLTK1
+//
+// FLTK1
+//
+#include <FL/Fl_Native_File_Chooser.H>
+#define FNFC_CLASS Fl_Native_File_Chooser
+#define FNFC_CTOR  Fl_Native_File_Chooser
+#else
+//
+// FLTK2
+//
+#include <fltk/NativeFileChooser.h>
+#include <fltk/run.h>
+#define FNFC_CTOR  NativeFileChooser
+#define FNFC_CLASS fltk::FNFC_CTOR
+#endif
+
+#define LCURLY_CHR	'{'
+#define RCURLY_CHR	'}'
+#define LBRACKET_CHR	'['
+#define RBRACKET_CHR	']'
+#define MAXFILTERS	80
+
+// STATIC: PRINT WINDOWS 'DOUBLE NULL' STRING (DEBUG)
+static void dnullprint(char *wp) {
+    if ( ! wp ) return;
+    for ( int t=0; true; t++ ) {
+        if ( wp[t] == '\0' && wp[t+1] == '\0' ) {
+	    printf("\\0\\0");
+	    fflush(stdout);
+	    return;
+	} else if ( wp[t] == '\0' ) {
+	    printf("\\0");
+	} else { 
+	    printf("%c",wp[t]);
+	}
+    }
+}
+
+// RETURN LENGTH OF DOUBLENULL STRING
+//    Includes single nulls in count, excludes trailing doublenull.
+//
+//         1234 567
+//         |||/\|||
+//    IN: "one\0two\0\0"
+//   OUT: 7
+//
+static int dnulllen(const char *wp) {
+    int len = 0;
+    while ( ! ( *(wp+0) == 0 && *(wp+1) == 0 ) )
+        { ++wp; ++len; }
+    return(len);
+}
+
+// STATIC: Append a string to another, leaving terminated with DOUBLE NULL.
+//     Automatically handles extending length of string.
+//     wp can be NULL (a new wp will be allocated and initialized).
+//     string must be NULL terminated.
+//     The pointer wp may be modified on return.
+//
+static void dnullcat(char*&wp, const char *string, int n = -1 ) {
+    //DEBUG printf("DEBUG: dnullcat IN: <"); dnullprint(wp); printf(">\n");
+    int inlen = ( n < 0 ) ? strlen(string) : n;
+    if ( ! wp ) {
+        wp = new char[inlen + 4];
+	*(wp+0) = '\0';
+	*(wp+1) = '\0';
+    } else {
+        int wplen = dnulllen(wp);
+	// Make copy of wp into larger buffer
+	char *tmp = new char[wplen + inlen + 4];
+	memcpy(tmp, wp, wplen+2);	// copy of wp plus doublenull
+	delete [] wp;			// delete old wp
+	wp = tmp;			// use new copy
+	//DEBUG printf("DEBUG: dnullcat COPY: <"); dnullprint(wp); printf("> (wplen=%d)\n", wplen);
+    }
+
+    // Find end of double null string
+    //     *wp2 is left pointing at second null.
+    //
+    char *wp2 = wp;
+    if ( *(wp2+0) != '\0' && *(wp2+1) != '\0' ) {
+	for ( ; 1; wp2++ )
+	    if ( *(wp2+0) == '\0' && *(wp2+1) == '\0' )
+		{ wp2++; break; }
+    }
+
+    if ( n == -1 ) n = strlen(string);
+    strncpy(wp2, string, n);
+
+    // Leave string double-null terminated
+    *(wp2+n+0) = '\0';
+    *(wp2+n+1) = '\0';
+    //DEBUG printf("DEBUG: dnullcat OUT: <"); dnullprint(wp); printf(">\n\n");
+}
+
+// CTOR
+FNFC_CLASS::FNFC_CTOR(int val) {
+    _btype           = val;
+    _options         = NO_OPTIONS;
+    memset((void*)&_ofn, 0, sizeof(OPENFILENAME));
+    _ofn.lStructSize = sizeof(OPENFILENAME);
+    _ofn.hwndOwner   = NULL;
+    memset((void*)&_binf, 0, sizeof(BROWSEINFO));
+    _pathnames       = NULL;
+    _tpathnames      = 0;
+    _directory       = NULL;
+    _title           = NULL;
+    _filter          = NULL;
+    _parsedfilt      = NULL;
+    _nfilters        = 0;
+    _preset_file     = NULL;
+    _errmsg          = NULL;
+}
+
+// DTOR
+FNFC_CLASS::~FNFC_CTOR() {
+    //_pathnames                // managed by clear_pathnames()
+    //_tpathnames               // managed by clear_pathnames()
+    _directory   = strfree(_directory);
+    _title       = strfree(_title);
+    _filter      = strfree(_filter);
+    //_parsedfilt               // managed by clear_filters()
+    //_nfilters                 // managed by clear_filters()
+    _preset_file = strfree(_preset_file);
+    _errmsg      = strfree(_errmsg);
+    clear_filters();
+    clear_pathnames();
+    ClearOFN();
+    ClearBINF();
+}
+
+// SET TYPE OF BROWSER
+void FNFC_CLASS::type(int val) {
+    _btype = val;
+}
+
+// GET TYPE OF BROWSER
+int FNFC_CLASS::type() const {
+    return( _btype );
+}
+
+// SET OPTIONS
+void FNFC_CLASS::options(int val) {
+    _options = val;
+}
+
+// GET OPTIONS
+int FNFC_CLASS::options() const {
+    return(_options);
+}
+
+// PRIVATE: SET ERROR MESSAGE
+void FNFC_CLASS::errmsg(const char *val) {
+    _errmsg = strfree(_errmsg);
+    _errmsg = strnew(val);
+}
+
+// FREE PATHNAMES ARRAY, IF IT HAS ANY CONTENTS
+void FNFC_CLASS::clear_pathnames() {
+    if ( _pathnames ) {
+	while ( --_tpathnames >= 0 ) {
+	    _pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]);
+	}
+	delete [] _pathnames;
+	_pathnames = NULL;
+    }
+    _tpathnames = 0;
+}
+
+// SET A SINGLE PATHNAME
+void FNFC_CLASS::set_single_pathname(const char *s) {
+    clear_pathnames();
+    _pathnames = new char*[1];
+    _pathnames[0] = strnew(s);
+    _tpathnames = 1;
+}
+
+// ADD PATHNAME TO EXISTING ARRAY
+void FNFC_CLASS::add_pathname(const char *s) {
+    if ( ! _pathnames ) {
+        // Create first element in array
+	++_tpathnames;
+	_pathnames = new char*[_tpathnames];
+    } else {
+        // Grow array by 1
+        char **tmp = new char*[_tpathnames+1];		// create new buffer
+	memcpy((void*)tmp, (void*)_pathnames, 
+	                   sizeof(char*)*_tpathnames);	// copy old
+	delete [] _pathnames;				// delete old
+	_pathnames = tmp;				// use new
+	++_tpathnames;
+    }
+    _pathnames[_tpathnames-1] = strnew(s);
+}
+
+// FREE A PIDL (Pointer to IDentity List)
+void FNFC_CLASS::FreePIDL(ITEMIDLIST *pidl) {
+    IMalloc *imalloc = NULL;
+    if ( SUCCEEDED(SHGetMalloc(&imalloc)) )
+	{ imalloc->Free(pidl); imalloc->Release(); imalloc = NULL; }
+}
+
+// CLEAR MICROSOFT OFN (OPEN FILE NAME) CLASS
+void FNFC_CLASS::ClearOFN() {
+    // Free any previously allocated lpstrFile before zeroing out _ofn
+    if ( _ofn.lpstrFile ) {
+        _ofn.lpstrFile = strfree((char*)_ofn.lpstrFile);
+    }
+    if ( _ofn.lpstrInitialDir ) {
+        _ofn.lpstrInitialDir = (LPCSTR)strfree((char*)_ofn.lpstrInitialDir);
+    }
+    _ofn.lpstrFilter = NULL;		// (deleted elsewhere)
+    int temp = _ofn.nFilterIndex;	// keep the filter_value
+    memset((void*)&_ofn, 0, sizeof(_ofn));
+    _ofn.lStructSize  = sizeof(OPENFILENAME);
+    _ofn.nFilterIndex = temp;
+}
+
+// CLEAR MICROSOFT BINF (BROWSER INFO) CLASS
+void FNFC_CLASS::ClearBINF() {
+    if ( _binf.pidlRoot ) {
+	FreePIDL((ITEMIDLIST*)_binf.pidlRoot);
+	_binf.pidlRoot = NULL;
+    }
+    memset((void*)&_binf, 0, sizeof(_binf));
+}
+
+// CONVERT WINDOWS BACKSLASHES TO UNIX FRONTSLASHES
+void FNFC_CLASS::Win2Unix(char *s) {
+    for ( ; *s; s++ )
+	if ( *s == '\\' ) *s = '/';
+}
+
+// CONVERT UNIX FRONTSLASHES TO WINDOWS BACKSLASHES
+void FNFC_CLASS::Unix2Win(char *s) {
+    for ( ; *s; s++ )
+	if ( *s == '/' ) *s = '\\';
+}
+
+// SHOW FILE BROWSER
+int FNFC_CLASS::showfile() {
+    ClearOFN();
+    clear_pathnames();
+    size_t fsize = 2048;
+    _ofn.Flags |= OFN_NOVALIDATE;	// prevent disabling of front slashes
+    _ofn.Flags |= OFN_HIDEREADONLY;	// hide goofy readonly flag
+    // USE NEW BROWSER
+    _ofn.Flags |= OFN_EXPLORER;		// use newer explorer windows
+    _ofn.Flags |= OFN_ENABLESIZING;	// allow window to be resized (hey, why not?)
+
+    // XXX: The docs for OFN_NOCHANGEDIR says the flag is 'ineffective' on XP/2K/NT!
+    //      But let's set it anyway..
+    //
+    _ofn.Flags |= OFN_NOCHANGEDIR;	// prevent dialog for messing up the cwd
+
+    switch ( _btype ) {
+	case BROWSE_DIRECTORY:
+	case BROWSE_MULTI_DIRECTORY:
+	case BROWSE_SAVE_DIRECTORY:
+	    abort();			// never happens: handled by showdir()
+	case BROWSE_FILE:
+	    fsize = 65536;		// XXX: there must be a better way
+	    break;
+	case BROWSE_MULTI_FILE:
+	    _ofn.Flags |= OFN_ALLOWMULTISELECT;
+	    fsize = 65536;		// XXX: there must be a better way
+	    break;
+	case BROWSE_SAVE_FILE:
+	    if ( options() & SAVEAS_CONFIRM && type() == BROWSE_SAVE_FILE ) {
+		_ofn.Flags |= OFN_OVERWRITEPROMPT;
+	    }
+	    break;
+    }
+    // SPACE FOR RETURNED FILENAME
+    _ofn.lpstrFile    = new char[fsize];
+    _ofn.nMaxFile     = fsize-1;
+    _ofn.lpstrFile[0] = '\0';
+    _ofn.lpstrFile[1] = '\0';		// dnull
+    // PARENT WINDOW
+    _ofn.hwndOwner = GetForegroundWindow();
+    // DIALOG TITLE
+    _ofn.lpstrTitle = _title ? _title : NULL;
+    // FILTER
+    _ofn.lpstrFilter = _parsedfilt ? _parsedfilt : NULL;
+    // PRESET FILE
+    //     If set, supercedes _directory. See KB Q86920 for details
+    //
+    if ( _preset_file ) {
+        size_t len = strlen(_preset_file);
+	if ( len >= _ofn.nMaxFile ) {
+	    char msg[80];
+	    sprintf(msg, "preset_file() filename is too long: %ld is >=%ld", 
+	        (long)len, (long)fsize);
+	    return(-1);
+	}
+	strncpy(_ofn.lpstrFile, _preset_file, _ofn.nMaxFile);
+	Unix2Win(_ofn.lpstrFile);
+	_ofn.lpstrFile[len+0] = 0;	// multiselect needs dnull
+	_ofn.lpstrFile[len+1] = 0;
+    }
+    if ( _directory ) {
+	// PRESET DIR
+	//     XXX: See KB Q86920 for doc bug:
+	//     http://support.microsoft.com/default.aspx?scid=kb;en-us;86920
+	//
+	_ofn.lpstrInitialDir = strnew(_directory);
+	Unix2Win((char*)_ofn.lpstrInitialDir);
+    }
+    // SAVE THE CURRENT DIRECTORY
+    //     XXX: Save the cwd because GetOpenFileName() is probably going to
+    //     change it, in spite of the OFN_NOCHANGEDIR flag, due to its docs
+    //     saying the flag is 'ineffective'. %^(
+    //
+    char oldcwd[MAX_PATH];
+    GetCurrentDirectory(MAX_PATH, oldcwd);
+    oldcwd[MAX_PATH-1] = '\0';
+    // OPEN THE DIALOG WINDOW
+    int err;
+    if ( _btype == BROWSE_SAVE_FILE ) {
+	err = GetSaveFileName(&_ofn);
+    } else {
+	err = GetOpenFileName(&_ofn);
+    }
+    if ( err == 0 ) {
+	// EXTENDED ERROR CHECK
+	int err = CommDlgExtendedError();
+	// CANCEL?
+	if ( err == 0 ) 
+	    return(1);	// user hit 'cancel'
+	// AN ERROR OCCURRED
+	char msg[80];
+	sprintf(msg, "CommDlgExtendedError() code=%d", err);
+	errmsg(msg);
+	// XXX: RESTORE CWD
+	if ( oldcwd[0] ) SetCurrentDirectory(oldcwd);
+	return(-1);
+    }
+    // XXX: RESTORE CWD
+    if ( oldcwd[0] ) {
+        SetCurrentDirectory(oldcwd);
+    }
+    // PREPARE PATHNAMES FOR RETURN
+    switch ( _btype ) {
+	case BROWSE_FILE: 
+	case BROWSE_SAVE_FILE:
+	    set_single_pathname(_ofn.lpstrFile);
+	    Win2Unix(_pathnames[_tpathnames-1]);
+	    break;
+	case BROWSE_MULTI_FILE: {
+	    // EXTRACT MULTIPLE FILENAMES
+	    const char *dirname = _ofn.lpstrFile;
+	    int dirlen = strlen(dirname);
+	    if ( dirlen > 0 ) {
+		// WALK STRING SEARCHING FOR 'DOUBLE-NULL'
+		//     eg. "/dir/name\0foo1\0foo2\0foo3\0\0"
+		//
+		char pathname[2048]; 
+		for ( const char *s = _ofn.lpstrFile + dirlen + 1; 
+						      *s; s+= (strlen(s)+1)) {
+		    strcpy(pathname, dirname);
+		    strcat(pathname, "\\");
+		    strcat(pathname, s);
+		    add_pathname(pathname);
+		    Win2Unix(_pathnames[_tpathnames-1]);
+		}
+	    }
+	    // XXX
+	    //    Work around problem where pasted forward-slash pathname
+	    //    into the file browser causes new "Explorer" interface
+	    //    not to grok forward slashes, passing back as a 'filename'..!
+	    //
+	    if ( _tpathnames == 0 ) {
+		add_pathname(dirname); 
+		Win2Unix(_pathnames[_tpathnames-1]);
+	    }
+	    break;
+	}
+	case BROWSE_DIRECTORY:
+	case BROWSE_MULTI_DIRECTORY:
+	case BROWSE_SAVE_DIRECTORY:
+	    abort();			// never happens: handled by showdir()
+    }
+    return(0);
+}
+
+// Used by SHBrowseForFolder(), sets initial selected dir.
+// Ref: Usenet: microsoft.public.vc.mfc, Dec 8 2000, 1:38p David Lowndes
+//              Subject: How to specify to select an initial folder .."
+//
+int CALLBACK FNFC_CLASS::Dir_CB(HWND win, UINT msg, 
+                                            LPARAM param, LPARAM data) {
+    switch (msg) {
+	case BFFM_INITIALIZED:
+	    if (data) ::SendMessage(win, BFFM_SETSELECTION, TRUE, data);
+	    break;
+	case BFFM_SELCHANGED:
+	    TCHAR path[MAX_PATH];
+	    if ( SHGetPathFromIDList((ITEMIDLIST*)param, path) ) {
+	        ::SendMessage(win, BFFM_ENABLEOK, 0, 1);
+	    } else {
+		//disable ok button if not a path
+	        ::SendMessage(win, BFFM_ENABLEOK, 0, 0);
+	    }
+	    break;
+	case BFFM_VALIDATEFAILED:
+	    // we could pop up an annoying message here. 
+	    // also needs set ulFlags |= BIF_VALIDATE
+	    break;
+	default:
+	    break;
+    }
+    return(0);
+}
+
+// SHOW DIRECTORY BROWSER
+int FNFC_CLASS::showdir() {
+    OleInitialize(NULL);	// init needed by BIF_USENEWUI
+    ClearBINF();
+    clear_pathnames();
+    // PARENT WINDOW
+    _binf.hwndOwner = GetForegroundWindow();
+    // DIALOG TITLE
+    _binf.lpszTitle = _title ? _title : NULL;
+    // FLAGS
+    _binf.ulFlags = 0; 		// initialize
+
+    // TBD: make sure matches to runtime system, if need be.
+    //( what if _WIN32_IE doesn't match system? does the program not run? )
+    // TBD: match all 3 types of directories
+
+#if defined(BIF_NONEWFOLDERBUTTON)				// Version 6.0
+    if ( _btype == BROWSE_DIRECTORY ) _binf.ulFlags |= BIF_NONEWFOLDERBUTTON;
+    _binf.ulFlags |= BIF_USENEWUI | BIF_SHAREABLE | BIF_RETURNONLYFSDIRS;
+#elif defined(BIF_USENEWUI)					// Version 5.0
+    if ( _btype == BROWSE_DIRECTORY ) _binf.ulFlags |= BIF_EDITBOX;
+    else if ( _btype == BROWSE_SAVE_DIRECTORY ) _binf.ulFlags |= BIF_USENEWUI;
+    _binf.ulFlags |= BIF_SHAREABLE | BIF_RETURNONLYFSDIRS;
+#elif defined(BIF_EDITBOX)					// Version 4.71
+    _binf.ulFlags |= BIF_RETURNONLYFSDIRS | BIF_EDITBOX;
+#else								// Version Old
+    _binf.ulFlags |= BIF_RETURNONLYFSDIRS;
+#endif
+
+    // BUFFER
+    char displayname[MAX_PATH];
+    _binf.pszDisplayName = displayname;
+    // PRESET DIR
+    char presetname[MAX_PATH];
+    if ( _directory ) {
+	strcpy(presetname, _directory);
+	Unix2Win(presetname);
+	_binf.lParam = (LPARAM)presetname;
+    }
+    else _binf.lParam = 0;
+    _binf.lpfn = Dir_CB;
+    // OPEN BROWSER
+    ITEMIDLIST *pidl = SHBrowseForFolder(&_binf);
+    // CANCEL?
+    if ( pidl == NULL ) return(1);
+
+    // GET THE PATHNAME(S) THE USER SELECTED
+    // TBD: expand NetHood shortcuts from this PIDL??
+    // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shbrowseforfolder.asp
+
+    TCHAR path[MAX_PATH];
+    if ( SHGetPathFromIDList(pidl, path) ) {
+        Win2Unix(path);
+	add_pathname(path);
+    }
+    FreePIDL(pidl);
+    if ( !strlen(path) ) return(1);             // don't return empty pathnames
+    return(0);
+}
+
+// RETURNS:
+//    0 - user picked a file
+//    1 - user cancelled
+//   -1 - failed; errmsg() has reason
+//
+int FNFC_CLASS::show() {
+    if ( _btype == BROWSE_DIRECTORY || 
+         _btype == BROWSE_MULTI_DIRECTORY || 
+	 _btype == BROWSE_SAVE_DIRECTORY ) {
+	return(showdir());
+    } else {
+	return(showfile());
+    }
+}
+
+// RETURN ERROR MESSAGE
+const char *FNFC_CLASS::errmsg() const {
+    return(_errmsg ? _errmsg : "No error");
+}
+
+// GET FILENAME
+const char* FNFC_CLASS::filename() const {
+    if ( _pathnames && _tpathnames > 0 ) return(_pathnames[0]);
+    return("");
+}
+
+// GET FILENAME FROM LIST OF FILENAMES
+const char* FNFC_CLASS::filename(int i) const {
+    if ( _pathnames && i < _tpathnames ) return(_pathnames[i]);
+    return("");
+}
+
+// GET TOTAL FILENAMES CHOSEN
+int FNFC_CLASS::count() const {
+    return(_tpathnames);
+}
+
+// PRESET PATHNAME
+//     Can be NULL if no preset is desired.
+//
+void FNFC_CLASS::directory(const char *val) {
+    _directory = strfree(_directory);
+    _directory = strnew(val);
+}
+
+// GET PRESET PATHNAME
+//    Can return NULL if none set.
+//
+const char *FNFC_CLASS::directory() const {
+    return(_directory);
+}
+
+// SET TITLE
+//     Can be NULL if no title desired.
+//
+void FNFC_CLASS::title(const char *val) {
+    _title = strfree(_title);
+    _title = strnew(val);
+}
+
+// GET TITLE
+//    Can return NULL if none set.
+//
+const char *FNFC_CLASS::title() const {
+    return(_title);
+}
+
+// SET FILTER
+//     Can be NULL if no filter needed
+//
+void FNFC_CLASS::filter(const char *val) {
+    _filter = strfree(_filter);
+    clear_filters();
+    if ( val ) {
+	_filter = strnew(val);
+	parse_filter(_filter);
+    }
+    add_filter("All Files", "*.*");	// always include 'all files' option
+
+#ifdef DEBUG
+    nullprint(_parsedfilt);
+#endif /*DEBUG*/
+}
+
+// GET FILTER
+//    Can return NULL if none set.
+//
+const char *FNFC_CLASS::filter() const {
+    return(_filter);
+}
+
+// CLEAR FILTERS
+void FNFC_CLASS::clear_filters() {
+    _nfilters = 0;
+    _parsedfilt = strfree(_parsedfilt);
+}
+
+// ADD A FILTER
+void FNFC_CLASS::add_filter(
+	   const char *name_in,	    // name of filter (optional: can be null)
+	   const char *winfilter    // windows style filter (eg. "*.cxx;*.h")
+	  ) {
+    // No name? Make one..
+    char name[1024];
+    if ( !name_in || name_in[0] == '\0' ) {
+	sprintf(name, "%.*s Files", sizeof(name)-10, winfilter);
+    } else {
+        sprintf(name, "%.*s", sizeof(name)-10, name_in);
+    }
+    dnullcat(_parsedfilt, name);
+    dnullcat(_parsedfilt, winfilter);
+    _nfilters++;
+    //DEBUG printf("DEBUG: ADD FILTER name=<%s> winfilter=<%s>\n", name, winfilter);
+}
+
+// CONVERT FLTK STYLE PATTERN MATCHES TO WINDOWS 'DOUBLENULL' PATTERN
+//    Handles:
+//        IN              OUT
+//        -----------     -----------------------------
+//        *.{ma,mb}       "*.{ma,mb} Files\0*.ma;*.mb\0\0"
+//        *.[abc]         "*.[abc] Files\0*.a;*.b;*.c\0\0"
+//        *.txt           "*.txt Files\0*.txt\0\0"
+//        C Files\t*.[ch] "C Files\0*.c;*.h\0\0"
+//
+//    Example:
+//         IN: "*.{ma,mb}"
+//        OUT: "*.ma;*.mb Files\0*.ma;*.mb\0All Files\0*.*\0\0"
+//              ---------------  ---------  ---------  ---
+//                     |             |          |       |
+//                   Title       Wildcards    Title    Wildcards
+//
+// Parsing Mode:
+//         IN:"C Files\t*.{cxx,h}"
+//             |||||||  |||||||||
+//       mode: nnnnnnn  ww{{{{{{{
+//             \_____/  \_______/
+//              Name     Wildcard
+//
+void FNFC_CLASS::parse_filter(const char *in) {
+    clear_filters();
+    if ( ! in ) return;
+
+    int has_name = strchr(in, '\t') ? 1 : 0;
+
+    char mode = has_name ? 'n' : 'w';	// parse mode: n=name, w=wildcard
+    int nwildcards = 0;
+    char wildcards[MAXFILTERS][1024];	// parsed wildcards (can be several)
+    char wildprefix[512] = "";
+    char name[512] = "";
+
+    // Init
+    int t;
+    for ( t=0; t<MAXFILTERS; t++ ) {
+        wildcards[t][0] = '\0';
+    }
+
+    // Parse
+    for ( ; 1; in++ ) {
+
+        //// DEBUG
+        //// printf("WORKING ON '%c': mode=<%c> name=<%s> wildprefix=<%s> nwildcards=%d wildcards[n]=<%s>\n",
+	////        *in, mode, name, wildprefix, nwildcards, wildcards[nwildcards]);
+
+        switch (*in) {
+	    case ',':
+	    case '|':
+	        if ( mode == LCURLY_CHR ) {
+		    // create new wildcard, copy in prefix
+		    strcat(wildcards[nwildcards++], wildprefix);
+		    continue;
+		} else {
+		    goto regchar;
+		}
+		continue;
+
+	    // FINISHED PARSING A NAME?
+	    case '\t':
+	        if ( mode != 'n' ) goto regchar;
+		// finish parsing name? switch to wildcard mode
+		mode = 'w';
+		break;
+
+	    // ESCAPE NEXT CHAR
+	    case '\\':
+	        ++in;
+		goto regchar;
+
+	    // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS?
+	    case '\r':
+	    case '\n':
+	    case '\0':
+	    {
+	        if ( mode == 'w' ) {		// finished parsing wildcard?
+		    if ( nwildcards == 0 ) {
+		        strcpy(wildcards[nwildcards++], wildprefix);
+		    }
+		    // Append wildcards in Microsoft's "*.one;*.two" format
+		    char comp[4096] = "";
+		    for ( t=0; t<nwildcards; t++ ) {
+			if ( t != 0 ) strcat(comp, ";");
+			strcat(comp, wildcards[t]);
+		    }
+		    // Add if not empty
+		    if ( comp[0] ) {
+			add_filter(name, comp);
+		    }
+		}
+		// RESET
+		for ( t=0; t<MAXFILTERS; t++ ) {
+		    wildcards[t][0] = '\0';
+		}
+		nwildcards = 0;
+		wildprefix[0] = name[0] = '\0';
+		mode = strchr(in,'\t') ? 'n' : 'w';
+		// DONE?
+		if ( *in == '\0' ) return;	// done
+		continue;			// not done yet, more filters
+	    }
+
+	    // STARTING A WILDCARD?
+	    case LBRACKET_CHR:
+	    case LCURLY_CHR:
+	        mode = *in;
+		if ( *in == LCURLY_CHR ) {
+		    // create new wildcard
+		    strcat(wildcards[nwildcards++], wildprefix);
+		}
+		continue;
+
+	    // ENDING A WILDCARD?
+	    case RBRACKET_CHR:
+	    case RCURLY_CHR:
+		mode = 'w';	// back to wildcard mode
+		continue;
+
+	    // ALL OTHER NON-SPECIAL CHARACTERS
+	    default:
+	    regchar:		// handle regular char
+                switch ( mode ) {
+	            case LBRACKET_CHR: 
+			// create new wildcard
+		        ++nwildcards;
+			// copy in prefix
+			strcpy(wildcards[nwildcards-1], wildprefix);
+			// append search char
+			chrcat(wildcards[nwildcards-1], *in);
+			continue;
+
+	            case LCURLY_CHR:
+		        if ( nwildcards > 0 ) {
+			    chrcat(wildcards[nwildcards-1], *in);
+			}
+			continue;
+
+	            case 'n':
+		        chrcat(name, *in);
+			continue;
+
+	            case 'w':
+			chrcat(wildprefix, *in);
+		        for ( t=0; t<nwildcards; t++ ) {
+			    chrcat(wildcards[t], *in);
+			}
+			continue;
+	        }
+		break;
+	}
+    }
+}
+
+// SET 'CURRENTLY SELECTED FILTER'
+void FNFC_CLASS::filter_value(int i) {
+    _ofn.nFilterIndex = i + 1;
+}
+
+// RETURN VALUE OF 'CURRENTLY SELECTED FILTER'
+int FNFC_CLASS::filter_value() const {
+    return(_ofn.nFilterIndex ? _ofn.nFilterIndex-1 : _nfilters+1);
+}
+
+// PRESET FILENAME FOR 'SAVE AS' CHOOSER
+void FNFC_CLASS::preset_file(const char* val) {
+    _preset_file = strfree(_preset_file);
+    _preset_file = strnew(val);
+}
+
+// GET PRESET FILENAME FOR 'SAVE AS' CHOOSER
+const char* FNFC_CLASS::preset_file() const {
+    return(_preset_file);
+}
diff --git a/contrib/NativeFileChooser/Makefile b/contrib/NativeFileChooser/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..e94f12909b868b63bd0efb83d6ec391a4f2eb577
--- /dev/null
+++ b/contrib/NativeFileChooser/Makefile
@@ -0,0 +1,51 @@
+# $Id: Makefile,v 1.1 2008-01-07 22:59:29 geuzaine Exp $
+#
+# Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+# 
+# Please report all bugs and problems to <gmsh@geuz.org>.
+
+include ../../variables
+
+LIB     = ../../lib/libGmshNativeFileChooser.a
+INCLUDE = -I.
+CFLAGS  = ${OPTIM} ${FLAGS} ${INCLUDE} -DFLTK1
+
+SRC = Fl_Native_File_Chooser.cxx
+OBJ = ${SRC:.cxx=.o}
+
+.SUFFIXES: .o .cxx
+
+${LIB}: ${OBJ} 
+	${AR} ${LIB} ${OBJ} 
+	${RANLIB} ${LIB}
+
+.cxx.o:
+	${CXX} ${CFLAGS} -c $<
+
+clean:
+	rm -f *.o
+
+depend:
+	(sed '/^# DO NOT DELETE THIS LINE/q' Makefile && \
+	${CXX} -MM ${CFLAGS} ${SRC} \
+	) >Makefile.new
+	cp Makefile Makefile.bak
+	cp Makefile.new Makefile
+	rm -f Makefile.new
+
+# DO NOT DELETE THIS LINE
diff --git a/contrib/NativeFileChooser/README.txt b/contrib/NativeFileChooser/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..fc9da1a370bfa27b116c13028283afd041fa4450
--- /dev/null
+++ b/contrib/NativeFileChooser/README.txt
@@ -0,0 +1,119 @@
+Fl_Native_File_Chooser -- Access platform's native file choosers in FLTK
+------------------------------------------------------------------------
+
+
+WHAT IS "Fl_Native_File_Chooser"?
+=================================
+
+    Fl_Native_File_Chooser is a 'widget' wrapper to access the
+    different platform's native file choosers. On platforms that
+    don't have a 'native' file chooser (linux), we use FLTK's own.
+
+    The purpose of this library is to make a consistent interface
+    for accessing the different native file choosers.
+
+    Tested under Linux, Mac OSX and Windows with fltk 1.1.6.
+    Tested under Linux with fltk 2.x.
+
+
+LICENSING
+=========
+
+    Fl_Native_File_Chooser comes with complete free source code. 
+    Fl_Native_File_Chooser is available under the terms of the 
+    GNU Library General Public License. See COPYING for more info.
+
+    Yes, it can be used in commercial software! Free! Imagine that.
+
+
+BUILD INSTRUCTIONS
+==================
+
+    1. Which version of FLTK?
+
+    Fl_Native_File_Chooser now supports fltk1 and fltk2 as of 0.83e.
+
+    Edit the Makefile and uncomment/modify the FLTKCONFIG and FLTK2CONFIG
+    variables as needed.
+    
+    If both variables are uncommented, both versions of
+    Fl_Native_File_Chooser will be built.
+
+    For instance, if you have both fltk1 and fltk2 installed on your
+    system, the top of your Makefile settings might look like:
+
+FLTKCONFIG=/usr/local/src/fltk-1.1.x-svn/fltk-config
+FLTK2CONFIG=/usr/local/src/fltk-2.0-svn/fltk2-config
+    
+    Then you can build both with just:
+
+	make
+
+   These test programs are created, depending on if you have
+   configured the above for fltk1, fltk2, or both:
+
+       	./test-browser            -- fltk1 exerciser demo
+	./simple-app              -- fltk1 simple app
+
+       	./test-browser-fltk2      -- fltk2 exerciser demo
+	./simple-app-fltk2        -- fltk2 simple app
+
+   Originally Fl_Native_File_Chooser was designed for FLTK1, 
+   so there may be some left over FLTK1 specific references
+   in the docs. Please report these as bugs (see below)
+
+
+PLATFORM SPECIFIC NOTES
+=======================
+
+   For linux and osx the default compilers are used.
+
+   For Windows, tested with VS Express 8 + make.bat / Makefile.MICROSOFT.
+   Ian confirmed it compiled OK under Windows with mingw using the default
+   unix Makefile.
+
+
+WHERE'S THE DOCUMENTATION?
+==========================
+
+    ./documentation/index.html
+
+
+HOW DO I LINK Fl_Native_File_Chooser INTO MY OWN APPLICATION?
+=============================================================
+
+    ./documentation/how-to-use.html
+
+
+FILE LAYOUT
+===========
+
+    ./Makefile                 -- main Makefile for unix builds
+    ./Makefile.MICROSOFT       -- main Makefile for native Microsoft builds
+
+    ./documentation/index.html -- public documentation for fltk1 + fltk2
+
+    ./FL                       \__ fltk1 include files and lib
+    ./Fl_Native_File_Chooser.o /   (for your app to include and link)
+
+    ./fltk                     \__ fltk2 include files and lib
+    ./NativeFileChooser.o      /   (for your app to include and link)
+
+    ./reference                 -- project's reference docs (internal use)
+
+    *_FLTK.{cxx,H,h}            -- Platforms that don't have native choosers
+    *_MAC.{cxx,H,h}             -- Mac platform specific source code
+    *_WIN32.{cxx,H,h}           -- Windows platform specific source code
+
+
+RELEASE NOTES/VERSION INFORMATION
+=================================
+    
+    See ./CHANGES.
+
+
+BUGS? FEATURE REQUESTS?
+=======================
+    
+    Send bugs and RFE's to erco at seriss dot com
+
diff --git a/contrib/NativeFileChooser/TODO b/contrib/NativeFileChooser/TODO
new file mode 100644
index 0000000000000000000000000000000000000000..93558f08603e79f46047295227c5b27a1ef01b50
--- /dev/null
+++ b/contrib/NativeFileChooser/TODO
@@ -0,0 +1,190 @@
+> Determine why Mac and OSX don't open browser with preset file selected.
+  WINDOWS: tried to make this work, but it just doesn't support it!
+           Even calling GetOpenFileName(&_ofn); twice in a row.
+
+> 0.84: Ian MacArthur indicated mingw warns about strapp and strdump
+	being "defined but not used" cause it's a static. Should
+	probably make a lib, disable this warning, or reference 
+	the calls in an unused subroutine.
+
+> 0.83d: Namespace pollution: Yuri wants Carbon.h/win32.h
+  to not be in the public .H files.  Can probably make an 'underbar'
+  version of the class to isolate them.  See erco's post on 
+  fltk.general 06/24/07.
+
+> 0.83d: MAC / Save File:
+  If:
+      1) /tmp/foo.xxx exists
+      2) Directory: set to /tmp
+      3) Preset File set to foo.xxx
+  ..when browser opens, foo.xxx is GRAYED OUT, even though filter
+  appears to be on. Can still click on grayed out items to pick them,
+  and Save As: name changes. Weird!
+  Looks OK when 'Single File' is selected.
+
+(?) > 0.83d: WINDOWS/FILE BROWSE: 
+(?) 	If simple-app's preset filename doesn't end in a backslash,
+(?)     browser shows contents of parent dir, not dir itself.
+(?) 	Maybe append a slash if stat() shows preset filename is a DIR?
+
+-- 0.82c --
+
+
+(?) > 0.82c: Windows "Save As" is not setting correct directory in browser
+
+
+(?) > 0.82: Andreas reports problem with Mac chooser not showing thumbnails
+(?)         that live on remote drives even though the Finder does. 
+(?)         Files located on the local file system show up OK.
+(?)         (See Reference #1 below for Apple's SimpleText.c excerpts?)
+(?)         Also, see Andreas' email 12/05/2005 (Reference #2 below)
+
+(?) > 0.82: Presetting value() under linux causes chooser to open with file 
+(?)         highlighted in the chooser, but not in windows or mac.
+
+(?) > 0.82: Fl_Native_File_Chooser: WINDOWS doesn't handle returning UTF8 from
+(?)         native windows file chooser.. comes back as garbage, possibly as non-UTF8?
+(?)         (Found problem on Japanese localized machine by browsing to a dir
+(?)         with Japanese chars. Shows OK in windows browser, but when returned
+(?)         to Fl_Input, comes up as garbage, even though the Fl_Input is capable
+(?)         of showing text correctly if japanese text pasted as text into the 
+(?)         Fl_Input from Windows URL input)
+
+*** DONE ***
+(DONE) > 0.82c: "Save As" + "Show Confirm Dialog" is not showing the confirm dialog..!
+(DONE)          TESTED ON LINUX AND OSX TO WORK OK.
+
+(DONE) > 0.83c: Shane Hill on 02/07/06 reports that under Windows, doing regular
+(DONE)   file browsing results in the current working dir being changed.
+(DONE)   Luckily there appears to be a WIN32 flag for this, but the docs
+(DONE)   say it's ineffective..!?
+(DONE)     OFN_NOCHANGEDIR
+(DONE) 	Restores the current directory to its original value if the user changed
+(DONE) 	the directory while searching for files.
+(DONE) 	Windows NT 4.0/2000/XP: This flag is ineffective for GetOpenFileName.
+(DONE) 				^^^^^^^^^^^^^^^^^^^^^^^^
+
+(DONE) > 0.82: Alessandro: uses very long wildcard strings..
+(DONE)         Replace fixed arrays (char wildcard[80]) with new strapp() stuff.
+
+------------------------------------------------------------------------
+				Reference #1
+------------------------------------------------------------------------
+
+	// REFERENCE FROM SimpleText.c for erco..
+
+	short		numTypes;
+	OSType		typeList[20];
+	OSType		fileType = '\?\?\?\?';
+	NavDialogRef	navDialog;
+
+	DetermineWindowTypeOrOpen( nil, fileType, &typeList[0], &numTypes, nil );
+	
+	// Open as many documents as the user wishes through Appleevents
+	return OpenFileDialog( 'ttxt', numTypes, typeList, &navDialog );
+
+	    OSType	typeList[20];
+	    OSType	docList[20];
+
+		    pFileTypes[*numTypes]	= 'MooV';
+		    pDocumentTypes[*numTypes] 	= kMovieWindow;
+		    (*numTypes)++;
+
+
+OSStatus OpenFileDialog(
+	OSType applicationSignature, 
+	short numTypes, 
+	OSType typeList[], 
+	NavDialogRef *outDialog )
+{
+	OSStatus theErr = noErr;
+	if ( gOpenFileDialog == NULL )
+	{
+		NavDialogCreationOptions	dialogOptions;
+		NavTypeListHandle		openList = NULL;
+	
+		NavGetDefaultDialogCreationOptions( &dialogOptions );
+	
+		dialogOptions.modality = kWindowModalityNone;
+		dialogOptions.clientName = CFStringCreateWithPascalString( 
+						NULL, LMGetCurApName(), GetApplicationTextEncoding());
+		
+		openList = (NavTypeListHandle)NewOpenHandle( applicationSignature, numTypes, typeList );
+		
+		theErr = NavCreateGetFileDialog( &dialogOptions, openList,
+		                                 GetPrivateEventUPP(),
+						 NULL, NULL, NULL, &gOpenFileDialog );
+
+------------------------------------------------------------------------
+				Reference #2
+------------------------------------------------------------------------
+
+Andreas Schömann wrote:
+> Greg Ercolano wrote:
+>
+>> Andreas Schömann wrote:
+>>
+>>> I've found a problem: when loading images (jpg) via network, no thumbnail is shown in the file chooser. Actual loading works. The network device is NTFS formatted. I thought it might be an access rights problem, but with 'Finder' it works fine...
+
+    BTW, Andreas is specifically referring to the MAC file browser;
+    when you have it in 'column' mode, when you highlight eg. a jpg
+    image, the preview that normally displays off to the right
+    doesn't show up.
+
+    I looked at the SimpleText.c code that comes with the OSX
+    developer toolkit, ie:
+    /Developer//Examples/Carbon/SimpleText/*
+
+    ..and it looks like they use a few options to NavCreateGetFileDialog()
+    that I don't use, namely arg2 and arg3 to set a list of files
+    and a callback.
+
+    I have to admit I don't fully understand the Mac stuff when it
+    comes to this sort of thing. Apparently there's a global database
+    somewhere of 4 character file types that dates back to the 1980's,
+    and it appears one needs to know these names and hard code them
+    into your app (as is done in SimpleText.cxx).
+
+    I think I'll leave this unfinished, since it's not really a show
+    stopper, and I'm not sure how to make it work correctly.
+
+> 4) Here on my machine Fl_Native_File_Chooser displays a preview for _local_ images (e.g. .jpeg, .tiff and .png) 
+
+    Really?
+
+    I actually couldn't get that to work on my 10.4.3 box.
+
+    When I single click on a jpeg, png, or other image format,
+    it shows a generic image, but the correct text info about
+    the image's file type.
+
+    What does work is if I click on .c or .cxx files it shows
+    correctly, and if I click on a .rm file (Real Media),
+    it shows Real's icon logo.. (shrug)
+
+    In the Finder, when you click on images, it shows a thumbnail
+    of the actual image.
+
+> Hmmmh, somewhat confusing results...
+> Especially the different behaviour of Finder and File Chooser is a mystery to me. Why did Apple do that? Maybe this has changed with Tiger?
+> 1) and 2) tell me that one can disable file preview with 'Navigation Services', though probably not by intention.
+
+    It might be I'm missing some args to NavCreateGetFileDialog()
+    (arg2 and 3?) Unfortunately I'm not sure what is the correct
+    code to make that work, if that's even the cause.
+
+    Or maybe I need to link in some apple framework that's missing
+    to make that stuff work.
+
+> I also had a look into the documentation ( http://developer.apple.com/documentation/Carbon/Conceptual/ProvidingNavigationDialogs/index.html ) and it says that 'Navigation Services' offers to specify a 'preview callback' with 'NavCreateGetFileDialog'. This is called when the user selects a file and offers a way to preview custom file types. But Fl_Native_File_Chooser does not use this feature and in that case 'Navigation Services' inspects the file.
+
+    Right, as described above.
+    However, I'd think there'd be defaults for things like jpeg/png/etc.
+
+    I'd hate to think I have to manually provide callbacks for each
+    image type..!
+
+------------------------------------------------------------------------
+				Reference #3
+------------------------------------------------------------------------
+
diff --git a/contrib/NativeFileChooser/common.cxx b/contrib/NativeFileChooser/common.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..efde4875fd410f7d65bdcdbcc32462136ca61d6a
--- /dev/null
+++ b/contrib/NativeFileChooser/common.cxx
@@ -0,0 +1,78 @@
+//
+// common.cxx -- common string subs for Fl_Native_File_Chooser
+//
+// Copyright 2004 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.
+//
+// Please keep code 80 column compliant.
+//
+//      10        20        30        40        50        60        70
+//       |         |         |         |         |         |         |
+// 4567890123456789012345678901234567890123456789012345678901234567890123456789
+//
+
+#include <string.h>
+
+// COPY A STRING WITH 'new'
+//    Value can be NULL
+//
+static char *strnew(const char *val) {
+    if ( val == NULL ) return(NULL);
+    char *s = new char[strlen(val)+1];
+    strcpy(s, val);
+    return(s);
+}
+
+// FREE STRING CREATED WITH strnew(), NULLS OUT STRING
+//    Value can be NULL
+//
+static char *strfree(char *val) {
+    if ( val ) delete [] val;
+    return(NULL);
+}
+
+// 'DYNAMICALLY' APPEND ONE STRING TO ANOTHER
+//    Returns newly allocated string, or NULL 
+//    if s && val == NULL.
+//    's' can be NULL; returns a strnew(val).
+//    'val' can be NULL; s is returned unmodified.
+//
+//    Usage:
+//	char *s = strnew("foo");	// s = "foo"
+//      s = strapp(s, "bar");		// s = "foobar"
+//
+static char *strapp(char *s, const char *val) {
+    if ( ! val ) {
+        return(s);              // Nothing to append? return s
+    }
+    if ( ! s ) {
+        return(strnew(val));    // New string? return copy of val
+    }
+    char *news = new char[strlen(s)+strlen(val)+1];
+    strcpy(news, s);
+    strcat(news, val);
+    delete [] s;		// delete old string
+    return(news);		// return new copy
+}
+
+// APPEND A CHARACTER TO A STRING
+//     This does NOT allocate space for the new character.
+//
+static void chrcat(char *s, char c) {
+    char tmp[2] = { c, '\0' };
+    strcat(s, tmp);
+}