From fa67aafa9d0c169daf38bc76cef6be3a6ea80d50 Mon Sep 17 00:00:00 2001 From: Manolo Gouy Date: Tue, 5 Apr 2016 11:25:35 +0000 Subject: [PATCH] Rewrite the Fl_File_Native_Chooser class under the driver model. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11529 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- FL/Fl_Native_File_Chooser.H | 288 +++++++++---------------- src/CMakeLists.txt | 17 +- src/Fl_Native_File_Chooser.cxx | 310 +++++++++++++++++++++++++-- src/Fl_Native_File_Chooser_FLTK.cxx | 255 +++------------------- src/Fl_Native_File_Chooser_GTK.cxx | 109 ++++++++-- src/Fl_Native_File_Chooser_MAC.mm | 161 +++++++++----- src/Fl_Native_File_Chooser_WIN32.cxx | 191 +++++++++++------ src/Makefile | 33 +-- src/makedepend | 1 - 9 files changed, 787 insertions(+), 578 deletions(-) diff --git a/FL/Fl_Native_File_Chooser.H b/FL/Fl_Native_File_Chooser.H index e89a00a7d..140298747 100644 --- a/FL/Fl_Native_File_Chooser.H +++ b/FL/Fl_Native_File_Chooser.H @@ -3,7 +3,7 @@ // // FLTK native OS file chooser widget // -// Copyright 1998-2014 by Bill Spitzak and others. +// Copyright 1998-2016 by Bill Spitzak and others. // Copyright 2004 Greg Ercolano. // // This library is free software. Distribution and use rights are outlined in @@ -20,42 +20,41 @@ /** \file Fl_Native_File_Chooser widget. */ +/* Implementation note: + + class Fl_Native_File_Chooser <== public API used by applications + + class Fl_Native_File_Chooser_Driver <== virtual API that a platform may implement + this API has a do-nothing default implementation + + class Fl_Native_File_Chooser_FLTK_Driver <== this API implementation is the default FLTK file chooser + class Fl_Native_File_Chooser_GTK_Driver <== this API implementation runs a GTK file chooser + it is determined at run-time if the GTK dynamic libraries are available + + class Fl_Native_File_Chooser_Darwin_Driver <== this API implementation runs a Mac OS X file chooser + + class Fl_Native_File_Chooser_WinAPI_Driver <== this API implementation runs a MSWindows file chooser + + + Each platform must implement the constructor of the Fl_Native_File_Chooser class. + This particular implementation: + + Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { + platform_fnfc = new Fl_Native_File_Chooser_FLTK_Driver(val); + } + + can be used by any platform. + No more code is required. The cross-platform Fl_Native_File_Chooser_FLTK.cxx file must be compiled in libfltk, + and the default FLTK file chooser will be used. + */ + #ifndef FL_NATIVE_FILE_CHOOSER_H #define FL_NATIVE_FILE_CHOOSER_H -// Use Windows' chooser -#ifdef WIN32 +#include +#include -// #define _WIN32_WINNT 0x0501 // needed for OPENFILENAME's 'FlagsEx' -#if defined(FL_LIBRARY) -# include -# include // OPENFILENAMEW, GetOpenFileName() -# include // BROWSEINFOW, SHBrowseForFolder() -typedef OPENFILENAMEW fl_OPENFILENAMEW; -typedef BROWSEINFOW fl_BROWSEINFOW; -#else -typedef void fl_OPENFILENAMEW; -typedef void fl_BROWSEINFOW; -#endif -# include // FL_EXPORT - -// Use Apple's chooser -#elif defined(__APPLE__) // PORTME: Fl_Screen_Driver - native file chooser support -# define MAXFILTERS 80 -# include // FL_EXPORT - -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: define a file chooser if one is available on your platform" -# include // default to FLTK file chooser if none id ported - -// All else falls back to FLTK's own chooser -#else -# include - -#endif - -class Fl_FLTK_File_Chooser; -class Fl_GTK_File_Chooser; +class Fl_Native_File_Chooser_Driver; /** This class lets an FLTK application easily and consistently access @@ -113,6 +112,8 @@ class Fl_GTK_File_Chooser; */ class FL_EXPORT Fl_Native_File_Chooser { +private: + Fl_Native_File_Chooser_Driver *platform_fnfc; public: enum Type { BROWSE_FILE = 0, ///< browse files (lets user choose one file) @@ -129,14 +130,15 @@ public: PREVIEW = 0x0004, ///< enable preview mode (if supported) USE_FILTER_EXT = 0x0008 ///< Chooser filter pilots the output file extension (if supported) }; - /** Localizable message */ static const char *file_exists_message; -public: - Fl_Native_File_Chooser(int val=BROWSE_FILE); + /** + The constructor. Internally allocates the native widgets. + Optional \p val presets the type of browser this will be, + which can also be changed with type(). + */ + Fl_Native_File_Chooser(int val = BROWSE_FILE); // each platorm implements it ~Fl_Native_File_Chooser(); - - // Public methods void type(int t); int type() const ; void options(int o); @@ -157,95 +159,46 @@ public: const char* preset_file() const; const char *errmsg() const ; int show() ; - -#ifdef WIN32 -private: - int _btype; // kind-of browser to show() - int _options; // general options - fl_OPENFILENAMEW *_ofn_ptr; // GetOpenFileName() & GetSaveFileName() struct - fl_BROWSEINFOW *_binf_ptr; // 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 ClearOFN(); - void ClearBINF(); - void Win2Unix(char *s); - void Unix2Win(char *s); - int showfile(); - int showdir(); - - void parse_filter(const char *); - void clear_filters(); - void add_filter(const char *, const char *); - -#elif defined(__APPLE__) // PORTME: Fl_Screen_Driver - native file chooser support -private: - int _btype; // kind-of browser to show() - int _options; // general options - void *_panel; - 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 methods - void errmsg(const char *msg); - void clear_pathnames(); - void set_single_pathname(const char *s); - int get_saveas_basename(void); - void clear_filters(); - void parse_filter(const char *from); - int post(); - int runmodal(); - -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: define member variables for file chooser if one is available on your platform" - -#else - -private: - static int have_looked_for_GTK_libs; - union { - Fl_FLTK_File_Chooser *_x11_file_chooser; - Fl_GTK_File_Chooser *_gtk_file_chooser; }; -#endif + + +class Fl_Native_File_Chooser_Driver { +protected: + static void chrcat(char *s, char c); + static char *strapp(char *s, const char *val); + static char *strfree(char *val); + static char *strnew(const char *val); +public: + Fl_Native_File_Chooser_Driver(int val) {} + virtual ~Fl_Native_File_Chooser_Driver() {} + virtual void type(int t) {} + virtual int type() const {return 0;} + virtual void options(int o) {} + virtual int options() const {return 0;} + virtual int count() const {return 0;} + virtual const char *filename() const {return 0;} + virtual const char *filename(int i) const {return 0;} + virtual void directory(const char *val) {} + virtual const char *directory() const {return 0;} + virtual void title(const char *t) {} + virtual const char* title() const {return 0;} + virtual const char *filter() const {return 0;} + virtual void filter(const char *f) {} + virtual int filters() const {return 0;} + virtual void filter_value(int i) {} + virtual int filter_value() const {return 0;} + virtual void preset_file(const char*f) {} + virtual const char* preset_file() const {return 0;} + virtual const char *errmsg() const {return 0;} + virtual int show() {return 1;} }; - -#if !defined(__APPLE__) && !defined(WIN32) && !defined(FL_PORTING) // PORTME: Fl_Screen_Driver - FLTK file chooser option -class FL_EXPORT Fl_FLTK_File_Chooser { - friend class Fl_Native_File_Chooser; +class Fl_Native_File_Chooser_FLTK_Driver : public Fl_Native_File_Chooser_Driver { +private: + void errmsg(const char *msg); + int type_fl_file(int val); + int exist_dialog(); + void parse_filter(); protected: int _btype; // kind-of browser to show() int _options; // general options @@ -257,78 +210,33 @@ protected: char *_prevvalue; // Returned filename char *_directory; char *_errmsg; // error message - Fl_FLTK_File_Chooser(int val); - virtual ~Fl_FLTK_File_Chooser(); - void errmsg(const char *msg); - int type_fl_file(int); - void parse_filter(); - int exist_dialog(); Fl_File_Chooser *_file_chooser; - virtual void type(int); - int type() const; - void options(int); - int options() const; +public: + Fl_Native_File_Chooser_FLTK_Driver(int val); + virtual ~Fl_Native_File_Chooser_FLTK_Driver(); + virtual void type(int t); + virtual int type() const ; + virtual void options(int o); + virtual int options() const; virtual int count() const; - virtual const char *filename() const; - virtual const char *filename(int i) const; - void directory(const char *val); - const char *directory() const; - virtual void title(const char *); + virtual const char *filename() const ; + virtual const char *filename(int i) const ; + virtual void directory(const char *val) ; + virtual const char *directory() const; + virtual void title(const char *t); virtual const char* title() const; - const char *filter() const; - void filter(const char *); - int filters() const; - void filter_value(int i); - int filter_value() const; - void preset_file(const char*); - const char* preset_file() const; - const char *errmsg() const; - virtual int show(); + virtual const char *filter() const ; + virtual void filter(const char *f); + virtual int filters() const ; + virtual void filter_value(int i) ; + virtual int filter_value() const ; + virtual void preset_file(const char*f) ; + virtual const char* preset_file() const; + virtual const char *errmsg() const ; + virtual int show() ; }; -class FL_EXPORT Fl_GTK_File_Chooser : public Fl_FLTK_File_Chooser { - friend class Fl_Native_File_Chooser; -private: - typedef struct _GtkWidget GtkWidget; - typedef struct _GtkFileFilterInfo GtkFileFilterInfo; - struct pair { - Fl_GTK_File_Chooser* running; // the running Fl_GTK_File_Chooser - const char *filter; // a filter string of the chooser - pair(Fl_GTK_File_Chooser* c, const char *f) { - running = c; - filter = strdup(f); - }; - ~pair() { - free((char*)filter); - }; - }; - GtkWidget *gtkw_ptr; // used to hold a GtkWidget* without pulling GTK into everything... - void *gtkw_slist; // used to hold a GLib GSList... - unsigned gtkw_count; // number of files read back - if any - mutable char *gtkw_filename; // last name we read back - char *gtkw_title; // the title to be applied to the dialog - const char *previous_filter; - - int fl_gtk_chooser_wrapper(); // method that wraps the GTK widget - Fl_GTK_File_Chooser(int val); - virtual ~Fl_GTK_File_Chooser(); - static int did_find_GTK_libs; - static void probe_for_GTK_libs(void); - virtual void type(int); - virtual int count() const; - virtual const char *filename() const; - virtual const char *filename(int i) const; - virtual void title(const char *); - virtual const char* title() const; - virtual int show(); - void changed_output_type(const char *filter); - - static int custom_gtk_filter_function(const GtkFileFilterInfo*, Fl_GTK_File_Chooser::pair*); - static void free_pair(pair *p); -}; -#endif // !defined(__APPLE__) && !defined(WIN32) // PORTME: Fl_Screen_Driver - native file chooser option - #endif /*FL_NATIVE_FILE_CHOOSER_H*/ // diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 946c4264b..2bdedcaa6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -185,6 +185,8 @@ if (USE_X11) drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx Fl_x.cxx fl_dnd_x.cxx + Fl_Native_File_Chooser_FLTK.cxx + Fl_Native_File_Chooser_GTK.cxx ) if (USE_XFT) set (DRIVER_FILES ${DRIVER_FILES} @@ -280,6 +282,7 @@ else () drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx Fl_win32.cxx fl_dnd_win32.cxx + Fl_Native_File_Chooser_WIN32.cxx ) set (DRIVER_HEADER_FILES drivers/WinAPI/Fl_WinAPI_System_Driver.H @@ -367,12 +370,18 @@ set (CFILES xutf8/is_right2left.c xutf8/is_spacing.c xutf8/case.c - xutf8/utf8Input.c - xutf8/utf8Utils.c - xutf8/utf8Wrap.c - xutf8/keysym2Ucs.c ) +if (USE_X11) + set (CFILES + ${CFILES} + xutf8/utf8Input.c + xutf8/utf8Utils.c + xutf8/utf8Wrap.c + xutf8/keysym2Ucs.c + ) +endif (USE_X11) + if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL)) set (MMFILES Fl_cocoa.mm diff --git a/src/Fl_Native_File_Chooser.cxx b/src/Fl_Native_File_Chooser.cxx index 8b7c46673..676fa858f 100644 --- a/src/Fl_Native_File_Chooser.cxx +++ b/src/Fl_Native_File_Chooser.cxx @@ -2,7 +2,7 @@ // // FLTK native OS file chooser widget // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2016 by Bill Spitzak and others. // Copyright 2004 Greg Ercolano. // // This library is free software. Distribution and use rights are outlined in @@ -16,25 +16,309 @@ // http://www.fltk.org/str.php // -// Use Windows' chooser -#ifdef WIN32 -#include "Fl_Native_File_Chooser_WIN32.cxx" -// Use Apple's chooser -#elif defined(__APPLE__) // PORTME: Fl_Screen_Driver - native file chooser #include -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement the native file chooser interface" -# include "Fl_Native_File_Chooser_FLTK.cxx" - -// All else falls back to FLTK's own chooser -#else -#include "Fl_Native_File_Chooser_FLTK.cxx" +#ifdef FL_PORTING +# pragma message "Implement a native file chooser (see Fl_Native_File_Chooser_Driver), or use FLTK's chooser" +Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { + platform_fnfc = new Fl_Native_File_Chooser_FLTK_Driver(val); +} #endif +/** Localizable message */ const char *Fl_Native_File_Chooser::file_exists_message = "File exists. Are you sure you want to overwrite?"; +/** + Destructor. + Deallocates any resources allocated to this widget. + */ +Fl_Native_File_Chooser::~Fl_Native_File_Chooser() +{ + delete platform_fnfc; +} + + +/** + Sets the current Fl_Native_File_Chooser::Type of browser. + */ +void Fl_Native_File_Chooser::type(int t) +{ + platform_fnfc->type(t); +} + +/** + Gets the current Fl_Native_File_Chooser::Type of browser. + */ +int Fl_Native_File_Chooser::type() const +{ + return platform_fnfc->type(); +} + +/** + Sets the platform specific chooser options to \p val. + \p val is expected to be one or more Fl_Native_File_Chooser::Option flags ORed together. + Some platforms have OS-specific functions that can be enabled/disabled via this method. +

