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