diff --git a/src/Makefile.am b/src/Makefile.am index a39688fe..a8bdac7c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -296,8 +296,6 @@ fldigi_SOURCES += \ dominoex/dominovar.cxx \ feld/feld.cxx \ feld/feldfonts.cxx \ - fileselector/FL/Native_File_Chooser.H \ - fileselector/Native_File_Chooser.cxx \ fileselector/fileselect.cxx \ filters/fftfilt.cxx \ filters/filters.cxx \ @@ -715,8 +713,6 @@ flarq_SOURCES += \ include/table.h \ include/util.h \ combo/combo.cxx \ - fileselector/FL/Native_File_Chooser.H \ - fileselector/Native_File_Chooser.cxx \ fileselector/fileselect.cxx \ logbook/table.cxx \ misc/ascii.cxx \ diff --git a/src/fileselector/FL/Native_File_Chooser.H b/src/fileselector/FL/Native_File_Chooser.H deleted file mode 100644 index c33649e1..00000000 --- a/src/fileselector/FL/Native_File_Chooser.H +++ /dev/null @@ -1,40 +0,0 @@ -// -// 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 -#if defined(_WIN32) || defined(__CYGWIN__) -#include -#endif - -// Use Apple's chooser designed by Stelios -#ifdef __APPLE__ -#include "FL/MAC_chooser.h" -#endif - -// All else falls back to FLTK's own chooser -#if ! defined(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) -#include -#endif - -#endif /*FL_NATIVE_FILE_CHOOSER_H*/ diff --git a/src/fileselector/FL/Native_File_Chooser_FLTK.H b/src/fileselector/FL/Native_File_Chooser_FLTK.H deleted file mode 100644 index a5b61edb..00000000 --- a/src/fileselector/FL/Native_File_Chooser_FLTK.H +++ /dev/null @@ -1,99 +0,0 @@ -// -// 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 -#include -#include "icons.h" -#include "gettext.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_choice2(_("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/src/fileselector/FL/Native_File_Chooser_MAC.H b/src/fileselector/FL/Native_File_Chooser_MAC.H deleted file mode 100644 index cea50b62..00000000 --- a/src/fileselector/FL/Native_File_Chooser_MAC.H +++ /dev/null @@ -1,137 +0,0 @@ -// -// MAC_chooser_MAC.H -- FLTK native OS file chooser widget -// -// Copyright 2004 by Greg Ercolano. -// 2010 by Stelios, M0GLD -// 2012 by Dave, W1HKJ -// -// 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. -// - -// OSX-SPECIFIC NATIVE BROWSER -#ifdef __APPLE_CC__ -#include -#else -#include -#endif - -#include -#define MAXFILTERS 80 - -class MAC_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: - MAC_chooser(int val = BROWSE_FILE); - ~MAC_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/src/fileselector/FL/Native_File_Chooser_WIN32.H b/src/fileselector/FL/Native_File_Chooser_WIN32.H deleted file mode 100644 index 889b4842..00000000 --- a/src/fileselector/FL/Native_File_Chooser_WIN32.H +++ /dev/null @@ -1,108 +0,0 @@ -// -// 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 -#include // malloc -#include -#include // OPENFILENAME, GetOpenFileName() -#include // 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/src/fileselector/Native_File_Chooser.cxx b/src/fileselector/Native_File_Chooser.cxx deleted file mode 100644 index 0c8a08ed..00000000 --- a/src/fileselector/Native_File_Chooser.cxx +++ /dev/null @@ -1,20 +0,0 @@ -// -// 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 General Public License -// along with this program. If not, see . - -#include - diff --git a/src/fileselector/Native_File_Chooser_FLTK.cxx b/src/fileselector/Native_File_Chooser_FLTK.cxx deleted file mode 100644 index e9addbc8..00000000 --- a/src/fileselector/Native_File_Chooser_FLTK.cxx +++ /dev/null @@ -1,348 +0,0 @@ -// -// 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 General Public License -// along with this program. If not, see . - -#include "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 - -#include "flnfc_common.cxx" -#include - -// 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]; - snprintf(comp, sizeof(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/src/fileselector/Native_File_Chooser_MAC.cxx b/src/fileselector/Native_File_Chooser_MAC.cxx deleted file mode 100644 index f4dada1c..00000000 --- a/src/fileselector/Native_File_Chooser_MAC.cxx +++ /dev/null @@ -1,834 +0,0 @@ -// -// MAC_chooser_MAC.cxx -- FLTK native OS file chooser widget -// -// Copyright 2004 by Greg Ercolano. -// FLTK2/MAC port by Greg Ercolano 2007. -// Dave Freese, W1HKJ 2012 -// -// 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 General Public License -// along with this program. If not, see . - -#include "flnfc_common.cxx" // strnew/strfree/strapp/chrcat - -#include -#include "FL/MAC_chooser.h" -#include - -// 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 -MAC_chooser::NavReply::NavReply() { - _valid_reply = 0; -} - -// NAVREPLY: DTOR -MAC_chooser::NavReply::~NavReply() { - if ( _valid_reply ) { - NavDisposeReply(&_reply); - } -} - -// GET REPLY FROM THE NAV* DIALOG -int MAC_chooser::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 MAC_chooser::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 MAC_chooser::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 MAC_chooser::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 MAC_chooser::clear_pathnames() { - if ( _pathnames ) { - while ( --_tpathnames >= 0 ) { - _pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]); - } - delete [] _pathnames; - _pathnames = NULL; - } - _tpathnames = 0; -} - -// SET A SINGLE PATHNAME -void MAC_chooser::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 MAC_chooser::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 MAC_chooser::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 MAC_chooser::event_handler( - NavEventCallbackMessage callBackSelector, - NavCBRecPtr cbparm, - void *data) { - OSStatus err; - MAC_chooser *nfb = (MAC_chooser*)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 -MAC_chooser::MAC_chooser(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 -MAC_chooser::~MAC_chooser() { - // _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 MAC_chooser::type(int val) { - _btype = val; -} - -// GET TYPE OF BROWSER -int MAC_chooser::type() const { - return(_btype); -} - -// SET OPTIONS -void MAC_chooser::options(int val) { - _options = val; -} - -// GET OPTIONS -int MAC_chooser::options() const { - return(_options); -} - -// SHOW THE BROWSER WINDOW -// Returns: -// 0 - user picked a file -// 1 - user cancelled -// -1 - failed; errmsg() has reason -// -int MAC_chooser::show() { - - // Make sure fltk interface updates before posting our dialog - Fl::awake(); - - // 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 MAC_chooser::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 MAC_chooser::errmsg(const char *msg) { - _errmsg = strfree(_errmsg); - _errmsg = strnew(msg); -} - -// RETURN ERROR MESSAGE -const char *MAC_chooser::errmsg() const { - return(_errmsg ? _errmsg : "No error"); -} - -// GET FILENAME -const char* MAC_chooser::filename() const { - if ( _pathnames && _tpathnames > 0 ) return(_pathnames[0]); - return(""); -} - -// GET FILENAME FROM LIST OF FILENAMES -const char* MAC_chooser::filename(int i) const { - if ( _pathnames && i < _tpathnames ) return(_pathnames[i]); - return(""); -} - -// GET TOTAL FILENAMES CHOSEN -int MAC_chooser::count() const { - return(_tpathnames); -} - -// PRESET PATHNAME -// Value can be NULL for none. -// -void MAC_chooser::directory(const char *val) { - _directory = strfree(_directory); - _directory = strnew(val); -} - -// GET PRESET PATHNAME -// Returned value can be NULL if none set. -// -const char* MAC_chooser::directory() const { - return(_directory); -} - -#include -// SET TITLE -// Value can be NULL if no title desired. -// -void MAC_chooser::title(const char *val) { -std::string tt = "My MAC "; -tt.append(val); - _title = strfree(_title); - _title = strnew(tt.c_str()); -// _title = strnew(val); -} - -// GET TITLE -// Returned value can be NULL if none set. -// -const char *MAC_chooser::title() const { - return(_title); -} - -// SET FILTER -// Can be NULL if no filter needed -// -void MAC_chooser::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 *MAC_chooser::filter() const { - return(_filter); -} - -// CLEAR ALL FILTERS -// Internal use only. -// -void MAC_chooser::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 MAC_chooser::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 MAC_chooser::filter_proc_cb(AEDesc *theItem, - void *info, - void *callBackUD, - NavFilterModes filterMode) { - return((MAC_chooser*)callBackUD)->filter_proc_cb2( - theItem, info, callBackUD, filterMode); -} - -// FILTER CALLBACK -// Return true if match, -// false if no match. -// -Boolean MAC_chooser::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 MAC_chooser::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* MAC_chooser::preset_file() { - return(_preset_file); -} - diff --git a/src/fileselector/Native_File_Chooser_WIN32.cxx b/src/fileselector/Native_File_Chooser_WIN32.cxx deleted file mode 100644 index 6072efb3..00000000 --- a/src/fileselector/Native_File_Chooser_WIN32.cxx +++ /dev/null @@ -1,777 +0,0 @@ -// -// 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 General Public License -// along with this program. If not, see . - -#include // debugging -#include "flnfc_common.cxx" // strnew/strfree/strapp/chrcat - -#include "FL/Native_File_Chooser.H" -#define FNFC_CLASS Fl_Native_File_Chooser -#define FNFC_CTOR Fl_Native_File_Chooser - -#define LCURLY_CHR '{' -#define RCURLY_CHR '}' -#define LBRACKET_CHR '[' -#define RBRACKET_CHR ']' -#define MAXFILTERS 80 - -#if 0 -// 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]); - } - } -} -#endif - -// 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 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 0 ) { - chrcat(wildcards[nwildcards-1], *in); - } - continue; - - case 'n': - chrcat(name, *in); - continue; - - case 'w': - chrcat(wildprefix, *in); - for ( t=0; t #include +#include +#include + #include "config.h" #include "fileselect.h" #include "debug.h" - -#include -#include +#include "qrunner.h" /** \class Fl_Native_File_Chooser @@ -108,35 +110,98 @@ using namespace std; namespace FSEL { -string filename; - void create(void) {}; void destroy(void) {}; -string stitle, sfilter, sdef; +string filename, stitle, sfilter, sdef, sdirectory; +char dirbuf[FL_PATH_MAX + 1] = ""; +char msg[400]; + +// use this function for testing on garbage OS, aka Windows +/* +void pfile (const char *dir, const char *fname, const char *filt) { + char fn[FL_PATH_MAX+1]; +#ifdef __WIN32__ + fl_filename_expand(fn, sizeof(fn) -1, "$USERPROFILE/"); +#else + fl_filename_expand(fn, sizeof(fn) -1, "$HOME/"); +#endif + strcat(fn, "pfile.txt"); + FILE *f = fopen(fn, "a"); + fprintf(f,"\ +dir: %s\n\ +file: %s\n\ +filter: %s\n", dir, fname, filt); + fclose(f); +} +*/ + +void dosfname(string &s) +{ + for (size_t i = 0; i < s.length(); i++) + if (s[i] == '/') s[i] = '\\'; +} const char* select(const char* title, const char* filter, const char* def, int* fsel) { + if (strlen(dirbuf) == 0) { +#ifdef __WIN32__ + fl_filename_expand(dirbuf, sizeof(dirbuf) -1, "$USERPROFILE/"); +#else + fl_filename_expand(dirbuf, sizeof(dirbuf) -1, "$HOME/"); +#endif + } + + size_t p = 0; Fl_Native_File_Chooser native; stitle.clear(); sfilter.clear(); sdef.clear(); + sdirectory.clear(); + if (title) stitle.assign(title); if (filter) sfilter.assign(filter); - if (def) sdef.assign(def); - if (!sfilter.empty() && sfilter[sfilter.length()-1] != '\n') sfilter += '\n'; - if (!stitle.empty()) native.title(stitle.c_str()); - native.type(Fl_Native_File_Chooser::BROWSE_FILE); - if (!sfilter.empty()) native.filter(sfilter.c_str()); - native.options(Fl_Native_File_Chooser::PREVIEW); + if (def) { + sdef.assign(def); + if (!sdef.empty()) { + p = sdef.length() - 1; + if ((sdef[p] == '/') || (sdef[p] == '\\')) sdef.append("fname"); + } + sdirectory.assign(sdef); + p = sdirectory.rfind(fl_filename_name(sdef.c_str())); + sdirectory.erase(p); + } + if (sdirectory.empty()) { + sdirectory.assign(dirbuf); + } + if (sdef.empty()) { + sdef.assign(sdirectory); + sdef.append("temp"); + } + + if (!sfilter.empty()) { + if (sfilter[sfilter.length()-1] != '\n') sfilter += '\n'; + native.filter(sfilter.c_str()); + } + native.title(stitle.c_str()); +#if __WIN32__ + dosfname(sdef); + dosfname(sdirectory); +#endif if (!sdef.empty()) native.preset_file(sdef.c_str()); + if (!sdirectory.empty()) native.directory(sdirectory.c_str()); + + native.type(Fl_Native_File_Chooser::BROWSE_FILE); + native.options(Fl_Native_File_Chooser::PREVIEW); + +// pfile(sdirectory.c_str(), sdef.c_str(), sfilter.c_str()); filename.clear(); switch ( native.show() ) { case -1: - LOG_INFO("ERROR: %s\n", native.errmsg()); // Error fall through + LOG_ERROR("ERROR: %s\n", native.errmsg()); // Error fall through case 1: return 0; break; @@ -157,25 +222,62 @@ const char* select(const char* title, const char* filter, const char* def, int* const char* saveas(const char* title, const char* filter, const char* def, int* fsel) { + if (strlen(dirbuf) == 0) { +#ifdef __WIN32__ + fl_filename_expand(dirbuf, sizeof(dirbuf) -1, "$USERPROFILE/"); +#else + fl_filename_expand(dirbuf, sizeof(dirbuf) -1, "$HOME/"); +#endif + } + + size_t p = 0; Fl_Native_File_Chooser native; stitle.clear(); sfilter.clear(); sdef.clear(); + sdirectory.clear(); + if (title) stitle.assign(title); if (filter) sfilter.assign(filter); - if (def) sdef.assign(def); - if (!sfilter.empty() && sfilter[sfilter.length()-1] != '\n') sfilter += '\n'; - if (!stitle.empty()) native.title(stitle.c_str()); - native.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); - if (!sfilter.empty()) native.filter(sfilter.c_str()); - native.options(Fl_Native_File_Chooser::NEW_FOLDER || Fl_Native_File_Chooser::SAVEAS_CONFIRM); + if (def) { + sdef.assign(def); + if (!sdef.empty()) { + p = sdef.length() - 1; + if ((sdef[p] == '/') || (sdef[p] == '\\')) sdef.append("fname"); + } + sdirectory.assign(sdef); + p = sdirectory.rfind(fl_filename_name(sdef.c_str())); + sdirectory.erase(p); + } + if (sdirectory.empty()) { + sdirectory.assign(dirbuf); + } + if (sdef.empty()) { + sdef.assign(sdirectory); + sdef.append("temp"); + } + + if (!sfilter.empty()) { + if (sfilter[sfilter.length()-1] != '\n') sfilter += '\n'; + native.filter(sfilter.c_str()); + } + native.title(stitle.c_str()); +#if __WIN32__ + dosfname(sdef); + dosfname(sdirectory); +#endif if (!sdef.empty()) native.preset_file(sdef.c_str()); + if (!sdirectory.empty()) native.directory(sdirectory.c_str()); + native.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); + native.options(Fl_Native_File_Chooser::NEW_FOLDER || Fl_Native_File_Chooser::SAVEAS_CONFIRM); + +// pfile(sdirectory.c_str(), sdef.c_str(), sfilter.c_str()); filename.clear(); switch ( native.show() ) { - case -1: LOG_INFO("ERROR: %s\n", native.errmsg()); break; // ERROR + case -1: LOG_ERROR("ERROR: %s\n", native.errmsg()); break; // ERROR case 1: break; // CANCEL default: if ( native.filename() ) { @@ -209,11 +311,18 @@ const char* dir_select(const char* title, const char* filter, const char* def) native.type(Fl_Native_File_Chooser::BROWSE_DIRECTORY); if (!sfilter.empty()) native.filter(sfilter.c_str()); native.options(Fl_Native_File_Chooser::NO_OPTIONS); - if (!sdef.empty()) native.directory(sdef.c_str()); +#if __WIN32__ + dosfname(sdef); +#endif + if (!sdef.empty()) { + native.directory(sdef.c_str()); + sdirectory = sdef; + } else + sdirectory.clear(); filename.clear(); switch ( native.show() ) { - case -1: LOG_INFO("ERROR: %s\n", native.errmsg()); break; // ERROR + case -1: LOG_ERROR("ERROR: %s\n", native.errmsg()); break; // ERROR case 1: break; // CANCEL default: if ( native.filename() ) { diff --git a/src/include/fileselect.h b/src/include/fileselect.h index 669fd7a9..dbb70847 100644 --- a/src/include/fileselect.h +++ b/src/include/fileselect.h @@ -23,39 +23,6 @@ #include -#if (FLDIGI_FLTK_API_MAJOR == 1 && FLDIGI_FLTK_API_MINOR < 3) || (FLARQ_FLTK_API_MAJOR == 1 && FLARQ_FLTK_API_MINOR < 3) -class Fl_Native_File_Chooser; - -class FSEL -{ -public: - static void create(void); - static void destroy(void); - static const char* select(const char* title, const char* filter, const char* def = 0, int* fsel = 0); - static const char* saveas(const char* title, const char* filter, const char* def = 0, int* fsel = 0); - static const char* dir_select(const char* title, const char* filter, const char* def = 0); - ~FSEL(); -private: - FSEL(); - FSEL(const FSEL&); - FSEL& operator=(const FSEL&); - - const char* get_file(void); -#if FSEL_THREAD - static void* thread_func(void* arg); -#endif -private: - static FSEL* inst; -#ifdef __APPLE__ - MAC_chooser* chooser; -#else - Fl_Native_File_Chooser* chooser; -#endif - int result; -}; - -#else // API >=1.3.0 - namespace FSEL { void create(void); @@ -66,6 +33,4 @@ namespace FSEL { } -#endif // API < 1.3.0 - #endif // FILESELECT_H diff --git a/src/logbook/adif_io.cxx b/src/logbook/adif_io.cxx index 8861957a..c8a61087 100644 --- a/src/logbook/adif_io.cxx +++ b/src/logbook/adif_io.cxx @@ -214,6 +214,7 @@ void cAdifIO::do_readfile(const char *fname, cQsoDb *db) long filesize = 0; char *buff; int found; + static char szmsg[200]; // open the adif file FILE *adiFile = fopen (fname, "r"); @@ -225,36 +226,37 @@ void cAdifIO::do_readfile(const char *fname, cQsoDb *db) filesize = ftell (adiFile); if (filesize == 0) { - LOG_INFO(_("Empty ADIF logbook file %s"), fl_filename_name(fname)); + snprintf(szmsg, sizeof(szmsg), _("Empty ADIF logbook file %s"), fname); + REQ(write_rxtext, "\n"); + REQ(write_rxtext, szmsg); + REQ(write_rxtext, "\n"); + LOG_ERROR("%s", szmsg); return; } buff = new char[filesize + 1]; - static char szmsg[100]; - static char szmsg2[100]; - snprintf(szmsg, sizeof(szmsg), "Reading %ld bytes from %s", - filesize, fl_filename_name(fname)); - REQ(write_rxtext, "\n*** "); - REQ(write_rxtext, szmsg); - LOG_INFO("%s", szmsg); // read the entire file into the buffer fseek (adiFile, 0, SEEK_SET); int retval = fread (buff, filesize, 1, adiFile); fclose (adiFile); if (retval != 1) { - LOG_ERROR(_("Error reading %s"), fl_filename_name(fname)); + snprintf(szmsg, sizeof(szmsg), _("Error reading %s"), fname); + REQ(write_rxtext, "\n"); + REQ(write_rxtext, szmsg); + REQ(write_rxtext, "\n"); + LOG_ERROR("%s", szmsg); return; } // relaxed file integrity test to all importing from non conforming log programs if (strcasestr(buff, "clearDatabase(); return; @@ -275,11 +277,11 @@ void cAdifIO::do_readfile(const char *fname, cQsoDb *db) } if (!p1) { delete [] buff; - strcpy(szmsg2, "Corrupt ADIF file ***"); - REQ(write_rxtext, "\n*** "); - REQ(write_rxtext, szmsg2); + snprintf(szmsg, sizeof(szmsg), "Corrupt logbook file: %s", fname); REQ(write_rxtext, "\n"); - LOG_ERROR("%s", szmsg2); + REQ(write_rxtext, szmsg); + REQ(write_rxtext, "\n"); + LOG_ERROR("%s", szmsg); return; // must not be an ADIF compliant file } p1 += 1; @@ -311,11 +313,14 @@ void cAdifIO::do_readfile(const char *fname, cQsoDb *db) t0 = t1 - t0; float t = (t0.tv_sec + t0.tv_nsec/1e9); - snprintf(szmsg2, sizeof(szmsg2), "Read %d records in %4.2f seconds", db->nbrRecs(), t); - REQ(write_rxtext, "\n*** "); - REQ(write_rxtext, szmsg2); + snprintf(szmsg, sizeof(szmsg), "\ +Loaded logbook: %s\n\ + %d records in %4.2f seconds", +fname, db->nbrRecs(), t); REQ(write_rxtext, "\n"); - LOG_INFO("%s", szmsg2); + REQ(write_rxtext, szmsg); + REQ(write_rxtext, "\n"); + LOG_INFO("%s", szmsg); if (db == &qsodb) REQ(adif_read_OK); diff --git a/src/logbook/logsupport.cxx b/src/logbook/logsupport.cxx index 1103c036..4bf1b17c 100644 --- a/src/logbook/logsupport.cxx +++ b/src/logbook/logsupport.cxx @@ -275,13 +275,17 @@ void adif_read_OK() void cb_mnuOpenLogbook(Fl_Menu_* m, void* d) { string title = _("Open logbook file"); - string filters; - filters.assign("ADIF\t*.").append(ADIF_SUFFIX); + string filter; + filter.assign("ADIF file\t*.").append(ADIF_SUFFIX); #ifdef __APPLE__ - filters.append("\n"); + filter.append("\n"); #endif - const char* p = FSEL::select( title.c_str(), filters.c_str(), logbook_filename.c_str()); + std::string deffilename = LogsDir; + deffilename.append(fl_filename_name(logbook_filename.c_str())); + + const char* p = FSEL::select( title.c_str(), filter.c_str(), deffilename.c_str()); + if (p) { saveLogbook(); qsodb.deleteRecs(); @@ -303,11 +307,19 @@ void cb_mnuSaveLogbook(Fl_Menu_*m, void* d) { #ifdef __APPLE__ filter.append("\n"); #endif - const char* p = FSEL::saveas( title.c_str(), filter.c_str(), logbook_filename.c_str()); + std::string deffilename = LogsDir; + deffilename.append(fl_filename_name(logbook_filename.c_str())); + + const char* p = FSEL::select( title.c_str(), filter.c_str(), deffilename.c_str()); + if (p) { logbook_filename = p; if (logbook_filename.find("." ADIF_SUFFIX) == string::npos) logbook_filename.append("." ADIF_SUFFIX); + + progdefaults.logbookfilename = logbook_filename; + progdefaults.changed = true; + dlgLogbook->label(fl_filename_name(logbook_filename.c_str())); cQsoDb::reverse = false; @@ -491,7 +503,7 @@ void merge_recs( cQsoDb *db, cQsoDb *mrgdb ) // (haystack, needle) } void cb_mnuMergeADIF_log(Fl_Menu_* m, void* d) { - const char* p = FSEL::select(_("Merge ADIF file"), "ADIF\t*." ADIF_SUFFIX); + const char* p = FSEL::select(_("Merge ADIF file"), "ADIF\t*." ADIF_SUFFIX, LogsDir.c_str()); Fl::wait(); fl_digi_main->redraw(); Fl::awake(); diff --git a/src/misc/macroedit.cxx b/src/misc/macroedit.cxx index c02cab6c..cb08fa6b 100644 --- a/src/misc/macroedit.cxx +++ b/src/misc/macroedit.cxx @@ -327,32 +327,41 @@ void cbInsertMacro(Fl_Widget *, void *) if (text == LINE_SEP) return; if (text == "") { - string filters = "Text\t*." "txt"; - const char* p = FSEL::select(_("Text file to insert"), filters.c_str(), - "text." "txt"); + string filters = "Text\t*.txt"; + const char* p = FSEL::select( + _("Text file to insert"), + filters.c_str(), + HomeDir.c_str()); if (p) { text.insert(6, p); } else text = ""; } else if ((text == "") || (text == "")) { - string filters = "Text\t*." "txt"; - const char* p = FSEL::select(_("Test text file"), filters.c_str(), - "text." "txt"); + string filters = "Text\t*.txt"; + const char* p = FSEL::select( + _("Test text file"), + filters.c_str(), + HomeDir.c_str()); if (p) { text.insert(10, p); } else text = ""; } else if (text == "") { - string filters = "Text\t*." "txt"; - const char *p = FSEL::select(_("MFSK image file"), "*.{png,jpg,bmp}\t*", ""); + string filters = "*.{png,jpg,bmp}\t*.png"; + const char *p = FSEL::select( + _("MFSK image file"), + filters.c_str(), + PicsDir.c_str()); if (p) { text.insert(7, p); } else text = ""; } else if (text == "") { - string filters = "Macrost\t*." "mdf"; - const char* p = FSEL::select(_("Change to Macro file"), filters.c_str(), - "macros." "mdf"); + string filters = "Macrost\t*.mdf"; + const char* p = FSEL::select( + _("Change to Macro file"), + filters.c_str(), + MacrosDir.c_str()); if (p) { text.insert(8, p); } else @@ -360,9 +369,11 @@ void cbInsertMacro(Fl_Widget *, void *) } #ifdef __MINGW32__ else if (text == "") { - string filters = "Exe\t*." "exe"; - const char* p = FSEL::select(_("Executable file to insert"), filters.c_str(), - "WordPad.exe"); + string filters = "Exe\t*.exe"; + const char* p = FSEL::select( + _("Executable file to insert"), + filters.c_str(), + HomeDir.c_str()); if (p) { string exefile = p; exefile.append(""); diff --git a/src/misc/macros.cxx b/src/misc/macros.cxx index a193a279..f41ff13d 100644 --- a/src/misc/macros.cxx +++ b/src/misc/macros.cxx @@ -2957,7 +2957,15 @@ void MACROTEXT::loadDefault() #endif if (progdefaults.DisplayMacroFilename) { string Macroset; - Macroset.assign("\nMacros: ").append(progStatus.LastMacroFile).append("\n"); + Macroset.assign("Read macro file: ").append(progStatus.LastMacroFile); +#ifdef __WOE32__ + size_t p = string::npos; + while ( (p = Macroset.find("/")) != string::npos) + Macroset[p] = '\\'; +#endif + LOG_INFO("%s", Macroset.c_str()); + Macroset.insert(0, "\n"); + Macroset.append("\n"); ReceiveText->addstr(Macroset); } } @@ -2979,12 +2987,13 @@ void MACROTEXT::openMacroFile() if (p) { loadMacros(p); progStatus.LastMacroFile = p; - } - showMacroSet(); - if (progdefaults.DisplayMacroFilename) { - string Macroset; - Macroset.assign("\nMacros: ").append(progStatus.LastMacroFile).append("\n"); - ReceiveText->addstr(Macroset); +// } + showMacroSet(); + if (progdefaults.DisplayMacroFilename) { + string Macroset; + Macroset.assign("\nLoaded macros: ").append(progStatus.LastMacroFile).append("\n"); + ReceiveText->addstr(Macroset); + } } }