FLTK logo

[RFE] STR #3520: Fixing a FileChooser feature

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 All Forums  |  Back to fltk.bugs  ]
 
Previous Message ]New Message | Reply ]Next Message ]

[RFE] STR #3520: Fixing a FileChooser feature peter fuerst Apr 24, 2019  
 
DO NOT REPLY TO THIS MESSAGE.  INSTEAD, POST ANY RESPONSES TO THE LINK BELOW.

[STR New]

Link: https://www.fltk.org/str.php?L3520
Version: 1.4-feature


Hello,

attached you find patches to allow the File Chooser to keep the initial/
suggested name-portion in the pathname of a file to be saved, when
changing directories in the process.
The patch is essentialy the same, that i submitted in October 2010 for
FLTK 2.0 (see below), using the Dillo 2.x web-browser then. And which
was seemingly incorporated sometime later. (At least the description at
https://www.fltk.org/doc-2.0/html/classfltk_1_1FileChooser.html
#a970cca52004fca5a0d9f9b8261bc429b suggests this)

Several years ago i upgraded to Dillo 3.0.x, which had switched to FLTK
1.3. This urged me (with a little delay though ;) to adapt the old patch
to FLTK 1.3.4-2. Since the affected files in 1.3.5 are identical (modulo
versioning tags) to the corresponding ones in 1.3.4-2, this patch also
fits 1.3.5.  Version 1.4 got its own (version of this) patch.

kind regards

peter fuerst


Date: Wed, 27 Oct 2010 02:54:19 -0700
From: fltk-bugs-bounces@easysw.com
To: post@pfrst.de
Subject: Your message to fltk-bugs awaits moderator approval
Your mail to 'fltk-bugs' with the subject
    Fixing a fltk::FileChooser "feature"
Is being held until the list moderator can review it for approval.
The reason it is being held:
Post by non-member to a members-only list
Either the message will get posted to the list, or you will receive
notification of the moderator's decision.  If you would like to cancel
this posting, please visit the following URL:
http://lists.easysw.com/mailman/confirm/fltk-bugs/
fca4275918188af96d68f6b89e9416bc818330f9


Link: https://www.fltk.org/str.php?L3520
Version: 1.4-feature
FileChooser.1.3.4-2.diff                                                                            0000644 0000764 0000144 00000027167 13457166634 013277  0                                                                                                    ustar   pf                              users                                                                                                                                                                                                                  

	This comment is taken from the fltk-2.0.x patch, with identifiers
	"translated" accordingly:

	Using the Dillo web-browser i could experience some rather nasty
	nuisance: whenever changing directory in the dialog for choosing
	where to save a file, the (suggested or just before selected)
	filename is erased and only the directory is displayed for
	further selecting.
	Closer examination showed that there is no way to change this
	behaviour outside FLTK, that in fact fltk::FileChooser was the
	culprit.

	So, here comes a patch to fix this issue (i hope to use FLTK's
	next release "out of the box" ;-):

	1) Fl_File_Chooser::directory(..) no longer simply overwrites
	   fileName with directory_. Now it retains the basename in there,
	   if it is not a directory and is existing or to be created.
	   A boolean parameter allows to control whether fileName should be
	   overwritten by directory_ at all (e.g. given, when called from
	   Fl_File_Chooser::value(..)).

	2) Changing directory in Fl_File_Input::handle_button(..) now also
	   retains the basename if appropriate, since it looks - let's
	   say - not easy to handle this correctly at an upper level.
	   (It maybe possible though, by examining the FileInput flags
	   - fileNameCB(Fl_File_Input*,void*) instead of fileNameCB() - to
	   find out how the change was done and by always maintaining
	   an additional fileName-backup in Fl_File_Chooser. But didn't do
	   any deeper investigation into that yet.)

	besides:

	3) Consistency of directory_ and fileName is now forced upon
	   return from each of Fl_File_Chooser::directory(..) and
	   Fl_File_Chooser::value(..).  Fl_File_Chooser::rescan() is no
	   longer involved in updating/overwriting fileName.
	   (IMHO, rescan() is really not the place to do that. Let alone
	   making this adjustment dependent on window state!)          


	Unlike in the FLTK 2.0 patch, no private directory(const char*, bool)
	is introduced. Instead the public directory() is augmented with the
	boolean parameter, with default value "true". (Making the switch
	public should hardly do any harm).

