DO NOT REPLY TO THIS MESSAGE.  INSTEAD, POST ANY RESPONSES TO THE LINK BELOW.

[STR New]

Link: http://www.fltk.org/str.php?L2488
Version: 2.0-current


This was originally a message by Peter Fuerst to the fltk.bugs group (saved
at 
http://www.fltk.org/newsgroups.php?s1+gfltk.bugs+v9+T+Qfltk%3A%3AFileChooser+%22feature%22),
reposted here in an effort to save the patch. I don't claim any credit for
this!

-----

Hello,

using the Dillo web-browser i could experience a 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...

Attached you find a patch, that will fix this issue.


kind regards

peter

---------

Further, this patch also fixes STR #1702
(http://www.fltk.org/str.php?L1702).

Whilst there're perhaps some style issues with this patch (such as
accessing slash[-1]), this does somewhat clean up code inside FileBrowser
as well as spring-clean bugs, and thus is probably worth checking in, with
a small modification or two....


Link: http://www.fltk.org/str.php?L2488
Version: 2.0-current
Index: src/FileInput.cxx
===================================================================
--- src/FileInput.cxx   (revision 8026)
+++ src/FileInput.cxx   (working copy)
@@ -27,6 +27,7 @@
 //
 
 #include <fltk/FileInput.h>
+#include <fltk/filename.h>
 #include <fltk/Window.h>
 #include <fltk/draw.h>
 #include <fltk/damage.h>
@@ -333,13 +334,33 @@
     }
 
     if (i < 0) {
+       char c = *start; // possibly start == basename
+       const char *basename = 0;
+       if (!fltk::filename_isdir(newtext))
+           if (!*(basename = fltk::filename_name(newtext)))
+               basename = 0;
+
        // Found the end; truncate the text and update the buttons...
        *start = '\0';
-       text(newtext, start - newtext);
 
-       // Then do the callbacks, if necessary...
-       set_changed();
-       if (when() & WHEN_CHANGED) do_callback();
+       // Prevent users from cursing us: keep basename, if not a directory
+       if (basename) {
+           *start = c;
+           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) && !fltk::filename_isfile(newtext))
+               //*start = 0;
+           //else
+               if (start == basename) i = 0; // unchanged!
+       }
+       if (i < 0) {
+           text(newtext);
+
+           // Then do the callbacks, if necessary...
+           set_changed();
+           if (when() & WHEN_CHANGED) do_callback();
+       }
     }
 
     return 1;
Index: src/FileChooser.fl
===================================================================
--- src/FileChooser.fl  (revision 8026)
+++ src/FileChooser.fl  (working copy)
@@ -62,6 +62,8 @@
     decl {void update_favorites();} {}
     decl {void update_preview();} {}
     decl {int favorites_showing;} {}