+ \code + Flag Description Win Mac Other + -------------- ----------------------------------------------- ------- ------- ------- + NEW_FOLDER Shows the 'New Folder' button. Ignored Used Used + PREVIEW Enables the 'Preview' mode by default. Ignored Ignored Used + SAVEAS_CONFIRM Confirm dialog if BROWSE_SAVE_FILE file exists. Used Used Used + USE_FILTER_EXT Chooser filter pilots the output file extension. Ignored Used Used (GTK) + \endcode + */ +void Fl_Native_File_Chooser::options(int o) +{ + platform_fnfc->options(o); +} + +/** + Gets the platform specific Fl_Native_File_Chooser::Option flags. + */ +int Fl_Native_File_Chooser::options() const +{ + return platform_fnfc->options(); +} + +/** + Returns the number of filenames (or directory names) the user selected. +

+ \b Example: + \code + if ( fnfc->show() == 0 ) { + // Print all filenames user selected + for (int n=0; ncount(); n++ ) { + printf("%d) '%s'\n", n, fnfc->filename(n)); + } + } + \endcode + */ +int Fl_Native_File_Chooser::count() const +{ + return platform_fnfc->count(); +} + +/** + Return the filename the user chose. + Use this if only expecting a single filename. + If more than one filename is expected, use filename(int) instead. + Return value may be "" if no filename was chosen (eg. user cancelled). + */ +const char *Fl_Native_File_Chooser::filename() const +{ + return platform_fnfc->filename(); +} + +/** + Return one of the filenames the user selected. + Use count() to determine how many filenames the user selected. +

+ \b Example: + \code + if ( fnfc->show() == 0 ) { + // Print all filenames user selected + for (int n=0; ncount(); n++ ) { + printf("%d) '%s'\n", n, fnfc->filename(n)); + } + } + \endcode + */ +const char *Fl_Native_File_Chooser::filename(int i) const +{ + return platform_fnfc->filename(i); +} + +/** + Preset the directory the browser will show when opened. + If \p val is NULL, or no directory is specified, the chooser will attempt + to use the last non-cancelled folder. + */ +void Fl_Native_File_Chooser::directory(const char *val) +{ + platform_fnfc->directory(val); +} + +/** + Returns the current preset directory() value. + */ +const char *Fl_Native_File_Chooser::directory() const +{ + return platform_fnfc->directory(); +} + +/** + Set the title of the file chooser's dialog window. + Can be NULL if no title desired. + The default title varies according to the platform, so you are advised to set the title explicitly. + */ +void Fl_Native_File_Chooser::title(const char *t) +{ + platform_fnfc->title(t); +} + +/** + Get the title of the file chooser's dialog window. + Return value may be NULL if no title was set. + */ +const char* Fl_Native_File_Chooser::title() const +{ + return platform_fnfc->title(); +} + +/** + Returns the filter string last set. + Can be NULL if no filter was set. + */ +const char *Fl_Native_File_Chooser::filter() const +{ + return platform_fnfc->filter(); +} + +/** + Sets the filename filters used for browsing. + The default is NULL, which browses all files. +

+ The filter string can be any of: +

+ - A single wildcard (eg. "*.txt") + - Multiple wildcards (eg. "*.{cxx,h,H}") + - A descriptive name followed by a "\t" and a wildcard (eg. "Text Files\t*.txt") + - A list of separate wildcards with a "\n" between each (eg. "*.{cxx,H}\n*.txt") + - A list of descriptive names and wildcards (eg. "C++ Files\t*.{cxx,H}\nTxt Files\t*.txt") +

+ The format of each filter is a wildcard, or an optional user description + followed by '\\t' and the wildcard. +

+ On most platforms, each filter is available to the user via a pulldown menu + in the file chooser. The 'All Files' option is always available to the user. + */ +void Fl_Native_File_Chooser::filter(const char *f) +{ + platform_fnfc->filter(f); +} + +/** + Gets how many filters were available, not including "All Files" + */ +int Fl_Native_File_Chooser::filters() const +{ + return platform_fnfc->filters(); +} + +/** + Sets which filter will be initially selected. + + The first filter is indexed as 0. + If filter_value()==filters(), then "All Files" was chosen. + If filter_value() > filters(), then a custom filter was set. + */ +void Fl_Native_File_Chooser::filter_value(int i) +{ + platform_fnfc->filter_value(i); +} + +/** + Returns which filter value was last selected by the user. + This is only valid if the chooser returns success. + */ +int Fl_Native_File_Chooser::filter_value() const +{ + return platform_fnfc->filters(); +} + +/** + Sets the default filename for the chooser. + Use directory() to set the default directory. + Mainly used to preset the filename for save dialogs, + and on most platforms can be used for opening files as well. + */ +void Fl_Native_File_Chooser::preset_file(const char*f) +{ + platform_fnfc->preset_file(f); +} + +/** + Get the preset filename. + */ +const char* Fl_Native_File_Chooser::preset_file() const +{ + return platform_fnfc->preset_file(); +} + +/** + Returns a system dependent error message for the last method that failed. + This message should at least be flagged to the user in a dialog box, or to some kind of error log. + Contents will be valid only for methods that document errmsg() will have info on failures. + */ +const char *Fl_Native_File_Chooser::errmsg() const +{ + return platform_fnfc->errmsg(); +} + +/** + Post the chooser's dialog. Blocks until dialog has been completed or cancelled. + \returns + - 0 -- user picked a file + - 1 -- user cancelled + - -1 -- failed; errmsg() has reason + */ +int Fl_Native_File_Chooser::show() +{ + return platform_fnfc->show(); +} + +// COPY A STRING WITH 'new' +// Value can be NULL +// +char *Fl_Native_File_Chooser_Driver::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 +// +char *Fl_Native_File_Chooser_Driver::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" +// +char *Fl_Native_File_Chooser_Driver::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. +// +void Fl_Native_File_Chooser_Driver::chrcat(char *s, char c) { + char tmp[2] = { c, '\0' }; + strcat(s, tmp); +} + // // End of "$Id$". // diff --git a/src/Fl_Native_File_Chooser_FLTK.cxx b/src/Fl_Native_File_Chooser_FLTK.cxx index c72ee74d0..5c3727134 100644 --- a/src/Fl_Native_File_Chooser_FLTK.cxx +++ b/src/Fl_Native_File_Chooser_FLTK.cxx @@ -16,216 +16,21 @@ // http://www.fltk.org/str.php // -#include #include +#include #include #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 -#include "Fl_Native_File_Chooser_common.cxx" -#include "Fl_Native_File_Chooser_GTK.cxx" - #include #include -#if defined(FL_PORTING) -# pragma message "FL_PORTING: implement Fl_Native_File_Chooser" -int Fl_Native_File_Chooser::show() { return 0; } -void Fl_Native_File_Chooser::type(int t) { } -void Fl_Native_File_Chooser::title(const char *t) { } -void Fl_Native_File_Chooser::filter(const char *f) { } -void Fl_Native_File_Chooser::options(int val) { } -const char *Fl_Native_File_Chooser::filename() const { return 0; } -Fl_Native_File_Chooser::Fl_Native_File_Chooser(int) { } -Fl_Native_File_Chooser::~Fl_Native_File_Chooser() { } -#else - -int Fl_Native_File_Chooser::have_looked_for_GTK_libs = 0; - -/** - The constructor. Internally allocates the native widgets. - Optional \p val presets the type of browser this will be, - which can also be changed with type(). - */ -Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { - if (have_looked_for_GTK_libs == 0) { - // First Time here, try to find the GTK libs if they are installed -#if HAVE_DLSYM && HAVE_DLFCN_H - if (Fl::option(Fl::OPTION_FNFC_USES_GTK)) { - Fl_GTK_File_Chooser::probe_for_GTK_libs(); - } -#endif - have_looked_for_GTK_libs = -1; - } - // if we found all the GTK functions we need, we will use the GtkFileChooserDialog - if (Fl_GTK_File_Chooser::did_find_GTK_libs) _gtk_file_chooser = new Fl_GTK_File_Chooser(val); - else _x11_file_chooser = new Fl_FLTK_File_Chooser(val); -} - -/** - Destructor. - Deallocates any resources allocated to this widget. - */ -Fl_Native_File_Chooser::~Fl_Native_File_Chooser() { - delete _x11_file_chooser; -} - -/** - Sets the current Fl_Native_File_Chooser::Type of browser. - */ -void Fl_Native_File_Chooser::type(int t) { return _x11_file_chooser->type(t); } -/** - Gets the current Fl_Native_File_Chooser::Type of browser. - */ -int Fl_Native_File_Chooser::type() const { return _x11_file_chooser->type(); } -/** - Sets the platform specific chooser options to \p val. - \p val is expected to be one or more Fl_Native_File_Chooser::Option flags ORed together. - Some platforms have OS-specific functions that can be enabled/disabled via this method. -