--- a/fltk-1.3.4-2/FL/Fl_File_Chooser.H	2016/09/20 12:57:18
+++ b/fltk-1.3.4-2/FL/Fl_File_Chooser.H	2018/07/07 22:30:58
@@ -65,6 +65,7 @@
   void showChoiceCB(); 
   void update_favorites(); 
   void update_preview(); 
+  void activate_okButton_if_file();
 public:
   Fl_File_Chooser(const char *d, const char *p, int t, const char *title);
 private:
@@ -132,7 +133,7 @@
   void color(Fl_Color c);
   Fl_Color color();
   int count(); 
-  void directory(const char *d); 
+  void directory(const char *d, bool f = true);
   char * directory();
   void filter(const char *p); 
   const char * filter();


--- a/fltk-1.3.4-2/FL/filename.H	2012/10/19 11:23:51
+++ b/fltk-1.3.4-2/FL/filename.H	2018/07/05 20:32:52
@@ -59,6 +59,7 @@
 FL_EXPORT int fl_filename_relative(char *to, int tolen, const char *from);
 FL_EXPORT int fl_filename_match(const char *name, const char *pattern);
 FL_EXPORT int fl_filename_isdir(const char *name);
+FL_EXPORT int fl_filename_isfile(const char *name);
 
 #  if defined(__cplusplus) && !defined(FL_DOXYGEN)
 /*


--- a/fltk-1.3.4-2/src/Fl_File_Chooser.fl	2015/12/19 06:35:26
+++ b/fltk-1.3.4-2/src/Fl_File_Chooser.fl	2018/07/07 22:30:58
@@ -68,6 +68,8 @@ class FL_EXPORT Fl_File_Chooser {open
   }
   decl {void update_preview();} {private local
   }
+  decl {void activate_okButton_if_file();} {
+  }
   Function {Fl_File_Chooser(const char *d, const char *p, int t, const char *title)} {} {
     code {if (!prefs_) {
   prefs_ = new Fl_Preferences(Fl_Preferences::USER, "fltk.org", "filechooser");
@@ -267,7 +269,7 @@ data_     = d;} {}
   }
   decl {int count();} {public local
   }
-  decl {void directory(const char *d);} {public local
+  decl {void directory(const char *d, bool f = true);} {public local
   }
   Function {directory()} {return_type {char *}
   } {


--- a/fltk-1.3.4-2/src/Fl_File_Chooser2.cxx	2016/07/15 20:01:08
+++ b/fltk-1.3.4-2/src/Fl_File_Chooser2.cxx	2018/07/07 22:30:58
@@ -455,7 +455,8 @@ Fl_File_Chooser::count() {
 //
 
 void
-Fl_File_Chooser::directory(const char *d)// I - Directory to change to
+Fl_File_Chooser::directory(const char *d,// I - Directory to change to
+                       bool       f)// I - update file name field?
 {
   char	*dirptr;			// Pointer into directory
 
@@ -518,6 +519,24 @@ Fl_File_Chooser::directory(const char *d
   else
     directory_[0] = '\0';
 
+  if (f) {
+    // Update the current filename accordingly...
+    char pathname[sizeof(directory_)];	// New pathname for filename field
+
+    strlcpy(pathname, directory_, sizeof(pathname));
+    if (pathname[0] && pathname[strlen(pathname) - 1] != '/')
+      strlcat(pathname, "/", sizeof(pathname));              
+
+    // Prevent users from cursing us: keep basename, if not a directory
+    if (!fl_filename_isdir(fileName->value())) {                     
+      dirptr = strchr(pathname, 0);               
+      strlcat(pathname, fl_filename_name(fileName->value()), sizeof(pathname));
+      if (!(type_ & CREATE) && !fl_filename_isfile(pathname))
+        *dirptr = 0;                                            
+    }
+    fileName->value(pathname);
+  }
+
   if (shown()) {
     // Rescan the directory...
     rescan();
@@ -774,7 +793,10 @@ Fl_File_Chooser::fileListCB()
     if (*filename == '/') *filename = '\0';
 
 //    puts("Setting fileName from fileListCB...");
-    fileName->value(pathname);
+    if (!*pathname || fl_filename_isdir(pathname))
+      directory(pathname);
+    else
+      fileName->value(pathname);
 
     // Update the preview box...
     Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this);
@@ -784,7 +806,7 @@ Fl_File_Chooser::fileListCB()
     if (callback_) (*callback_)(this, data_);
 
     // Activate the OK button as needed...
-    if (!_fl_filename_isdir_quick(pathname) || (type_ & DIRECTORY))
+    if (!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY))
       okButton->activate();
     else
       okButton->deactivate();
@@ -857,7 +879,7 @@ Fl_File_Chooser::fileNameCB()
     if (_fl_filename_isdir_quick(pathname) &&
 	compare_dirnames(pathname, directory_)) {
 #endif /* WIN32 || __EMX__ */
