|
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
Thanks for the patches.
Note: Looking at the patches I found some embedded comments and some code
formatting issues. I created a new patch for FLTK 1.4 (based on commit
357dad1e5, uploaded as 'FileChooser.1.4.0_357dad1e5.diff') w/o comments and
some (probably not all) formatting fixes.
I'll also upload 'comments.txt' with all comments I found for reference.
I did not test or review the patch as such, i.e. for functionality, leaving
this for others for now.
Link: https://www.fltk.org/str.php?L3520
Version: 1.4-feature From 18c592661fdfce7222dd9172874fc1efaaf47e7a Mon Sep 17 00:00:00 2001
From: Albrecht Schlosser <albrechts.fltk@online.de>
Date: Sun, 19 May 2019 14:01:32 +0200
Subject: [PATCH] Patch as given by OP in STR 3520
See: FileChooser.1.4.0.diff (inside .tar file)
Modified slightly to be closer to the FLTK coding standard:
- remove trailing spaces
- fix indenting
- other minor formatting issues
---
FL/Fl_File_Chooser.H | 3 +-
FL/filename.H | 1 +
src/Fl_File_Chooser.fl | 4 +-
src/Fl_File_Chooser2.cxx | 86 +++++++++++++++++++++++-----------------
src/Fl_File_Input.cxx | 28 ++++++++++---
src/filename_isdir.cxx | 6 +++
6 files changed, 84 insertions(+), 44 deletions(-)
diff --git a/FL/Fl_File_Chooser.H b/FL/Fl_File_Chooser.H
index 4ce459ebf..6f3beac1f 100644
--- a/FL/Fl_File_Chooser.H
+++ b/FL/Fl_File_Chooser.H
@@ -65,6 +65,7 @@ private:
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 @@ public:
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();
diff --git a/FL/filename.H b/FL/filename.H
index 9d41008a9..cfda5d1fa 100644
--- a/FL/filename.H
+++ b/FL/filename.H
@@ -54,6 +54,7 @@ FL_EXPORT int fl_filename_absolute(char *to, int tolen, const char *from);
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)
/*
diff --git a/src/Fl_File_Chooser.fl b/src/Fl_File_Chooser.fl
index fca0a32f3..dcb80dc6f 100644
--- a/src/Fl_File_Chooser.fl
+++ b/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 *}
} {
diff --git a/src/Fl_File_Chooser2.cxx b/src/Fl_File_Chooser2.cxx
index 80d842bcf..06b99e107 100644
--- a/src/Fl_File_Chooser2.cxx
+++ b/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)// I - Directory to change to
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_Chooser *fc) { // I - File chooser
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 *filename)
// 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 *filename)
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,15 @@ Fl_File_Chooser::value(const char *filename)
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()
{
diff --git a/src/Fl_File_Input.cxx b/src/Fl_File_Input.cxx
index 201101809..05e52aef0 100644
--- a/src/Fl_File_Input.cxx
+++ b/src/Fl_File_Input.cxx
@@ -266,12 +266,30 @@ Fl_File_Input::handle_button(int event) // I - 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;
+
+ 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();
+ // Then do the callbacks, if necessary...
+ set_changed();
+ if (when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE) ) do_callback();
+ }
}
return 1;
diff --git a/src/filename_isdir.cxx b/src/filename_isdir.cxx
index 5488f9131..e39ee11aa 100644
--- a/src/filename_isdir.cxx
+++ b/src/filename_isdir.cxx
@@ -81,6 +81,12 @@ int Fl_System_Driver::filename_isdir(const char* n) {
\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$".
//
--
2.20.1
[ Direct Link to Message ] | |