- \code - Flag Description Win Mac Other - -------------- ----------------------------------------------- ------- ------- ------- - NEW_FOLDER Shows the 'New Folder' button. Ignored Used Used - PREVIEW Enables the 'Preview' mode by default. Ignored Ignored Used - SAVEAS_CONFIRM Confirm dialog if BROWSE_SAVE_FILE file exists. Used Used Used - USE_FILTER_EXT Chooser filter pilots the output file extension. Ignored Used Used (GTK) -\endcode - */ -void Fl_Native_File_Chooser::options(int o) { _x11_file_chooser->options(o); } -/** - Gets the platform specific Fl_Native_File_Chooser::Option flags. - */ -int Fl_Native_File_Chooser::options() const { return _x11_file_chooser->options(); } - -/** - Returns the number of filenames (or directory names) the user selected. -

- \b Example: - \code - if ( fnfc->show() == 0 ) { - // Print all filenames user selected - for (int n=0; ncount(); n++ ) { - printf("%d) '%s'\n", n, fnfc->filename(n)); - } - } - \endcode - */ -int Fl_Native_File_Chooser::count() const { return _x11_file_chooser->count(); } -/** - Return the filename the user chose. - Use this if only expecting a single filename. - If more than one filename is expected, use filename(int) instead. - Return value may be "" if no filename was chosen (eg. user cancelled). - */ -const char *Fl_Native_File_Chooser::filename() const { return _x11_file_chooser->filename(); } -/** - Return one of the filenames the user selected. - Use count() to determine how many filenames the user selected. -

- \b Example: - \code - if ( fnfc->show() == 0 ) { - // Print all filenames user selected - for (int n=0; ncount(); n++ ) { - printf("%d) '%s'\n", n, fnfc->filename(n)); - } - } - \endcode - */ -const char *Fl_Native_File_Chooser::filename(int i) const { return _x11_file_chooser->filename(i); } -/** - Preset the directory the browser will show when opened. - If \p val is NULL, or no directory is specified, the chooser will attempt - to use the last non-cancelled folder. - */ -void Fl_Native_File_Chooser::directory(const char *val) { _x11_file_chooser->directory(val); } -/** - Returns the current preset directory() value. - */ -const char *Fl_Native_File_Chooser::directory() const { return _x11_file_chooser->directory(); } -/** - Set the title of the file chooser's dialog window. - Can be NULL if no title desired. - The default title varies according to the platform, so you are advised to set the title explicitly. - */ -void Fl_Native_File_Chooser::title(const char *t) { _x11_file_chooser->title(t); } -/** - Get the title of the file chooser's dialog window. - Return value may be NULL if no title was set. - */ -const char* Fl_Native_File_Chooser::title() const { return _x11_file_chooser->title(); } -/** - Returns the filter string last set. - Can be NULL if no filter was set. - */ -const char *Fl_Native_File_Chooser::filter() const { return _x11_file_chooser->filter(); } -/** - Sets the filename filters used for browsing. - The default is NULL, which browses all files. -

- The filter string can be any of: -

- - A single wildcard (eg. "*.txt") - - Multiple wildcards (eg. "*.{cxx,h,H}") - - A descriptive name followed by a "\t" and a wildcard (eg. "Text Files\t*.txt") - - A list of separate wildcards with a "\n" between each (eg. "*.{cxx,H}\n*.txt") - - A list of descriptive names and wildcards (eg. "C++ Files\t*.{cxx,H}\nTxt Files\t*.txt") -

- The format of each filter is a wildcard, or an optional user description - followed by '\\t' and the wildcard. -

- On most platforms, each filter is available to the user via a pulldown menu - in the file chooser. The 'All Files' option is always available to the user. - */ -void Fl_Native_File_Chooser::filter(const char *f) { _x11_file_chooser->filter(f); } -/** - Gets how many filters were available, not including "All Files" - */ -int Fl_Native_File_Chooser::filters() const { return _x11_file_chooser->filters(); } -/** - Sets which filter will be initially selected. - - The first filter is indexed as 0. - If filter_value()==filters(), then "All Files" was chosen. - If filter_value() > filters(), then a custom filter was set. - */ -void Fl_Native_File_Chooser::filter_value(int i) { _x11_file_chooser->filter_value(i); } -/** - Returns which filter value was last selected by the user. - This is only valid if the chooser returns success. - */ -int Fl_Native_File_Chooser::filter_value() const { return _x11_file_chooser->filter_value(); } -/** - Sets the default filename for the chooser. - Use directory() to set the default directory. - Mainly used to preset the filename for save dialogs, - and on most platforms can be used for opening files as well. - */ -void Fl_Native_File_Chooser::preset_file(const char* f) { _x11_file_chooser->preset_file(f); } -/** - Get the preset filename. - */ -const char* Fl_Native_File_Chooser::preset_file() const { return _x11_file_chooser->preset_file(); } -/** - Returns a system dependent error message for the last method that failed. - This message should at least be flagged to the user in a dialog box, or to some kind of error log. - Contents will be valid only for methods that document errmsg() will have info on failures. - */ -const char *Fl_Native_File_Chooser::errmsg() const { return _x11_file_chooser->errmsg(); } -/** - Post the chooser's dialog. Blocks until dialog has been completed or cancelled. - \returns - - 0 -- user picked a file - - 1 -- user cancelled - - -1 -- failed; errmsg() has reason - */ -int Fl_Native_File_Chooser::show() { return _x11_file_chooser->show(); } -Fl_FLTK_File_Chooser::Fl_FLTK_File_Chooser(int val) { +Fl_Native_File_Chooser_FLTK_Driver::Fl_Native_File_Chooser_FLTK_Driver(int val) : + Fl_Native_File_Chooser_Driver(val) { _btype = 0; _options = 0; _filter = NULL; @@ -243,7 +48,7 @@ Fl_FLTK_File_Chooser::Fl_FLTK_File_Chooser(int val) { _nfilters = 0; } -Fl_FLTK_File_Chooser::~Fl_FLTK_File_Chooser() { +Fl_Native_File_Chooser_FLTK_Driver::~Fl_Native_File_Chooser_FLTK_Driver() { delete _file_chooser; _file_chooser = NULL; _filter = strfree(_filter); @@ -256,13 +61,13 @@ Fl_FLTK_File_Chooser::~Fl_FLTK_File_Chooser() { // PRIVATE: SET ERROR MESSAGE -void Fl_FLTK_File_Chooser::errmsg(const char *msg) { +void Fl_Native_File_Chooser_FLTK_Driver::errmsg(const char *msg) { _errmsg = strfree(_errmsg); _errmsg = strnew(msg); } // PRIVATE: translate Native types to Fl_File_Chooser types -int Fl_FLTK_File_Chooser::type_fl_file(int val) { +int Fl_Native_File_Chooser_FLTK_Driver::type_fl_file(int val) { switch (val) { case Fl_Native_File_Chooser::BROWSE_FILE: return(Fl_File_Chooser::SINGLE); @@ -281,24 +86,24 @@ int Fl_FLTK_File_Chooser::type_fl_file(int val) { } } -void Fl_FLTK_File_Chooser::type(int val) { +void Fl_Native_File_Chooser_FLTK_Driver::type(int val) { _btype = val; _file_chooser->type(type_fl_file(val)); } -int Fl_FLTK_File_Chooser::type() const { +int Fl_Native_File_Chooser_FLTK_Driver::type() const { return(_btype); } -void Fl_FLTK_File_Chooser::options(int val) { +void Fl_Native_File_Chooser_FLTK_Driver::options(int val) { _options = val; } -int Fl_FLTK_File_Chooser::options() const { +int Fl_Native_File_Chooser_FLTK_Driver::options() const { return(_options); } -int Fl_FLTK_File_Chooser::show() { +int Fl_Native_File_Chooser_FLTK_Driver::show() { // FILTER if ( _parsedfilt ) { @@ -345,7 +150,7 @@ int Fl_FLTK_File_Chooser::show() { // HANDLE SHOWING 'SaveAs' CONFIRM if ( options() & Fl_Native_File_Chooser::SAVEAS_CONFIRM && type() == Fl_Native_File_Chooser::BROWSE_SAVE_FILE ) { struct stat buf; - if ( stat(_file_chooser->value(), &buf) != -1 ) { + if ( fl_stat(_file_chooser->value(), &buf) != -1 ) { if ( buf.st_mode & S_IFREG ) { // Regular file + exists? if ( exist_dialog() == 0 ) { return(1); @@ -359,63 +164,63 @@ int Fl_FLTK_File_Chooser::show() { else return(1); } -const char *Fl_FLTK_File_Chooser::errmsg() const { +const char *Fl_Native_File_Chooser_FLTK_Driver::errmsg() const { return(_errmsg ? _errmsg : "No error"); } -const char* Fl_FLTK_File_Chooser::filename() const { +const char* Fl_Native_File_Chooser_FLTK_Driver::filename() const { if ( _file_chooser->count() > 0 ) { return(_file_chooser->value()); } return(""); } -const char* Fl_FLTK_File_Chooser::filename(int i) const { +const char* Fl_Native_File_Chooser_FLTK_Driver::filename(int i) const { if ( i < _file_chooser->count() ) return(_file_chooser->value(i+1)); // convert fltk 1 based to our 0 based return(""); } -void Fl_FLTK_File_Chooser::title(const char *val) { +void Fl_Native_File_Chooser_FLTK_Driver::title(const char *val) { _file_chooser->label(val); } -const char *Fl_FLTK_File_Chooser::title() const { +const char *Fl_Native_File_Chooser_FLTK_Driver::title() const { return(_file_chooser->label()); } -void Fl_FLTK_File_Chooser::filter(const char *val) { +void Fl_Native_File_Chooser_FLTK_Driver::filter(const char *val) { _filter = strfree(_filter); _filter = strnew(val); parse_filter(); } -const char *Fl_FLTK_File_Chooser::filter() const { +const char *Fl_Native_File_Chooser_FLTK_Driver::filter() const { return(_filter); } -int Fl_FLTK_File_Chooser::filters() const { +int Fl_Native_File_Chooser_FLTK_Driver::filters() const { return(_nfilters); } -void Fl_FLTK_File_Chooser::filter_value(int val) { +void Fl_Native_File_Chooser_FLTK_Driver::filter_value(int val) { _filtvalue = val; } -int Fl_FLTK_File_Chooser::filter_value() const { +int Fl_Native_File_Chooser_FLTK_Driver::filter_value() const { return _filtvalue; } -int Fl_FLTK_File_Chooser::count() const { +int Fl_Native_File_Chooser_FLTK_Driver::count() const { return _file_chooser->count(); } -void Fl_FLTK_File_Chooser::directory(const char *val) { +void Fl_Native_File_Chooser_FLTK_Driver::directory(const char *val) { _directory = strfree(_directory); _directory = strnew(val); } -const char *Fl_FLTK_File_Chooser::directory() const { +const char *Fl_Native_File_Chooser_FLTK_Driver::directory() const { return _directory; } @@ -429,7 +234,7 @@ const char *Fl_FLTK_File_Chooser::directory() const { // Returns a modified version of the filter that the caller is responsible // for freeing with strfree(). // -void Fl_FLTK_File_Chooser::parse_filter() { +void Fl_Native_File_Chooser_FLTK_Driver::parse_filter() { _parsedfilt = strfree(_parsedfilt); // clear previous parsed filter (if any) _nfilters = 0; char *in = _filter; @@ -492,21 +297,19 @@ void Fl_FLTK_File_Chooser::parse_filter() { //NOTREACHED } -void Fl_FLTK_File_Chooser::preset_file(const char* val) { +void Fl_Native_File_Chooser_FLTK_Driver::preset_file(const char* val) { _preset_file = strfree(_preset_file); _preset_file = strnew(val); } -const char* Fl_FLTK_File_Chooser::preset_file() const { +const char* Fl_Native_File_Chooser_FLTK_Driver::preset_file() const { return _preset_file; } -int Fl_FLTK_File_Chooser::exist_dialog() { +int Fl_Native_File_Chooser_FLTK_Driver::exist_dialog() { return fl_choice("%s", fl_cancel, fl_ok, NULL, Fl_Native_File_Chooser::file_exists_message); } -#endif - // // End of "$Id$". // diff --git a/src/Fl_Native_File_Chooser_GTK.cxx b/src/Fl_Native_File_Chooser_GTK.cxx index 2a972856b..4f10ea4ab 100644 --- a/src/Fl_Native_File_Chooser_GTK.cxx +++ b/src/Fl_Native_File_Chooser_GTK.cxx @@ -16,9 +16,11 @@ // http://www.fltk.org/str.php // -#include +#include #ifdef USE_X11 +#include +#include #if HAVE_DLSYM && HAVE_DLFCN_H #include // for dlopen et al @@ -93,7 +95,51 @@ typedef void (*GClosureNotify)(gpointer data, GClosure *closure); /* --------------------- End of Type definitions from GLIB and GTK --------------------- */ -int Fl_GTK_File_Chooser::did_find_GTK_libs = 0; + +class FL_EXPORT Fl_Native_File_Chooser_GTK_Driver : public Fl_Native_File_Chooser_FLTK_Driver { + friend class Fl_Native_File_Chooser; +private: + static int have_looked_for_GTK_libs; + typedef struct _GtkWidget GtkWidget; + typedef struct _GtkFileFilterInfo GtkFileFilterInfo; + struct pair { + Fl_Native_File_Chooser_GTK_Driver* running; // the running Fl_GTK_File_Chooser + const char *filter; // a filter string of the chooser + pair(Fl_Native_File_Chooser_GTK_Driver* c, const char *f) { + running = c; + filter = strdup(f); + }; + ~pair() { + free((char*)filter); + }; + }; + GtkWidget *gtkw_ptr; // used to hold a GtkWidget* without pulling GTK into everything... + void *gtkw_slist; // used to hold a GLib GSList... + unsigned gtkw_count; // number of files read back - if any + mutable char *gtkw_filename; // last name we read back + char *gtkw_title; // the title to be applied to the dialog + const char *previous_filter; + + int fl_gtk_chooser_wrapper(); // method that wraps the GTK widget + Fl_Native_File_Chooser_GTK_Driver(int val); + virtual ~Fl_Native_File_Chooser_GTK_Driver(); + static int did_find_GTK_libs; + static void probe_for_GTK_libs(void); + virtual void type(int); + virtual int count() const; + virtual const char *filename() const; + virtual const char *filename(int i) const; + virtual void title(const char *); + virtual const char* title() const; + virtual int show(); + void changed_output_type(const char *filter); + + static int custom_gtk_filter_function(const GtkFileFilterInfo*, Fl_Native_File_Chooser_GTK_Driver::pair*); + static void free_pair(pair *p); +}; + + +int Fl_Native_File_Chooser_GTK_Driver::did_find_GTK_libs = 0; /* These are the GTK/GLib methods we want to load, but not call by name...! */ @@ -245,7 +291,26 @@ typedef void (*XX_gtk_toggle_button_set_active)(GtkToggleButton *, gboolean); static XX_gtk_toggle_button_set_active fl_gtk_toggle_button_set_active = NULL; -Fl_GTK_File_Chooser::Fl_GTK_File_Chooser(int val) : Fl_FLTK_File_Chooser(-1) +int Fl_Native_File_Chooser_GTK_Driver::have_looked_for_GTK_libs = 0; + + +Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { + if (Fl_Native_File_Chooser_GTK_Driver::have_looked_for_GTK_libs == 0) { + // First Time here, try to find the GTK libs if they are installed +#if HAVE_DLSYM && HAVE_DLFCN_H + if (Fl::option(Fl::OPTION_FNFC_USES_GTK)) { + Fl_Native_File_Chooser_GTK_Driver::probe_for_GTK_libs(); + } +#endif + Fl_Native_File_Chooser_GTK_Driver::have_looked_for_GTK_libs = -1; + } + // if we found all the GTK functions we need, we will use the GtkFileChooserDialog + if (Fl_Native_File_Chooser_GTK_Driver::did_find_GTK_libs) platform_fnfc = new Fl_Native_File_Chooser_GTK_Driver(val); + else platform_fnfc = new Fl_Native_File_Chooser_FLTK_Driver(val); +} + + +Fl_Native_File_Chooser_GTK_Driver::Fl_Native_File_Chooser_GTK_Driver(int val) : Fl_Native_File_Chooser_FLTK_Driver(-1) { gtkw_ptr = NULL; // used to hold a GtkWidget* gtkw_slist = NULL; // will hold the returned file names in a multi-selection... @@ -256,7 +321,7 @@ Fl_GTK_File_Chooser::Fl_GTK_File_Chooser(int val) : Fl_FLTK_File_Chooser(-1) previous_filter = NULL; } -Fl_GTK_File_Chooser::~Fl_GTK_File_Chooser() +Fl_Native_File_Chooser_GTK_Driver::~Fl_Native_File_Chooser_GTK_Driver() { // Should free up resources taken for... if(gtkw_ptr) { @@ -280,15 +345,15 @@ Fl_GTK_File_Chooser::~Fl_GTK_File_Chooser() gtkw_title = strfree(gtkw_title); } -void Fl_GTK_File_Chooser::type(int val) { +void Fl_Native_File_Chooser_GTK_Driver::type(int val) { _btype = val; } -int Fl_GTK_File_Chooser::count() const { +int Fl_Native_File_Chooser_GTK_Driver::count() const { return gtkw_count; } -const char *Fl_GTK_File_Chooser::filename() const +const char *Fl_Native_File_Chooser_GTK_Driver::filename() const { if(gtkw_ptr) { if(fl_gtk_file_chooser_get_select_multiple((GtkFileChooser *)gtkw_ptr) == FALSE) { @@ -303,7 +368,7 @@ const char *Fl_GTK_File_Chooser::filename() const return(""); } -const char *Fl_GTK_File_Chooser::filename(int i) const +const char *Fl_Native_File_Chooser_GTK_Driver::filename(int i) const { if(fl_gtk_file_chooser_get_select_multiple((GtkFileChooser *)gtkw_ptr) == FALSE) { return gtkw_filename; @@ -318,19 +383,19 @@ const char *Fl_GTK_File_Chooser::filename(int i) const return(""); } -void Fl_GTK_File_Chooser::title(const char *val) +void Fl_Native_File_Chooser_GTK_Driver::title(const char *val) { strfree(gtkw_title); gtkw_title = strnew(val); } -const char* Fl_GTK_File_Chooser::title() const +const char* Fl_Native_File_Chooser_GTK_Driver::title() const { return gtkw_title; } /* changes the extension of the outfile in the chooser according to newly selected filter */ -void Fl_GTK_File_Chooser::changed_output_type(const char *filter) +void Fl_Native_File_Chooser_GTK_Driver::changed_output_type(const char *filter) { if ( !(options()&Fl_Native_File_Chooser::USE_FILTER_EXT) ) return; if (strchr(filter, '(') || strchr(filter, '{') || strchr(filter+1, '*') || strncmp(filter, "*.", 2)) return; @@ -348,7 +413,7 @@ void Fl_GTK_File_Chooser::changed_output_type(const char *filter) /* Filters files before display in chooser. Also used to detect when the filter just changed */ -gboolean Fl_GTK_File_Chooser::custom_gtk_filter_function(const GtkFileFilterInfo *info, Fl_GTK_File_Chooser::pair* p) +gboolean Fl_Native_File_Chooser_GTK_Driver::custom_gtk_filter_function(const GtkFileFilterInfo *info, Fl_Native_File_Chooser_GTK_Driver::pair* p) { if (p->running->previous_filter != p->filter) { p->running->changed_output_type(p->filter); @@ -357,7 +422,7 @@ gboolean Fl_GTK_File_Chooser::custom_gtk_filter_function(const GtkFileFilterInfo return (gboolean)fl_filename_match(fl_filename_name(info->filename), p->filter); } -void Fl_GTK_File_Chooser::free_pair(Fl_GTK_File_Chooser::pair *p) +void Fl_Native_File_Chooser_GTK_Driver::free_pair(Fl_Native_File_Chooser_GTK_Driver::pair *p) { delete p; } @@ -368,7 +433,7 @@ static void hidden_files_cb(GtkToggleButton *togglebutton, gpointer user_data) fl_gtk_file_chooser_set_show_hidden((GtkFileChooser*)user_data, state); } -int Fl_GTK_File_Chooser::show() +int Fl_Native_File_Chooser_GTK_Driver::show() { // The point here is that after running a GTK dialog, the calling program's current locale is modified. // To avoid that, we memorize the calling program's current locale, and the locale as modified @@ -424,7 +489,7 @@ static void run_response_handler(GtkDialog *dialog, gint response_id, gpointer d } -int Fl_GTK_File_Chooser::fl_gtk_chooser_wrapper() +int Fl_Native_File_Chooser_GTK_Driver::fl_gtk_chooser_wrapper() { int result = 1; static int have_gtk_init = 0; @@ -521,9 +586,9 @@ int Fl_GTK_File_Chooser::fl_gtk_chooser_wrapper() char *q = strchr(p, ')'); *q = 0; fl_gtk_file_filter_add_custom(filter_tab[count], GTK_FILE_FILTER_FILENAME, - (GtkFileFilterFunc)Fl_GTK_File_Chooser::custom_gtk_filter_function, - new Fl_GTK_File_Chooser::pair(this, p), - (GDestroyNotify)Fl_GTK_File_Chooser::free_pair); + (GtkFileFilterFunc)Fl_Native_File_Chooser_GTK_Driver::custom_gtk_filter_function, + new Fl_Native_File_Chooser_GTK_Driver::pair(this, p), + (GDestroyNotify)Fl_Native_File_Chooser_GTK_Driver::free_pair); fl_gtk_file_chooser_add_filter((GtkFileChooser *)gtkw_ptr, filter_tab[count]); p = strtok(NULL, "\t"); count++; @@ -642,14 +707,14 @@ static void* fl_dlopen(const char *filename1, const char *filename2) if (!ptr) ptr = dlopen(filename2, RTLD_LAZY | RTLD_GLOBAL); return ptr; } -#endif +#endif // HAVE_DLSYM && HAVE_DLFCN_H /* * Use dlopen to see if we can load the gtk dynamic libraries that * will allow us to create a GtkFileChooserDialog() on the fly, * without linking to the GTK libs at compile time. */ -void Fl_GTK_File_Chooser::probe_for_GTK_libs(void) { +void Fl_Native_File_Chooser_GTK_Driver::probe_for_GTK_libs(void) { #if HAVE_DLSYM && HAVE_DLFCN_H void *ptr_glib = NULL; void *ptr_gtk = NULL; @@ -728,10 +793,10 @@ void Fl_GTK_File_Chooser::probe_for_GTK_libs(void) { GET_SYM(gtk_toggle_button_set_active, ptr_gtk); did_find_GTK_libs = 1; -#endif +#endif // HAVE_DLSYM && HAVE_DLFCN_H } // probe_for_GTK_libs -#endif +#endif // USE_X11 // // End of "$Id$". diff --git a/src/Fl_Native_File_Chooser_MAC.mm b/src/Fl_Native_File_Chooser_MAC.mm index d09024d70..606a3c112 100644 --- a/src/Fl_Native_File_Chooser_MAC.mm +++ b/src/Fl_Native_File_Chooser_MAC.mm @@ -23,7 +23,6 @@ #ifdef __APPLE__ -#include "Fl_Native_File_Chooser_common.cxx" // strnew/strfree/strapp/chrcat #include // dirname(3) #include // stat(2) #include // stat(2) @@ -34,9 +33,74 @@ #include #include #include +# define MAXFILTERS 80 + +class Fl_Native_File_Chooser_Darwin_Driver : public Fl_Native_File_Chooser_Driver { +private: + int _btype; // kind-of browser to show() + int _options; // general options + void *_panel; + 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 methods + void errmsg(const char *msg); + void clear_pathnames(); + void set_single_pathname(const char *s); + int get_saveas_basename(void); + void clear_filters(); + void parse_filter(const char *from); + int post(); + int runmodal(); +public: + Fl_Native_File_Chooser_Darwin_Driver(int val); + ~Fl_Native_File_Chooser_Darwin_Driver(); + virtual void type(int t); + virtual int type() const ; + virtual void options(int o); + virtual int options() const; + virtual int count() const; + virtual const char *filename() const ; + virtual const char *filename(int i) const ; + virtual void directory(const char *val) ; + virtual const char *directory() const; + virtual void title(const char *t); + virtual const char* title() const; + virtual const char *filter() const ; + virtual void filter(const char *f); + virtual int filters() const ; + virtual void filter_value(int i) ; + virtual int filter_value() const ; + virtual void preset_file(const char*f) ; + virtual const char* preset_file() const; + virtual const char *errmsg() const ; + virtual int show() ; +}; + +Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { + platform_fnfc = new Fl_Native_File_Chooser_Darwin_Driver(val); +} // FREE PATHNAMES ARRAY, IF IT HAS ANY CONTENTS -void Fl_Native_File_Chooser::clear_pathnames() { +void Fl_Native_File_Chooser_Darwin_Driver::clear_pathnames() { if ( _pathnames ) { while ( --_tpathnames >= 0 ) { _pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]); @@ -48,7 +112,7 @@ void Fl_Native_File_Chooser::clear_pathnames() { } // SET A SINGLE PATHNAME -void Fl_Native_File_Chooser::set_single_pathname(const char *s) { +void Fl_Native_File_Chooser_Darwin_Driver::set_single_pathname(const char *s) { clear_pathnames(); _pathnames = new char*[1]; _pathnames[0] = strnew(s); @@ -56,10 +120,11 @@ void Fl_Native_File_Chooser::set_single_pathname(const char *s) { } // CONSTRUCTOR -Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { +Fl_Native_File_Chooser_Darwin_Driver::Fl_Native_File_Chooser_Darwin_Driver(int val) : + Fl_Native_File_Chooser_Driver(val) { _btype = val; _panel = NULL; - _options = NO_OPTIONS; + _options = Fl_Native_File_Chooser::NO_OPTIONS; _pathnames = NULL; _tpathnames = 0; _title = NULL; @@ -74,7 +139,7 @@ Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { } // DESTRUCTOR -Fl_Native_File_Chooser::~Fl_Native_File_Chooser() { +Fl_Native_File_Chooser_Darwin_Driver::~Fl_Native_File_Chooser_Darwin_Driver() { // _opts // nothing to manage // _options // nothing to manage // _keepstate // nothing to manage @@ -93,17 +158,17 @@ Fl_Native_File_Chooser::~Fl_Native_File_Chooser() { } // GET TYPE OF BROWSER -int Fl_Native_File_Chooser::type() const { +int Fl_Native_File_Chooser_Darwin_Driver::type() const { return(_btype); } // SET OPTIONS -void Fl_Native_File_Chooser::options(int val) { +void Fl_Native_File_Chooser_Darwin_Driver::options(int val) { _options = val; } // GET OPTIONS -int Fl_Native_File_Chooser::options() const { +int Fl_Native_File_Chooser_Darwin_Driver::options() const { return(_options); } @@ -113,7 +178,7 @@ int Fl_Native_File_Chooser::options() const { // 1 - user cancelled // -1 - failed; errmsg() has reason // -int Fl_Native_File_Chooser::show() { +int Fl_Native_File_Chooser_Darwin_Driver::show() { // Make sure fltk interface updates before posting our dialog Fl::flush(); @@ -127,37 +192,37 @@ int Fl_Native_File_Chooser::show() { // SET ERROR MESSAGE // Internal use only. // -void Fl_Native_File_Chooser::errmsg(const char *msg) { +void Fl_Native_File_Chooser_Darwin_Driver::errmsg(const char *msg) { _errmsg = strfree(_errmsg); _errmsg = strnew(msg); } // RETURN ERROR MESSAGE -const char *Fl_Native_File_Chooser::errmsg() const { +const char *Fl_Native_File_Chooser_Darwin_Driver::errmsg() const { return(_errmsg ? _errmsg : "No error"); } // GET FILENAME -const char* Fl_Native_File_Chooser::filename() const { +const char* Fl_Native_File_Chooser_Darwin_Driver::filename() const { if ( _pathnames && _tpathnames > 0 ) return(_pathnames[0]); return(""); } // GET FILENAME FROM LIST OF FILENAMES -const char* Fl_Native_File_Chooser::filename(int i) const { +const char* Fl_Native_File_Chooser_Darwin_Driver::filename(int i) const { if ( _pathnames && i < _tpathnames ) return(_pathnames[i]); return(""); } // GET TOTAL FILENAMES CHOSEN -int Fl_Native_File_Chooser::count() const { +int Fl_Native_File_Chooser_Darwin_Driver::count() const { return(_tpathnames); } // PRESET PATHNAME // Value can be NULL for none. // -void Fl_Native_File_Chooser::directory(const char *val) { +void Fl_Native_File_Chooser_Darwin_Driver::directory(const char *val) { _directory = strfree(_directory); _directory = strnew(val); } @@ -165,14 +230,14 @@ void Fl_Native_File_Chooser::directory(const char *val) { // GET PRESET PATHNAME // Returned value can be NULL if none set. // -const char* Fl_Native_File_Chooser::directory() const { +const char* Fl_Native_File_Chooser_Darwin_Driver::directory() const { return(_directory); } // SET TITLE // Value can be NULL if no title desired. // -void Fl_Native_File_Chooser::title(const char *val) { +void Fl_Native_File_Chooser_Darwin_Driver::title(const char *val) { _title = strfree(_title); _title = strnew(val); } @@ -180,14 +245,14 @@ void Fl_Native_File_Chooser::title(const char *val) { // GET TITLE // Returned value can be NULL if none set. // -const char *Fl_Native_File_Chooser::title() const { +const char *Fl_Native_File_Chooser_Darwin_Driver::title() const { return(_title); } // SET FILTER // Can be NULL if no filter needed // -void Fl_Native_File_Chooser::filter(const char *val) { +void Fl_Native_File_Chooser_Darwin_Driver::filter(const char *val) { _filter = strfree(_filter); _filter = strnew(val); @@ -204,14 +269,14 @@ void Fl_Native_File_Chooser::filter(const char *val) { // GET FILTER // Returned value can be NULL if none set. // -const char *Fl_Native_File_Chooser::filter() const { +const char *Fl_Native_File_Chooser_Darwin_Driver::filter() const { return(_filter); } // CLEAR ALL FILTERS // Internal use only. // -void Fl_Native_File_Chooser::clear_filters() { +void Fl_Native_File_Chooser_Darwin_Driver::clear_filters() { _filt_names = strfree(_filt_names); for (int i=0; i<_filt_total; i++) { _filt_patt[i] = strfree(_filt_patt[i]); @@ -239,7 +304,7 @@ void Fl_Native_File_Chooser::clear_filters() { // \_____/ \_______/ // Name Wildcard // -void Fl_Native_File_Chooser::parse_filter(const char *in) { +void Fl_Native_File_Chooser_Darwin_Driver::parse_filter(const char *in) { clear_filters(); if ( ! in ) return; int has_name = strchr(in, '\t') ? 1 : 0; @@ -285,7 +350,7 @@ void Fl_Native_File_Chooser::parse_filter(const char *in) { // CFStringCreateArrayBySeparatingStrings() // if ( _filt_total ) { - _filt_names = strapp(_filt_names, "\t"); + _filt_names = strapp(_filt_names, "\t"); } _filt_names = strapp(_filt_names, name); @@ -303,8 +368,8 @@ void Fl_Native_File_Chooser::parse_filter(const char *in) { default: // handle all non-special chars regchar: // handle regular char switch ( mode ) { - case 'n': chrcat(name, *in); continue; - case 'w': chrcat(wildcard, *in); continue; + case 'n': chrcat(name, *in); continue; + case 'w': chrcat(wildcard, *in); continue; } break; } @@ -315,7 +380,7 @@ void Fl_Native_File_Chooser::parse_filter(const char *in) { // SET PRESET FILE // Value can be NULL for none. // -void Fl_Native_File_Chooser::preset_file(const char* val) { +void Fl_Native_File_Chooser_Darwin_Driver::preset_file(const char* val) { _preset_file = strfree(_preset_file); _preset_file = strnew(val); } @@ -323,28 +388,28 @@ void Fl_Native_File_Chooser::preset_file(const char* val) { // PRESET FILE // Returned value can be NULL if none set. // -const char* Fl_Native_File_Chooser::preset_file() const { +const char* Fl_Native_File_Chooser_Darwin_Driver::preset_file() const { return(_preset_file); } -void Fl_Native_File_Chooser::filter_value(int val) { +void Fl_Native_File_Chooser_Darwin_Driver::filter_value(int val) { _filt_value = val; } -int Fl_Native_File_Chooser::filter_value() const { +int Fl_Native_File_Chooser_Darwin_Driver::filter_value() const { return(_filt_value); } -int Fl_Native_File_Chooser::filters() const { +int Fl_Native_File_Chooser_Darwin_Driver::filters() const { return(_filt_total); } #import #define UNLIKELYPREFIX "___fl_very_unlikely_prefix_" -int Fl_Native_File_Chooser::get_saveas_basename(void) { +int Fl_Native_File_Chooser_Darwin_Driver::get_saveas_basename(void) { char *q = strdup( [[[(NSSavePanel*)_panel URL] path] UTF8String] ); - if ( !(_options & SAVEAS_CONFIRM) ) { + if ( !(_options & Fl_Native_File_Chooser::SAVEAS_CONFIRM) ) { const char *d = [[[[(NSSavePanel*)_panel URL] path] stringByDeletingLastPathComponent] UTF8String]; int l = (int)strlen(d) + 1; if (strcmp(d, "/") == 0) l = 1; @@ -358,7 +423,7 @@ int Fl_Native_File_Chooser::get_saveas_basename(void) { } // SET THE TYPE OF BROWSER -void Fl_Native_File_Chooser::type(int val) { +void Fl_Native_File_Chooser_Darwin_Driver::type(int val) { _btype = val; } @@ -527,7 +592,7 @@ static NSPopUpButton *createPopupAccessory(NSSavePanel *panel, const char *filte return popup; } -int Fl_Native_File_Chooser::runmodal() +int Fl_Native_File_Chooser_Darwin_Driver::runmodal() { NSString *dir = nil; NSString *fname = nil; @@ -563,7 +628,7 @@ int Fl_Native_File_Chooser::runmodal() // 1 - user cancelled // -1 - failed; errmsg() has reason // -int Fl_Native_File_Chooser::post() { +int Fl_Native_File_Chooser_Darwin_Driver::post() { // INITIALIZE BROWSER if ( _filt_total == 0 ) { // Make sure they match _filt_value = 0; // TBD: move to someplace more logical? @@ -571,30 +636,30 @@ int Fl_Native_File_Chooser::post() { NSAutoreleasePool *localPool; localPool = [[NSAutoreleasePool alloc] init]; switch (_btype) { - case BROWSE_FILE: - case BROWSE_MULTI_FILE: - case BROWSE_DIRECTORY: - case BROWSE_MULTI_DIRECTORY: + case Fl_Native_File_Chooser::BROWSE_FILE: + case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: + case Fl_Native_File_Chooser::BROWSE_DIRECTORY: + case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: _panel = [NSOpenPanel openPanel]; break; - case BROWSE_SAVE_DIRECTORY: - case BROWSE_SAVE_FILE: + case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: + case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: _panel = [NSSavePanel savePanel]; break; } NSString *nstitle = [NSString stringWithUTF8String: (_title ? _title : "No Title")]; [(NSSavePanel*)_panel setTitle:nstitle]; switch (_btype) { - case BROWSE_MULTI_FILE: + case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: [(NSOpenPanel*)_panel setAllowsMultipleSelection:YES]; break; - case BROWSE_MULTI_DIRECTORY: + case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: [(NSOpenPanel*)_panel setAllowsMultipleSelection:YES]; /* FALLTHROUGH */ - case BROWSE_DIRECTORY: + case Fl_Native_File_Chooser::BROWSE_DIRECTORY: [(NSOpenPanel*)_panel setCanChooseDirectories:YES]; break; - case BROWSE_SAVE_DIRECTORY: + case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: [(NSSavePanel*)_panel setCanCreateDirectories:YES]; break; } @@ -621,13 +686,13 @@ int Fl_Native_File_Chooser::post() { FLsaveDelegate *saveDelegate = [[[FLsaveDelegate alloc] init] autorelease]; [(NSSavePanel*)_panel setAllowsOtherFileTypes:YES]; [(NSSavePanel*)_panel setDelegate:saveDelegate]; - [saveDelegate option:(_options & SAVEAS_CONFIRM)]; + [saveDelegate option:(_options & Fl_Native_File_Chooser::SAVEAS_CONFIRM)]; if (_filt_total) { if (_filt_value >= _filt_total) _filt_value = _filt_total - 1; char *t = prepareMacFilter(_filt_total, _filter, _filt_patt); popup = createPopupAccessory((NSSavePanel*)_panel, t, [[(NSSavePanel*)_panel nameFieldLabel] UTF8String], _filt_value); delete[] t; - if (_options & USE_FILTER_EXT) { + if (_options & Fl_Native_File_Chooser::USE_FILTER_EXT) { [popup setAction:@selector(changedPopup:)]; [popup setTarget:saveDelegate]; [saveDelegate panel:(NSSavePanel*)_panel]; diff --git a/src/Fl_Native_File_Chooser_WIN32.cxx b/src/Fl_Native_File_Chooser_WIN32.cxx index 7cd50e7dd..6dd6b1bf1 100644 --- a/src/Fl_Native_File_Chooser_WIN32.cxx +++ b/src/Fl_Native_File_Chooser_WIN32.cxx @@ -2,7 +2,7 @@ // // FLTK native OS file chooser widget // -// Copyright 1998-2014 by Bill Spitzak and others. +// Copyright 1998-2016 by Bill Spitzak and others. // Copyright 2004 Greg Ercolano. // API changes + filter improvements by Nathan Vander Wilt 2005 // @@ -28,15 +28,83 @@ #include // sprintf #include -#include "Fl_Native_File_Chooser_common.cxx" // strnew/strfree/strapp/chrcat - #define FNFC_MAX_PATH 32768 // XXX: MAX_PATH under win32 is 260, too small for modern use #include +# include +# include // OPENFILENAMEW, GetOpenFileName() +# include // BROWSEINFOW, SHBrowseForFolder() +# include // FL_EXPORT +#include // for fl_open_display + + +class Fl_Native_File_Chooser_WinAPI_Driver : public Fl_Native_File_Chooser_Driver { +private: + int _btype; // kind-of browser to show() + int _options; // general options + OPENFILENAMEW *_ofn_ptr; // GetOpenFileName() & GetSaveFileName() struct + BROWSEINFOW *_binf_ptr; // 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 ClearOFN(); + void ClearBINF(); + void Win2Unix(char *s); + void Unix2Win(char *s); + int showfile(); + int showdir(); + + void parse_filter(const char *); + void clear_filters(); + void add_filter(const char *, const char *); +public: + Fl_Native_File_Chooser_WinAPI_Driver(int val); + ~Fl_Native_File_Chooser_WinAPI_Driver(); + virtual void type(int t); + virtual int type() const ; + virtual void options(int o); + virtual int options() const; + virtual int count() const; + virtual const char *filename() const ; + virtual const char *filename(int i) const ; + virtual void directory(const char *val) ; + virtual const char *directory() const; + virtual void title(const char *t); + virtual const char* title() const; + virtual const char *filter() const ; + virtual void filter(const char *f); + virtual int filters() const ; + virtual void filter_value(int i) ; + virtual int filter_value() const ; + virtual void preset_file(const char*f) ; + virtual const char* preset_file() const; + virtual const char *errmsg() const ; + virtual int show() ; +}; + + +Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { + platform_fnfc = new Fl_Native_File_Chooser_WinAPI_Driver(val); +} + + static LPCWSTR utf8towchar(const char *in); static char *wchartoutf8(LPCWSTR in); -#include // for fl_open_display #define LCURLY_CHR '{' #define RCURLY_CHR '}' @@ -125,10 +193,11 @@ static void dnullcat(char*&wp, const char *string, int n = -1 ) { } // CTOR -Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { +Fl_Native_File_Chooser_WinAPI_Driver::Fl_Native_File_Chooser_WinAPI_Driver(int val) : + Fl_Native_File_Chooser_Driver(val) { _btype = val; - _options = NO_OPTIONS; - _ofn_ptr = new OPENFILENAMEW; + _options = Fl_Native_File_Chooser::NO_OPTIONS; + _ofn_ptr = new OPENFILENAMEW; _binf_ptr = new BROWSEINFOW; memset((void*)_ofn_ptr, 0, sizeof(OPENFILENAMEW)); _ofn_ptr->lStructSize = sizeof(OPENFILENAMEW); @@ -146,7 +215,7 @@ Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { } // DTOR -Fl_Native_File_Chooser::~Fl_Native_File_Chooser() { +Fl_Native_File_Chooser_WinAPI_Driver::~Fl_Native_File_Chooser_WinAPI_Driver() { //_pathnames // managed by clear_pathnames() //_tpathnames // managed by clear_pathnames() _directory = strfree(_directory); @@ -165,33 +234,33 @@ Fl_Native_File_Chooser::~Fl_Native_File_Chooser() { } // SET TYPE OF BROWSER -void Fl_Native_File_Chooser::type(int val) { +void Fl_Native_File_Chooser_WinAPI_Driver::type(int val) { _btype = val; } // GET TYPE OF BROWSER -int Fl_Native_File_Chooser::type() const { +int Fl_Native_File_Chooser_WinAPI_Driver::type() const { return( _btype ); } // SET OPTIONS -void Fl_Native_File_Chooser::options(int val) { +void Fl_Native_File_Chooser_WinAPI_Driver::options(int val) { _options = val; } // GET OPTIONS -int Fl_Native_File_Chooser::options() const { +int Fl_Native_File_Chooser_WinAPI_Driver::options() const { return(_options); } // PRIVATE: SET ERROR MESSAGE -void Fl_Native_File_Chooser::errmsg(const char *val) { +void Fl_Native_File_Chooser_WinAPI_Driver::errmsg(const char *val) { _errmsg = strfree(_errmsg); _errmsg = strnew(val); } // FREE PATHNAMES ARRAY, IF IT HAS ANY CONTENTS -void Fl_Native_File_Chooser::clear_pathnames() { +void Fl_Native_File_Chooser_WinAPI_Driver::clear_pathnames() { if ( _pathnames ) { while ( --_tpathnames >= 0 ) { _pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]); @@ -203,7 +272,7 @@ void Fl_Native_File_Chooser::clear_pathnames() { } // SET A SINGLE PATHNAME -void Fl_Native_File_Chooser::set_single_pathname(const char *s) { +void Fl_Native_File_Chooser_WinAPI_Driver::set_single_pathname(const char *s) { clear_pathnames(); _pathnames = new char*[1]; _pathnames[0] = strnew(s); @@ -211,7 +280,7 @@ void Fl_Native_File_Chooser::set_single_pathname(const char *s) { } // ADD PATHNAME TO EXISTING ARRAY -void Fl_Native_File_Chooser::add_pathname(const char *s) { +void Fl_Native_File_Chooser_WinAPI_Driver::add_pathname(const char *s) { if ( ! _pathnames ) { // Create first element in array ++_tpathnames; @@ -239,7 +308,7 @@ static void FreePIDL(LPITEMIDLIST pidl) { } // CLEAR MICROSOFT OFN (OPEN FILE NAME) CLASS -void Fl_Native_File_Chooser::ClearOFN() { +void Fl_Native_File_Chooser_WinAPI_Driver::ClearOFN() { // Free any previously allocated lpstrFile before zeroing out _ofn_ptr if ( _ofn_ptr->lpstrFile ) { delete[] _ofn_ptr->lpstrFile; @@ -257,7 +326,7 @@ void Fl_Native_File_Chooser::ClearOFN() { } // CLEAR MICROSOFT BINF (BROWSER INFO) CLASS -void Fl_Native_File_Chooser::ClearBINF() { +void Fl_Native_File_Chooser_WinAPI_Driver::ClearBINF() { if ( _binf_ptr->pidlRoot ) { FreePIDL((ITEMIDLIST*)_binf_ptr->pidlRoot); _binf_ptr->pidlRoot = NULL; @@ -266,19 +335,19 @@ void Fl_Native_File_Chooser::ClearBINF() { } // CONVERT WINDOWS BACKSLASHES TO UNIX FRONTSLASHES -void Fl_Native_File_Chooser::Win2Unix(char *s) { +void Fl_Native_File_Chooser_WinAPI_Driver::Win2Unix(char *s) { for ( ; *s; s++ ) if ( *s == '\\' ) *s = '/'; } // CONVERT UNIX FRONTSLASHES TO WINDOWS BACKSLASHES -void Fl_Native_File_Chooser::Unix2Win(char *s) { +void Fl_Native_File_Chooser_WinAPI_Driver::Unix2Win(char *s) { for ( ; *s; s++ ) if ( *s == '/' ) *s = '\\'; } // SHOW FILE BROWSER -int Fl_Native_File_Chooser::showfile() { +int Fl_Native_File_Chooser_WinAPI_Driver::showfile() { ClearOFN(); clear_pathnames(); size_t fsize = FNFC_MAX_PATH; @@ -294,17 +363,17 @@ int Fl_Native_File_Chooser::showfile() { _ofn_ptr->Flags |= OFN_NOCHANGEDIR; // prevent dialog for messing up the cwd switch ( _btype ) { - case BROWSE_DIRECTORY: - case BROWSE_MULTI_DIRECTORY: - case BROWSE_SAVE_DIRECTORY: + case Fl_Native_File_Chooser::BROWSE_DIRECTORY: + case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: + case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: abort(); // never happens: handled by showdir() - case BROWSE_FILE: + case Fl_Native_File_Chooser::BROWSE_FILE: break; - case BROWSE_MULTI_FILE: + case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: _ofn_ptr->Flags |= OFN_ALLOWMULTISELECT; break; - case BROWSE_SAVE_FILE: - if ( options() & SAVEAS_CONFIRM && type() == BROWSE_SAVE_FILE ) { + case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: + if ( options() & Fl_Native_File_Chooser::SAVEAS_CONFIRM && type() == Fl_Native_File_Chooser::BROWSE_SAVE_FILE ) { _ofn_ptr->Flags |= OFN_OVERWRITEPROMPT; } break; @@ -376,7 +445,7 @@ int Fl_Native_File_Chooser::showfile() { } // OPEN THE DIALOG WINDOW int err; - if ( _btype == BROWSE_SAVE_FILE ) { + if ( _btype == Fl_Native_File_Chooser::BROWSE_SAVE_FILE ) { err = GetSaveFileNameW(_ofn_ptr); } else { err = GetOpenFileNameW(_ofn_ptr); @@ -399,12 +468,12 @@ int Fl_Native_File_Chooser::showfile() { } // PREPARE PATHNAMES FOR RETURN switch ( _btype ) { - case BROWSE_FILE: - case BROWSE_SAVE_FILE: + case Fl_Native_File_Chooser::BROWSE_FILE: + case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: set_single_pathname(wchartoutf8(_ofn_ptr->lpstrFile)); // Win2Unix(_pathnames[_tpathnames-1]); break; - case BROWSE_MULTI_FILE: { + case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: { // EXTRACT MULTIPLE FILENAMES const WCHAR *dirname = _ofn_ptr->lpstrFile; size_t dirlen = wcslen(dirname); @@ -432,9 +501,9 @@ int Fl_Native_File_Chooser::showfile() { } break; } - case BROWSE_DIRECTORY: - case BROWSE_MULTI_DIRECTORY: - case BROWSE_SAVE_DIRECTORY: + case Fl_Native_File_Chooser::BROWSE_DIRECTORY: + case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: + case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: abort(); // never happens: handled by showdir() } return(0); @@ -469,7 +538,7 @@ static int CALLBACK Dir_CB(HWND win, UINT msg, LPARAM param, LPARAM data) { } // SHOW DIRECTORY BROWSER -int Fl_Native_File_Chooser::showdir() { +int Fl_Native_File_Chooser_WinAPI_Driver::showdir() { // initialize OLE only once fl_open_display(); // init needed by BIF_USENEWUI ClearBINF(); @@ -506,11 +575,11 @@ int Fl_Native_File_Chooser::showdir() { // --- #if defined(BIF_NONEWFOLDERBUTTON) // Version 6.0 - if ( _btype == BROWSE_DIRECTORY ) _binf_ptr->ulFlags |= BIF_NONEWFOLDERBUTTON; + if ( _btype == Fl_Native_File_Chooser::BROWSE_DIRECTORY ) _binf_ptr->ulFlags |= BIF_NONEWFOLDERBUTTON; _binf_ptr->ulFlags |= BIF_USENEWUI | BIF_RETURNONLYFSDIRS; #elif defined(BIF_USENEWUI) // Version 5.0 - if ( _btype == BROWSE_DIRECTORY ) _binf_ptr->ulFlags |= BIF_EDITBOX; - else if ( _btype == BROWSE_SAVE_DIRECTORY ) _binf_ptr->ulFlags |= BIF_USENEWUI; + if ( _btype == Fl_Native_File_Chooser::BROWSE_DIRECTORY ) _binf_ptr->ulFlags |= BIF_EDITBOX; + else if ( _btype == Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY ) _binf_ptr->ulFlags |= BIF_USENEWUI; _binf_ptr->ulFlags |= BIF_RETURNONLYFSDIRS; #elif defined(BIF_EDITBOX) // Version 4.71 _binf_ptr->ulFlags |= BIF_RETURNONLYFSDIRS | BIF_EDITBOX; @@ -558,11 +627,11 @@ int Fl_Native_File_Chooser::showdir() { // 1 - user cancelled // -1 - failed; errmsg() has reason // -int Fl_Native_File_Chooser::show() { +int Fl_Native_File_Chooser_WinAPI_Driver::show() { int retval; - if ( _btype == BROWSE_DIRECTORY || - _btype == BROWSE_MULTI_DIRECTORY || - _btype == BROWSE_SAVE_DIRECTORY ) { + if ( _btype == Fl_Native_File_Chooser::BROWSE_DIRECTORY || + _btype == Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY || + _btype == Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY ) { retval = showdir(); } else { retval = showfile(); @@ -577,31 +646,31 @@ int Fl_Native_File_Chooser::show() { } // RETURN ERROR MESSAGE -const char *Fl_Native_File_Chooser::errmsg() const { +const char *Fl_Native_File_Chooser_WinAPI_Driver::errmsg() const { return(_errmsg ? _errmsg : "No error"); } // GET FILENAME -const char* Fl_Native_File_Chooser::filename() const { +const char* Fl_Native_File_Chooser_WinAPI_Driver::filename() const { if ( _pathnames && _tpathnames > 0 ) return(_pathnames[0]); return(""); } // GET FILENAME FROM LIST OF FILENAMES -const char* Fl_Native_File_Chooser::filename(int i) const { +const char* Fl_Native_File_Chooser_WinAPI_Driver::filename(int i) const { if ( _pathnames && i < _tpathnames ) return(_pathnames[i]); return(""); } // GET TOTAL FILENAMES CHOSEN -int Fl_Native_File_Chooser::count() const { +int Fl_Native_File_Chooser_WinAPI_Driver::count() const { return(_tpathnames); } // PRESET PATHNAME // Can be NULL if no preset is desired. // -void Fl_Native_File_Chooser::directory(const char *val) { +void Fl_Native_File_Chooser_WinAPI_Driver::directory(const char *val) { _directory = strfree(_directory); _directory = strnew(val); } @@ -609,14 +678,14 @@ void Fl_Native_File_Chooser::directory(const char *val) { // GET PRESET PATHNAME // Can return NULL if none set. // -const char *Fl_Native_File_Chooser::directory() const { +const char *Fl_Native_File_Chooser_WinAPI_Driver::directory() const { return(_directory); } // SET TITLE // Can be NULL if no title desired. // -void Fl_Native_File_Chooser::title(const char *val) { +void Fl_Native_File_Chooser_WinAPI_Driver::title(const char *val) { _title = strfree(_title); _title = strnew(val); } @@ -624,14 +693,14 @@ void Fl_Native_File_Chooser::title(const char *val) { // GET TITLE // Can return NULL if none set. // -const char *Fl_Native_File_Chooser::title() const { +const char *Fl_Native_File_Chooser_WinAPI_Driver::title() const { return(_title); } // SET FILTER // Can be NULL if no filter needed // -void Fl_Native_File_Chooser::filter(const char *val) { +void Fl_Native_File_Chooser_WinAPI_Driver::filter(const char *val) { _filter = strfree(_filter); clear_filters(); if ( val ) { @@ -648,18 +717,18 @@ void Fl_Native_File_Chooser::filter(const char *val) { // GET FILTER // Can return NULL if none set. // -const char *Fl_Native_File_Chooser::filter() const { +const char *Fl_Native_File_Chooser_WinAPI_Driver::filter() const { return(_filter); } // CLEAR FILTERS -void Fl_Native_File_Chooser::clear_filters() { +void Fl_Native_File_Chooser_WinAPI_Driver::clear_filters() { _nfilters = 0; _parsedfilt = strfree(_parsedfilt); } // ADD A FILTER -void Fl_Native_File_Chooser::add_filter(const char *name_in, // name of filter (optional: can be null) +void Fl_Native_File_Chooser_WinAPI_Driver::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]; @@ -749,7 +818,7 @@ static int count_filters(const char *filter) { // \_____/ \_______/ // Name Wildcard // -void Fl_Native_File_Chooser::parse_filter(const char *in) { +void Fl_Native_File_Chooser_WinAPI_Driver::parse_filter(const char *in) { clear_filters(); if ( ! in ) return; @@ -896,27 +965,27 @@ void Fl_Native_File_Chooser::parse_filter(const char *in) { } // SET 'CURRENTLY SELECTED FILTER' -void Fl_Native_File_Chooser::filter_value(int i) { +void Fl_Native_File_Chooser_WinAPI_Driver::filter_value(int i) { _ofn_ptr->nFilterIndex = i + 1; } // RETURN VALUE OF 'CURRENTLY SELECTED FILTER' -int Fl_Native_File_Chooser::filter_value() const { +int Fl_Native_File_Chooser_WinAPI_Driver::filter_value() const { return(_ofn_ptr->nFilterIndex ? _ofn_ptr->nFilterIndex-1 : _nfilters+1); } // PRESET FILENAME FOR 'SAVE AS' CHOOSER -void Fl_Native_File_Chooser::preset_file(const char* val) { +void Fl_Native_File_Chooser_WinAPI_Driver::preset_file(const char* val) { _preset_file = strfree(_preset_file); _preset_file = strnew(val); } // GET PRESET FILENAME FOR 'SAVE AS' CHOOSER -const char* Fl_Native_File_Chooser::preset_file() const { +const char* Fl_Native_File_Chooser_WinAPI_Driver::preset_file() const { return(_preset_file); } -int Fl_Native_File_Chooser::filters() const { +int Fl_Native_File_Chooser_WinAPI_Driver::filters() const { return(_nfilters); } diff --git a/src/Makefile b/src/Makefile index 632b0570a..01cd4d0b2 100644 --- a/src/Makefile +++ b/src/Makefile @@ -215,11 +215,7 @@ CFILES = fl_call_main.c flstring.c scandir.c numericsort.c vsnprintf.c UTF8CFILES = \ xutf8/case.c \ xutf8/is_right2left.c \ - xutf8/is_spacing.c \ - xutf8/keysym2Ucs.c \ - xutf8/utf8Input.c \ - xutf8/utf8Utils.c \ - xutf8/utf8Wrap.c + xutf8/is_spacing.c QUARTZCPPFILES = \ drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx \ @@ -253,7 +249,15 @@ XLIBCPPFILES = \ drivers/Posix/Fl_Posix_System_Driver.cxx \ drivers/Posix/Fl_Posix_Printer_Driver.cxx \ Fl_x.cxx \ - fl_dnd_x.cxx + fl_dnd_x.cxx \ + Fl_Native_File_Chooser_FLTK.cxx \ + Fl_Native_File_Chooser_GTK.cxx + +XLIBCFILES = \ + xutf8/keysym2Ucs.c \ + xutf8/utf8Input.c \ + xutf8/utf8Utils.c \ + xutf8/utf8Wrap.c XLIBFONTFILES = \ drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx @@ -277,7 +281,8 @@ GDICPPFILES = \ drivers/WinAPI/Fl_WinAPI_System_Driver.cxx \ drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx \ Fl_win32.cxx \ - fl_dnd_win32.cxx + fl_dnd_win32.cxx \ + Fl_Native_File_Chooser_WIN32.cxx PSCPPFILES = \ drivers/PostScript/Fl_PostScript.cxx \ @@ -297,6 +302,7 @@ CPPFILES += $(shell if test $(BUILD_X11) = Yes -a $(BUILD_XFT) != Yes; then echo CPPFILES += $(shell if test $(BUILD_GDI) = Yes; then echo $(GDICPPFILES); fi) +CFILES += $(shell if test $(BUILD_X11) = Yes; then echo $(XLIBCFILES); fi) OBJECTS = $(MMFILES:.mm=.o) $(CPPFILES:.cxx=.o) $(CFILES:.c=.o) $(UTF8CFILES:.c=.o) GLOBJECTS = $(GLCPPFILES:.cxx=.o) @@ -565,9 +571,9 @@ clean: libfltk_gl.dylib libfltk_images.dylib \ cmap core -depend: $(CPPFILES) $(MMFILES) $(FLCPPFILES) $(GLCPPFILES) $(IMGCPPFILES) $(CFILES) $(UTF8CFILES) +depend: $(CPPFILES) $(MMFILES) $(FLCPPFILES) $(GLCPPFILES) $(IMGCPPFILES) $(CFILES) $(UTF8CFILES) $(XLIBCFILES) makedepend -Y -I.. -f makedepend $(CPPFILES) $(MMFILES) $(FLCPPFILES) \ - $(GLCPPFILES) $(IMGCPPFILES) $(CFILES) $(UTF8CFILES) + $(GLCPPFILES) $(IMGCPPFILES) $(CFILES) $(UTF8CFILES) $(XLIBCFILES) # Automatically generated dependencies... generated on a Linux/Unix host ! include makedepend @@ -577,12 +583,15 @@ include makedepend # Please add only non-Linux/Unix files or such that are optional # (like "*xft*") here: Fl_get_key.o: Fl_get_key_mac.cxx Fl_get_key_win32.cxx -Fl_Native_File_Chooser.o : Fl_Native_File_Chooser_WIN32.cxx +Fl_Native_File_Chooser_WIN32.o : Fl_Native_File_Chooser_WIN32.cxx Fl_Native_File_Chooser_MAC.o: Fl_Native_File_Chooser_MAC.mm +Fl_Native_File_Chooser_FLTK.o: Fl_Native_File_Chooser_FLTK.cxx +Fl_Native_File_Chooser_GTK.o: Fl_Native_File_Chooser_GTK.cxx Fl_win32.o: Fl_win32.cxx Fl_cocoa.o: Fl_cocoa.mm fl_color.o: -fl_dnd.o: fl_dnd_win32.cxx fl_dnd_x.cxx +fl_dnd_win32.o: fl_dnd_win32.cxx +fl_dnd_x.o: fl_dnd_x.cxx Fl_Printer.o: ../src/drivers/PostScript/Fl_PostScript.cxx Fl_Quartz_Printer.o: Fl_Quartz_Printer.mm fl_arci.o: ../FL/mac.H ../FL/win32.H @@ -591,8 +600,6 @@ fl_ask.o: ../FL/mac.H ../FL/win32.H Fl_Bitmap.o: ../FL/mac.H ../FL/win32.H fl_color.o: ../FL/mac.H ../FL/win32.H fl_cursor.o: ../FL/mac.H ../FL/win32.H -fl_dnd.o: ../FL/mac.H ../FL/win32.H -Fl.o: ../FL/mac.H ../FL/win32.H Fl_Double_Window.o: ../FL/mac.H ../FL/win32.H fl_draw_image.o: ../FL/mac.H ../FL/win32.H fl_draw_pixmap.o: ../FL/mac.H ../FL/win32.H diff --git a/src/makedepend b/src/makedepend index 4c875c149..fb83a4555 100644 --- a/src/makedepend +++ b/src/makedepend @@ -380,7 +380,6 @@ Fl_Native_File_Chooser.o: ../FL/Fl_Light_Button.H ../FL/Fl_Button.H Fl_Native_File_Chooser.o: ../FL/Fl_File_Input.H ../FL/Fl_Input.H Fl_Native_File_Chooser.o: ../FL/Fl_Input_.H ../FL/Fl_Return_Button.H Fl_Native_File_Chooser.o: ../FL/fl_ask.H ../FL/Fl_File_Icon.H -Fl_Native_File_Chooser.o: Fl_Native_File_Chooser_common.cxx Fl_Native_File_Chooser.o: ../FL/Enumerations.H Fl_Native_File_Chooser_GTK.cxx Fl_Native_File_Chooser.o: ../FL/x.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H Fl_Native_File_Chooser.o: ../FL/Fl_Preferences.H