-      directory(pathname);
+      directory(pathname, false);
     } else if ((type_ & CREATE) || access(pathname, 0) == 0) {
       if (!_fl_filename_isdir_quick(pathname) || (type_ & DIRECTORY)) {
 	// Update the preview box...
@@ -896,7 +918,7 @@ Fl_File_Chooser::fileNameCB()
       int p = fileName->position();
       int m = fileName->mark();
 
-      directory(pathname);
+      directory(pathname, false);
 
       if (filename[0]) {
 	char tempname[FL_PATH_MAX];
@@ -982,22 +1004,13 @@ Fl_File_Chooser::fileNameCB()
     }
 
     // See if we need to enable the OK button...
-    if (((type_ & CREATE) || !access(fileName->value(), 0)) &&
-        (!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY))) {
-      okButton->activate();
-    } else {
-      okButton->deactivate();
-    }
+    activate_okButton_if_file();
+
   } else {
     // FL_Delete or FL_BackSpace
     fileList->deselect(0);
     fileList->redraw();
-    if (((type_ & CREATE) || !access(fileName->value(), 0)) &&
-        (!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY))) {
-      okButton->activate();
-    } else {
-      okButton->deactivate();
-    }
+    activate_okButton_if_file();
   }
 }
 
@@ -1139,21 +1152,7 @@ Fl_File_Chooser::previewCB(Fl_File_Choos
 void
 Fl_File_Chooser::rescan()
 {
-  char	pathname[FL_PATH_MAX];		// New pathname for filename field
-
-
-  // Clear the current filename
-  strlcpy(pathname, directory_, sizeof(pathname));
-  if (pathname[0] && pathname[strlen(pathname) - 1] != '/') {
-    strlcat(pathname, "/", sizeof(pathname));
-  }
-//  puts("Setting fileName in rescan()");
-  fileName->value(pathname);
-
-  if (type_ & DIRECTORY)
-    okButton->activate();
-  else
-    okButton->deactivate();
+  activate_okButton_if_file();
 
   // Build the file list...
   fileList->load(directory_, sort);
@@ -1534,7 +1533,7 @@ Fl_File_Chooser::value(const char *filen
   // See if the filename is the "My System" directory...
   if (filename == NULL || !filename[0]) {
     // Yes, just change the current directory...
-    directory(filename);
+    directory(filename, false);
     fileName->value("");
     okButton->deactivate();
     return;
@@ -1559,18 +1558,20 @@ Fl_File_Chooser::value(const char *filen
 
   if ((slash = strrchr(pathname, '/')) != NULL) {
     // Yes, change the display to the directory... 
-    if (!fl_filename_isdir(pathname)) *slash++ = '\0';
+    if (fl_filename_isdir(pathname))
+      slash = pathname;
+    else
+      *slash++ = 0;
 
-    directory(pathname);
-    if (*slash == '/') slash = pathname;
+    directory(pathname, false);
+    if (!shown()) fileList->load(pathname);
+    if (slash > pathname) slash[-1] = '/';
   } else {
-    directory(".");
+    directory(".", false);
     slash = pathname;
   }
 
   // Set the input field to the absolute path...
-  if (slash > pathname) slash[-1] = '/';
-
   fileName->value(pathname);
   fileName->position(0, (int) strlen(pathname));
   okButton->activate();
@@ -1593,6 +1594,16 @@ Fl_File_Chooser::value(const char *filen
       break;
     }
 }
+
+void
+Fl_File_Chooser::activate_okButton_if_file()
+{
+    if (((type_ & CREATE) || !access(fileName->value(), 0)) &&
+        (!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY)))
+      okButton->activate();
+    else
+      okButton->deactivate();
+}
   
 void Fl_File_Chooser::show()
 {


	This comment is taken from the fltk-2.0.x patch, with identifiers
	"translated" accordingly:

	class Fl_File_Input should have some 'ftype_' field (CREATE, DIRECTORY,
	...) to reflect its caller's intentions. For now - since the input is
	checked for "(type_ & CREATE) || fl_filename_isfile()" at the upper
	level (Fl_File_Chooser) anyway - we get away without defining it
	and its corresponding methods (leaving a Fl_File_Input object even
	binary compatible :-)

--- a/fltk-1.3.4-2/src/Fl_File_Input.cxx	2012/04/05 05:12:30
+++ b/fltk-1.3.4-2/src/Fl_File_Input.cxx	2018/07/05 22:09:32
@@ -272,12 +272,30 @@ Fl_File_Input::handle_button(int event)
 
   if (i < 0) {
     // Found the end; truncate the value and update the buttons...
-    *start = '\0';
-    value(newvalue, (int) (start - newvalue) );
+    const char *basename = 0;
+    if (!fl_filename_isdir(newvalue))
+    	if (!*(basename = fl_filename_name(newvalue)))
+    	  basename = 0;
 
-    // Then do the callbacks, if necessary...
-    set_changed();
-    if (when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE) ) do_callback();
+    if (!basename)
+    	*start = '\0';
+    else {
+    	// Prevent users from cursing us: keep basename, if not a directory
+    	memmove(start, basename, strlen(basename)+1);
+    	// Should have some 'ftype_' field to reflect the caller's
+    	// intentions, but for now we get along without...
+    	//if (!(ftype_ & CREATE) && !fl_filename_isfile(newvalue))
+		//*start = 0;
+    	//else
+		if (start == basename) i = 0; // unchanged!
+    }
+    if (i < 0) {
+    	value(newvalue);
+
+    	// Then do the callbacks, if necessary...
+    	set_changed();
+    	if (when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE) ) do_callback();
+    }
   }
 
   return 1;


--- a/fltk-1.3.4-2/src/filename_isdir.cxx	2012/04/05 05:12:30
+++ b/fltk-1.3.4-2/src/filename_isdir.cxx	2018/07/05 23:07:39
@@ -89,6 +89,12 @@ int fl_filename_isdir(const char* n) {
   return !fl_stat(n, &s) && (s.st_mode&0170000)==0040000;
 }
 
+/** Returns true if the file exists and is a regular file. */        
+int fl_filename_isfile(const char* name) {               
+  struct stat	s;
+  return !fl_stat(name, &s) && (s.st_mode&0170000)==0100000;
+}
+
 //
 // End of "$Id: filename_isdir.cxx 9325 2012-04-05 05:12:30Z fabien $".
 //


                                                                                                                                                                                                                                                                                                                                                                                                         FileChooser.1.4.0.diff                                                                              0000644 0000764 0000144 00000027056 13457201650 013116  0                                                                                                    ustar   pf                              users                                                                                                                                                                                                                  

	This comment is taken from the fltk-2.0.x patch, with identifiers
	"translated" accordingly:

	Using the Dillo web-browser i could experience some rather nasty
	nuisance: whenever changing directory in the dialog for choosing
	where to save a file, the (suggested or just before selected)
	filename is erased and only the directory is displayed for
	further selecting.
	Closer examination showed that there is no way to change this
	behaviour outside FLTK, that in fact fltk::FileChooser was the
	culprit.

	So, here comes a patch to fix this issue (i hope to use FLTK's
	next release "out of the box" ;-):

	1) Fl_File_Chooser::directory(..) no longer simply overwrites
	   fileName with directory_. Now it retains the basename in there,
	   if it is not a directory and is existing or to be created.
	   A boolean parameter allows to control whether fileName should be
	   overwritten by directory_ at all (e.g. given, when called from
	   Fl_File_Chooser::value(..)).

	2) Changing directory in Fl_File_Input::handle_button(..) now also
	   retains the basename if appropriate, since it looks - let's
	   say - not easy to handle this correctly at an upper level.
	   (It maybe possible though, by examining the FileInput flags
	   - fileNameCB(Fl_File_Input*,void*) instead of fileNameCB() - to
	   find out how the change was done and by always maintaining
	   an additional fileName-backup in Fl_File_Chooser. But didn't do
	   any deeper investigation into that yet.)

	besides:

	3) Consistency of directory_ and fileName is now forced upon
	   return from each of Fl_File_Chooser::directory(..) and
	   Fl_File_Chooser::value(..).  Fl_File_Chooser::rescan() is no
	   longer involved in updating/overwriting fileName.
	   (IMHO, rescan() is really not the place to do that. Let alone
	   making this adjustment dependent on window state!)          


	Unlike in the FLTK 2.0 patch, no private directory(const char*, bool)
	is introduced. Instead the public directory() is augmented with the
	boolean parameter, with default value "true". (Making the switch
	public should hardly do any harm).