+    decl {void activate_okButton_if_file();} {}
+    decl {void directory(const char *d, bool);} {}
     Function {FileChooser(const char *d, const char *p, int t, const char 
*title)} {open
     } {
       {fltk::Window} window {
Index: src/FileChooser2.cxx
===================================================================
--- src/FileChooser2.cxx        (revision 8026)
+++ src/FileChooser2.cxx        (working copy)
@@ -26,17 +26,19 @@
 //
 // Contents:
 //
-//   FileChooser::count()             - Return the number of selected files.
-//   FileChooser::directory()         - Set the directory in the file chooser.
-//   FileChooser::filter()            - Set the filter(s) for the chooser.
-//   FileChooser::newdir()            - Make a new directory.
-//   FileChooser::value()             - Return a selected filename.
-//   FileChooser::rescan()            - Rescan the current directory.
-//   FileChooser::favoritesButtonCB() - Handle favorites selections.
-//   FileChooser::fileListCB()        - Handle clicks (and double-clicks)
-//                                          in the Fl_File_Browser.
-//   FileChooser::fileNameCB()        - Handle text entry in the FileBrowser.
-//   FileChooser::showChoiceCB()      - Handle show selections.
+//   FileChooser::count()                     - Return the number of selected 
files.
+//   FileChooser::directory()                 - Set the directory in the file 
chooser.
+//   FileChooser::filter()                    - Set the filter(s) for the 
chooser.
+//   FileChooser::newdir()                    - Make a new directory.
+//   FileChooser::value()                     - Return a selected filename.
+//   FileChooser::rescan()                    - Rescan the current directory.
+//   FileChooser::favoritesButtonCB()         - Handle favorites selections.
+//   FileChooser::fileListCB()                - Handle clicks (and 
double-clicks)
+//                                                  in the FileBrowser.
+//   FileChooser::fileNameCB()                - Handle text entry in the 
FileBrowser.
+//   FileChooser::showChoiceCB()              - Handle show selections.
+//   FileChooser::activate_okButton_if_file() - Ungrey the OK button if the 
user
+//                                                  chooses a file
 //   compare_dirnames()                   - Compare two directory names.
 //   quote_pathname()                     - Quote a pathname for a menu.
 //   unquote_pathname()                   - Unquote a pathname from a menu.
@@ -157,6 +159,13 @@
 void
 FileChooser::directory(const char *d)// I - Directory to change to
 {
+  return directory(d, true);
+}
+
+void
+FileChooser::directory(const char *d,// I - Directory to change to
+                       bool       f)// I - update file name field?
+{
   char *dirptr;                        // Pointer into directory
 
 
@@ -218,6 +227,24 @@
   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 (!fltk::filename_isdir(fileName->text())) {
+      dirptr = strchr(pathname, 0);
+      strlcat(pathname, fltk::filename_name(fileName->text()), 
sizeof(pathname));
+      if (!(type_ & CREATE) && !fltk::filename_isfile(pathname))
+        *dirptr = 0;
+    }
+    fileName->text(pathname);
+  }
+
   if (shown()) {
     // Rescan the directory...
     rescan();
@@ -421,7 +448,7 @@
 #endif /* WIN32 || __EMX__ */
     {
       // Change directories...
-      directory(pathname);
+      directory(pathname, true);
 
       // Reset the click count so that a click in the same spot won't
       // be treated as a triple-click.  We use a value of -1 because
@@ -464,7 +491,10 @@
     if (*filename == '/') *filename = '\0';
 
 //    puts("Setting fileName from fileListCB...");
-    fileName->value(pathname);
+    if (fltk::filename_isdir(pathname))
+      directory(pathname, true);
+    else
+      fileName->value(pathname);
 
     // Update the preview box...
     fltk::remove_timeout((TimeoutHandler)previewCB, this);
@@ -474,7 +504,7 @@
     if (callback_) (*callback_)(this, data_);
 
     // Activate the OK button as needed...
-    if (!fltk::filename_isdir(pathname) || (type_ & DIRECTORY))
+    if (!fltk::filename_isdir(fileName->text()) || (type_ & DIRECTORY))
       okButton->activate();
     else
       okButton->deactivate();
@@ -541,7 +571,7 @@
     if (fltk::filename_isdir(pathname) &&
        compare_dirnames(pathname, directory_)) {
 #endif /* WIN32 || __EMX__ */
-      directory(pathname);
+      directory(pathname, false);
     } else if ((type_ & CREATE) || access(pathname, 0) == 0) {
       if (!fltk::filename_isdir(pathname) || (type_ & DIRECTORY)) {
        // Update the preview box...
@@ -580,7 +610,7 @@
       int p = fileName->position();
       int m = fileName->mark();
 
-      directory(pathname);
+      directory(pathname, false);
 
       if (filename[0]) {
        char tempname[1024];
@@ -663,22 +693,13 @@
     }
 
     // See if we need to enable the OK button...
-    if (((type_ & CREATE) || !access(fileName->text(), 0)) &&
-        (!fltk::filename_isdir(fileName->text()) || (type_ & DIRECTORY))) {
-      okButton->activate();
-    } else {
-      okButton->deactivate();
-    }
+    activate_okButton_if_file();
+
   } else {
     // fltk::DeleteKey or fltk::BackSpace
     fileList->deselect(0);
     fileList->redraw();
-    if (((type_ & CREATE) || !access(fileName->text(), 0)) &&
-        (!fltk::filename_isdir(fileName->text()) || (type_ & DIRECTORY))) {
-      okButton->activate();
-    } else {
-      okButton->deactivate();
-    }
+    activate_okButton_if_file();
   }
 }
 
@@ -822,22 +843,8 @@
 void
 FileChooser::rescan()
 {
-  char pathname[1024];         // New pathname for filename field
+  activate_okButton_if_file();
 
-
-  // 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->text(pathname);
-
-  if (type_ & DIRECTORY)
-    okButton->activate();
-  else
-    okButton->deactivate();
-
   // Build the file list...
   fileList->load(directory_, sort);
 
@@ -1103,7 +1110,7 @@
   // 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;
@@ -1125,25 +1132,24 @@
 
   // See if there is a directory in there...
   fltk::filename_absolute(pathname, sizeof(pathname), filename);
-  char dir[1024]="";
-  strlcpy(dir,pathname,sizeof(dir));
-  if ((slash = strrchr(dir, '/')) != NULL) {
+  if ((slash = strrchr(pathname, '/')) != NULL) {
     // Yes, change the display to the directory... 
-    if (!fltk::filename_isdir(dir)) *slash++ = '\0';
+    if (fltk::filename_isdir(pathname))
+      slash = pathname;
+    else
+      *slash++ = 0;
 
-    directory(dir);
-    if (!shown()) fileList->load(dir);
-    if (*slash == '/') slash = dir;
+    directory(pathname, false);
+    if (!shown()) fileList->load(pathname);
+    if (slash > pathname) slash[-1] = '/';
   } else {
-    directory(".");
-    slash = dir;
+    directory(".", false);
+    slash = pathname;
   }
 
   // Set the input field to the absolute path...
-  if (slash > dir) slash[-1] = '/';
-
-  if (slash && *slash) fileName->value(pathname);
-  fileName->position(0, strlen(dir));
+  fileName->value(pathname);   // Why "if(*slash)..." ?
+  fileName->position(0, strlen(pathname));
   okButton->activate();
 
   // Then find the file in the file list and select it...
@@ -1168,6 +1174,17 @@
 }
 
 
+void
+FileChooser::activate_okButton_if_file()
+{
+    if (((type_ & CREATE) || !access(fileName->text(), 0)) &&
+        (!fltk::filename_isdir(fileName->text()) || (type_ & DIRECTORY)))
+      okButton->activate();
+    else
+      okButton->deactivate();
+}
+
+
 //
 // 'compare_dirnames()' - Compare two directory names.
 //
Index: src/filename_isdir.cxx
===================================================================
--- src/filename_isdir.cxx      (revision 8026)
+++ src/filename_isdir.cxx      (working copy)
@@ -71,6 +71,12 @@
   return (last_stat.st_mode&0170000)==0040000;
 }
 
+/** Returns true if the file exists and is a regular file. */
+bool fltk::filename_isfile(const char* name) {
+  if (!fill_stat(name)) return false;
+  return (last_stat.st_mode&0170000)==0100000;
+}
+
 /** Returns the size of the file in bytes. Returns zero if it does not exist.*/
 FL_FILESIZE_T fltk::filename_size(const char* name) {
   if (!fill_stat(name)) return 0;
Index: fltk/FileChooser.h
===================================================================
--- fltk/FileChooser.h  (revision 8026)
+++ fltk/FileChooser.h  (working copy)
@@ -43,6 +43,8 @@
   void update_favorites();
   void update_preview();
   int favorites_showing;
+  void activate_okButton_if_file();
+  void directory(const char *d, bool);
 public:
   FileChooser(const char *d, const char *p, int t, const char *title);
 private:
Index: fltk/FileInput.h
===================================================================
--- fltk/FileInput.h    (revision 8026)
+++ fltk/FileInput.h    (working copy)
@@ -55,7 +55,11 @@
   void                 errorcolor(Color c) { errorcolor_ = c; }
   int                  text(const char*);
   int                  text(const char*, int);
-  const char *         text() { return Input::text(); }
+  const char *         text() const { return Input::text(); }
+
+  int          value(const char* v) { return text(v); }
+  int          value(const char* v, int n) { return text(v,n); }
+  const char*  value() const { return text(); }
 };
 
 }
Index: fltk/filename.h
===================================================================
--- fltk/filename.h     (revision 8026)
+++ fltk/filename.h     (working copy)
@@ -111,6 +111,7 @@
 FL_API bool filename_match(const char *, const char *pattern); // glob match
 FL_API bool filename_exist(const char*);
 FL_API bool filename_isdir(const char*);
+FL_API bool filename_isfile(const char*);
 FL_API FL_FILESIZE_T filename_size(const char *); // return size of file
 FL_API long int filename_mtime(const char *); // return modification time
 
_______________________________________________
fltk-bugs mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-bugs

Reply via email to