--- a/fltk-1.4.x-20190419-8d064773/FL/Fl_File_Chooser.H
+++ b/fltk-1.4.x-20190419-8d064773/FL/Fl_File_Chooser.H
@@ -65,6 +65,7 @@
   void showChoiceCB(); 
   void update_favorites(); 
   void update_preview(); 
+  void activate_okButton_if_file();
 public:
   Fl_File_Chooser(const char *d, const char *p, int t, const char *title);
 private:
@@ -132,7 +133,7 @@
   void color(Fl_Color c);
   Fl_Color color();
   int count(); 
-  void directory(const char *d); 
+  void directory(const char *d, bool f = true);
   char * directory();
   void filter(const char *p); 
   const char * filter();


--- a/fltk-1.4.x-20190419-8d064773/FL/filename.H
+++ b/fltk-1.4.x-20190419-8d064773/FL/filename.H
@@ -54,6 +54,7 @@
 FL_EXPORT int fl_filename_relative(char *to, int tolen, const char *from);
 FL_EXPORT int fl_filename_match(const char *name, const char *pattern);
 FL_EXPORT int fl_filename_isdir(const char *name);
+FL_EXPORT int fl_filename_isfile(const char *name);
 
 #  if defined(__cplusplus) && !defined(FL_DOXYGEN)
 /*


--- a/fltk-1.4.x-20190419-8d064773/src/Fl_File_Chooser.fl
+++ b/fltk-1.4.x-20190419-8d064773/src/Fl_File_Chooser.fl
@@ -68,6 +68,8 @@ class FL_EXPORT Fl_File_Chooser {open
   }
   decl {void update_preview();} {private local
   }
+  decl {void activate_okButton_if_file();} {
+  }
   Function {Fl_File_Chooser(const char *d, const char *p, int t, const char *title)} {} {
     code {if (!prefs_) {
   prefs_ = new Fl_Preferences(Fl_Preferences::USER, "fltk.org", "filechooser");
@@ -267,7 +269,7 @@ data_     = d;} {}
   }
   decl {int count();} {public local
   }
-  decl {void directory(const char *d);} {public local
+  decl {void directory(const char *d, bool f = true);} {public local
   }
   Function {directory()} {return_type {char *}
   } {


--- a/fltk-1.4.x-20190419-8d064773/src/Fl_File_Chooser2.cxx
+++ b/fltk-1.4.x-20190419-8d064773/src/Fl_File_Chooser2.cxx
@@ -430,7 +430,8 @@ Fl_File_Chooser::count() {
 //
 
 void
-Fl_File_Chooser::directory(const char *d)// I - Directory to change to
+Fl_File_Chooser::directory(const char *d,// I - Directory to change to
+                       bool       f)// I - update file name field?
 {
   char	*dirptr;			    // Pointer into directory
   char  fixpath[FL_PATH_MAX];   // Path with slashes converted
@@ -489,6 +490,24 @@ Fl_File_Chooser::directory(const char *d
   else
     directory_[0] = '\0';
 
+  if (f) {
+    // Update the current filename accordingly...
+    char pathname[sizeof(directory_)];	// New pathname for filename field
+
+    strlcpy(pathname, directory_, sizeof(pathname));
+    if (pathname[0] && pathname[strlen(pathname) - 1] != '/')
+      strlcat(pathname, "/", sizeof(pathname));              
+
+    // Prevent users from cursing us: keep basename, if not a directory
+    if (!fl_filename_isdir(fileName->value())) {                     
+      dirptr = strchr(pathname, 0);               
+      strlcat(pathname, fl_filename_name(fileName->value()), sizeof(pathname));
+      if (!(type_ & CREATE) && !fl_filename_isfile(pathname))
+        *dirptr = 0;                                            
+    }
+    fileName->value(pathname);
+  }
+
   if (shown()) {
     // Rescan the directory...
     rescan();
@@ -743,7 +762,10 @@ Fl_File_Chooser::fileListCB()
     if (*filename == '/') *filename = '\0';
 
 //    puts("Setting fileName from fileListCB...");
-    fileName->value(pathname);
+    if (!*pathname || fl_filename_isdir(pathname))
+      directory(pathname);
+    else
+      fileName->value(pathname);
 
     // Update the preview box...
     Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this);
@@ -753,7 +775,7 @@ Fl_File_Chooser::fileListCB()
     if (callback_) (*callback_)(this, data_);
 
     // Activate the OK button as needed...
-    if (!Fl::system_driver()->filename_isdir_quick(pathname) || (type_ & DIRECTORY))
+    if (!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY))
       okButton->activate();
     else
       okButton->deactivate();
@@ -818,7 +840,7 @@ Fl_File_Chooser::fileNameCB()
     if (Fl::system_driver()->colon_is_drive()) condition = isalpha(pathname[0] & 255) && pathname[1] == ':' && !pathname[2];
     if (!condition) condition = ( Fl::system_driver()->filename_isdir_quick(pathname) && compare_dirnames(pathname, directory_) );
     if (condition) {
-      directory(pathname);
+      directory(pathname, false);
     } else if ((type_ & CREATE) || fl_access(pathname, 0) == 0) {
       if (!Fl::system_driver()->filename_isdir_quick(pathname) || (type_ & DIRECTORY)) {
 	// Update the preview box...
@@ -853,7 +875,7 @@ Fl_File_Chooser::fileNameCB()
       int p = fileName->position();
       int m = fileName->mark();
 
-      directory(pathname);
+      directory(pathname, false);
 
       if (filename[0]) {
 	char tempname[FL_PATH_MAX];
@@ -933,22 +955,13 @@ Fl_File_Chooser::fileNameCB()
     }
 
     // See if we need to enable the OK button...
-    if (((type_ & CREATE) || !fl_access(fileName->value(), 0)) &&
-        (!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY))) {
-      okButton->activate();
-    } else {
-      okButton->deactivate();
-    }
+    activate_okButton_if_file();
+
   } else {
     // FL_Delete or FL_BackSpace
     fileList->deselect(0);
     fileList->redraw();
-    if (((type_ & CREATE) || !fl_access(fileName->value(), 0)) &&
-        (!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY))) {
-      okButton->activate();
-    } else {
-      okButton->deactivate();
-    }
+    activate_okButton_if_file();
   }
 }
 
@@ -1082,21 +1095,7 @@ Fl_File_Chooser::previewCB(Fl_File_Choos
 void
 Fl_File_Chooser::rescan()
 {
-  char	pathname[FL_PATH_MAX];		// New pathname for filename field
-
-
-  // Clear the current filename
-  strlcpy(pathname, directory_, sizeof(pathname));
-  if (pathname[0] && pathname[strlen(pathname) - 1] != '/') {
-    strlcat(pathname, "/", sizeof(pathname));
-  }
-//  puts("Setting fileName in rescan()");
-  fileName->value(pathname);
-
-  if (type_ & DIRECTORY)
-    okButton->activate();
-  else
-    okButton->deactivate();
+  activate_okButton_if_file();
 
   // Build the file list...
   fileList->load(directory_, sort);
@@ -1470,7 +1469,7 @@ Fl_File_Chooser::value(const char *filen
   // See if the filename is the "My System" directory...
   if (filename == NULL || !filename[0]) {
     // Yes, just change the current directory...
-    directory(filename);
+    directory(filename, false);
     fileName->value("");
     okButton->deactivate();
     return;
@@ -1495,12 +1494,16 @@ Fl_File_Chooser::value(const char *filen
 
   if ((slash = strrchr(pathname, '/')) != NULL) {
     // Yes, change the display to the directory... 
-    if (!fl_filename_isdir(pathname)) *slash++ = '\0';
+    if (fl_filename_isdir(pathname))
+      slash = pathname;
+    else
+      *slash++ = '\0';
 
-    directory(pathname);
-    if (*slash == '/') slash = pathname;
+    directory(pathname, false);
+    if (!shown()) fileList->load(pathname);
+    if (slash > pathname) slash[-1] = '/';
   } else {
-    directory(".");
+    directory(".", false);
     slash = pathname;
   }
 
@@ -1525,6 +1528,16 @@ Fl_File_Chooser::value(const char *filen
       break;
     }
 }
+
+void
+Fl_File_Chooser::activate_okButton_if_file()
+{
+    if (((type_ & CREATE) || !fl_access(fileName->value(), 0)) &&
+        (!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY)))
+      okButton->activate();
+    else
+      okButton->deactivate();
+}
   
 void Fl_File_Chooser::show()
 {


	This comment is taken from the fltk-2.0.x patch, with identifiers
	"translated" accordingly:

	class Fl_File_Input should have some 'ftype_' field (CREATE, DIRECTORY,
	...) to reflect its caller's intentions. For now - since the input is
	checked for "(type_ & CREATE) || fl_filename_isfile()" at the upper
	level (Fl_File_Chooser) anyway - we get away without defining it
	and its corresponding methods (leaving a Fl_File_Input object even
	binary compatible :-)

--- a/fltk-1.4.x-20190419-8d064773/src/Fl_File_Input.cxx
+++ b/fltk-1.4.x-20190419-8d064773/src/Fl_File_Input.cxx
@@ -267,12 +267,30 @@ Fl_File_Input::handle_button(int event)
 
   if (i < 0) {
     // Found the end; truncate the value and update the buttons...
-    *start = '\0';
-    value(newvalue, (int) (start - newvalue) );
+    const char *basename = 0;
+    if (!fl_filename_isdir(newvalue))
+    	if (!*(basename = fl_filename_name(newvalue)))
+    	  basename = 0;
 
-    // Then do the callbacks, if necessary...
-    set_changed();
-    if (when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE) ) do_callback();
+    if (!basename)
+    	*start = '\0';
+    else {
+    	// Prevent users from cursing us: keep basename, if not a directory
+    	memmove(start, basename, strlen(basename)+1);
+    	// Should have some 'ftype_' field to reflect the caller's
+    	// intentions, but for now we get along without...
+    	//if (!(ftype_ & CREATE) && !fl_filename_isfile(newvalue))
+		//*start = 0;
+    	//else
+		if (start == basename) i = 0; // unchanged!
+    }
+    if (i < 0) {
+    	value(newvalue);
+
+    	// Then do the callbacks, if necessary...
+    	set_changed();
+    	if (when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE) ) do_callback();
+    }
   }
 
   return 1;


--- a/fltk-1.4.x-20190419-8d064773/src/filename_isdir.cxx
+++ b/fltk-1.4.x-20190419-8d064773/src/filename_isdir.cxx
@@ -81,6 +81,12 @@ int Fl_System_Driver::filename_isdir(con
  \endcond
  */
 
+/** Returns true if the file exists and is a regular file. */        
+int fl_filename_isfile(const char* name) {               
+  struct stat	s;
+  return !fl_stat(name, &s) && (s.st_mode&0170000)==0100000;
+}
+
 //
 // End of "$Id$".
 //


                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
Direct Link to Message ]
 
     
Previous Message ]New Message | Reply ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.