summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Fl_File_Browser.cxx79
-rw-r--r--src/Fl_File_Chooser.cxx23
-rw-r--r--src/Fl_File_Chooser.fl29
-rw-r--r--src/Fl_File_Chooser2.cxx31
-rw-r--r--src/Fl_System_Driver.H8
-rw-r--r--src/Fl_System_Driver.cxx6
-rw-r--r--src/drivers/Android/Fl_Android_System_Driver.H8
-rw-r--r--src/drivers/Android/Fl_Android_System_Driver.cxx12
-rw-r--r--src/drivers/Darwin/Fl_Darwin_System_Driver.H4
-rw-r--r--src/drivers/Darwin/Fl_Darwin_System_Driver.cxx9
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_System_Driver.H8
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx15
-rw-r--r--src/drivers/X11/Fl_X11_System_Driver.H4
-rw-r--r--src/drivers/X11/Fl_X11_System_Driver.cxx22
-rw-r--r--src/filename_isdir.cxx1
-rw-r--r--src/filename_list.cxx3
-rw-r--r--src/scandir_posix.c103
-rw-r--r--src/scandir_win32.c101
18 files changed, 326 insertions, 140 deletions
diff --git a/src/Fl_File_Browser.cxx b/src/Fl_File_Browser.cxx
index e7a7ea8d4..cb92428dd 100644
--- a/src/Fl_File_Browser.cxx
+++ b/src/Fl_File_Browser.cxx
@@ -354,10 +354,10 @@ Fl_File_Browser::item_draw(void *p, // I - List item data
}
-//
-// 'Fl_File_Browser::Fl_File_Browser()' - Create a Fl_File_Browser widget.
-//
-
+/**
+ The constructor creates the Fl_File_Browser widget at the specified position and size.
+ The destructor destroys the widget and frees all memory that has been allocated.
+*/
Fl_File_Browser::Fl_File_Browser(int X, // I - Upper-lefthand X coordinate
int Y, // I - Upper-lefthand Y coordinate
int W, // I - Width in pixels
@@ -370,13 +370,40 @@ Fl_File_Browser::Fl_File_Browser(int X, // I - Upper-lefthand X coordina
directory_ = "";
iconsize_ = (uchar)(3 * textsize() / 2);
filetype_ = FILES;
+ errmsg_ = NULL;
}
-//
-// 'Fl_File_Browser::load()' - Load a directory into the browser.
-//
+// DTOR
+Fl_File_Browser::~Fl_File_Browser() {
+ errmsg(NULL); // free()s prev errmsg, if any
+}
+
+
+/**
+ Sets OS error message to a string, which can be NULL.
+ Frees previous if any.
+ void errmsg(const char *emsg);
+ */
+void Fl_File_Browser::errmsg(const char* emsg) {
+ if ( errmsg_ ) { free((void*)errmsg_); errmsg_ = NULL; }
+ errmsg_ = emsg ? strdup(emsg) : NULL;
+}
+
+
+/**
+ Loads the specified directory into the browser. If icons have been
+ loaded then the correct icon is associated with each file in the list.
+ If directory is "", all mount points (unix) or drive letters (Windows)
+ are listed.
+
+ The sort argument specifies a sort function to be used with
+ fl_filename_list().
+
+ Return value is the number of filename entries, or 0 if none.
+ On error, 0 is returned, and errmsg() has OS error string if non-NULL.
+*/
int // O - Number of files loaded
Fl_File_Browser::load(const char *directory,// I - Directory to load
Fl_File_Sort_F *sort) // I - Sort function to use
@@ -387,6 +414,7 @@ Fl_File_Browser::load(const char *directory,// I - Directory to load
char filename[4096]; // Current file
Fl_File_Icon *icon; // Icon to use
+ errmsg(NULL); // clear errors first
// printf("Fl_File_Browser::load(\"%s\")\n", directory);
@@ -394,11 +422,12 @@ Fl_File_Browser::load(const char *directory,// I - Directory to load
directory_ = directory;
- if (!directory)
- return (0);
+ if (!directory) {
+ errmsg("NULL directory specified");
+ return 0;
+ }
- if (directory_[0] == '\0')
- {
+ if (directory_[0] == '\0') {
//
// No directory specified; for UNIX list all mount points. For DOS
// list all valid drive letters...
@@ -406,21 +435,25 @@ Fl_File_Browser::load(const char *directory,// I - Directory to load
if ((icon = Fl_File_Icon::find("any", Fl_File_Icon::DEVICE)) == NULL)
icon = Fl_File_Icon::find("any", Fl_File_Icon::DIRECTORY);
num_files = Fl::system_driver()->file_browser_load_filesystem(this, filename, (int)sizeof(filename), icon);
- }
- else
- {
- dirent **files; // Files in in directory
- //
- // Build the file list...
- //
- num_files = Fl::system_driver()->file_browser_load_directory(directory_, filename, sizeof(filename), &files, sort);
- if (num_files <= 0)
- return (0);
+ } else {
+ dirent **files; // Files in in directory
+ char emsg[1024] = "";
+
+ // Build the file list, check for errors
+ num_files = Fl::system_driver()->file_browser_load_directory(directory_,
+ filename, sizeof(filename),
+ &files, sort,
+ emsg, sizeof(emsg));
+ // printf("Fl_File_Browser::load(dir='%s',filename='%s'): failed, emsg='%s'\n", directory_, filename, emsg);
+
+ if (num_files <= 0) {
+ errmsg(emsg);
+ return 0;
+ }
for (i = 0, num_dirs = 0; i < num_files; i ++) {
if (strcmp(files[i]->d_name, "./")) {
- snprintf(filename, sizeof(filename), "%s/%s", directory_,
- files[i]->d_name);
+ fl_snprintf(filename, sizeof(filename), "%s/%s", directory_, files[i]->d_name);
icon = Fl_File_Icon::find(filename);
if ((icon && icon->type() == Fl_File_Icon::DIRECTORY) ||
diff --git a/src/Fl_File_Chooser.cxx b/src/Fl_File_Chooser.cxx
index 8036ffaed..22fadf57f 100644
--- a/src/Fl_File_Chooser.cxx
+++ b/src/Fl_File_Chooser.cxx
@@ -197,9 +197,18 @@ Fl_File_Chooser::Fl_File_Chooser(const char *d, const char *p, int t, const char
o->callback((Fl_Callback*)cb_);
{ fileList = new Fl_File_Browser(10, 45, 295, 225);
fileList->type(2);
+ fileList->box(FL_DOWN_BOX);
fileList->callback((Fl_Callback*)cb_fileList);
fileList->window()->hotspot(fileList);
} // Fl_File_Browser* fileList
+ { errorBox = new Fl_Box(10, 45, 295, 225, "dynamic error display");
+ errorBox->box(FL_DOWN_BOX);
+ errorBox->color(FL_BACKGROUND2_COLOR);
+ errorBox->labelsize(18);
+ errorBox->labelcolor((Fl_Color)1);
+ errorBox->align(Fl_Align(133|FL_ALIGN_INSIDE));
+ errorBox->hide();
+ } // Fl_Box* errorBox
{ previewBox = new Fl_Box(305, 45, 175, 225, "?");
previewBox->box(FL_DOWN_BOX);
previewBox->labelsize(100);
@@ -471,3 +480,17 @@ Fl_Widget* Fl_File_Chooser::add_extra(Fl_Widget* gr) {
}
return ret;
}
+
+/**
+ Show error box if val=1, hide if val=0
+*/
+void Fl_File_Chooser::show_error_box(int val) {
+ if ( val ) {
+ errorBox->color(fileList->color()); // inherit fileList's bg color
+ errorBox->show();
+ fileList->hide();
+ } else {
+ errorBox->hide();
+ fileList->show();
+ }
+}
diff --git a/src/Fl_File_Chooser.fl b/src/Fl_File_Chooser.fl
index d222bd1c8..7cf01e1c7 100644
--- a/src/Fl_File_Chooser.fl
+++ b/src/Fl_File_Chooser.fl
@@ -66,7 +66,8 @@ class FL_EXPORT Fl_File_Chooser {open
}
decl {void update_preview();} {private local
}
- Function {Fl_File_Chooser(const char *d, const char *p, int t, const char *title)} {} {
+ Function {Fl_File_Chooser(const char *d, const char *p, int t, const char *title)} {open
+ } {
code {if (!prefs_) {
prefs_ = new Fl_Preferences(Fl_Preferences::CORE_USER, "fltk.org", "filechooser");
}} {}
@@ -77,11 +78,11 @@ class FL_EXPORT Fl_File_Chooser {open
fileList->deselect();
Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this);
window->hide();} open
- private xywh {507 327 490 380} type Double hide resizable
+ private xywh {1171 438 490 380} type Double resizable
code0 {if (title) window->label(title);}
code1 {\#include <stdio.h>}
code2 {\#include <stdlib.h>}
- code3 {\#include <string.h>} modal
+ code3 {\#include <string.h>} modal visible
} {
Fl_Group {} {open
private xywh {10 10 470 25}
@@ -106,14 +107,18 @@ window->hide();} open
}
}
Fl_Tile {} {
- callback {update_preview();}
+ callback {update_preview();} open
private xywh {10 45 470 225} resizable
} {
Fl_File_Browser fileList {
callback {fileListCB();}
- private xywh {10 45 295 225} type Hold hotspot
+ private xywh {10 45 295 225} type Hold box DOWN_BOX hotspot
code0 {\#include <FL/Fl_File_Browser.H>}
}
+ Fl_Box errorBox {
+ label {dynamic error display} selected
+ private xywh {10 45 295 225} box DOWN_BOX color 7 labelsize 18 labelcolor 1 align 149 hide
+ }
Fl_Box previewBox {
label {?}
private xywh {305 45 175 225} box DOWN_BOX labelsize 100 align 80
@@ -349,7 +354,7 @@ okButton->parent()->init_sizes();} {}
} {
code {fileList->textfont(f);} {}
}
- Function {textfont()} {selected return_type Fl_Font
+ Function {textfont()} {return_type Fl_Font
} {
code {return (fileList->textfont());} {}
}
@@ -475,6 +480,18 @@ window->resizable(svres);} {}
}
code {return ret;} {}
}
+ Function {show_error_box(int val)} {
+ comment {Show error box if val=1, hide if val=0} open protected return_type void
+ } {
+ code {if ( val ) {
+ errorBox->color(fileList->color()); // inherit fileList's bg color
+ errorBox->show();
+ fileList->hide();
+} else {
+ errorBox->hide();
+ fileList->show();
+}} {}
+ }
}
decl {FL_EXPORT char *fl_dir_chooser(const char *message,const char *fname,int relative=0);} {public local
diff --git a/src/Fl_File_Chooser2.cxx b/src/Fl_File_Chooser2.cxx
index de2b7c160..ec04bd77c 100644
--- a/src/Fl_File_Chooser2.cxx
+++ b/src/Fl_File_Chooser2.cxx
@@ -1020,17 +1020,15 @@ void Fl_File_Chooser::preview(int e)
Fl_Group *p = previewBox->parent();
if (e) {
int w = p->w() * 2 / 3;
- fileList->resize(fileList->x(), fileList->y(),
- w, fileList->h());
- previewBox->resize(fileList->x()+w, previewBox->y(),
- p->w()-w, previewBox->h());
+ fileList->resize(fileList->x(), fileList->y(), w, fileList->h());
+ errorBox->resize(errorBox->x(), errorBox->y(), w, errorBox->h());
+ previewBox->resize(fileList->x()+w, previewBox->y(), p->w()-w, previewBox->h());
previewBox->show();
update_preview();
} else {
- fileList->resize(fileList->x(), fileList->y(),
- p->w(), fileList->h());
- previewBox->resize(p->x()+p->w(), previewBox->y(),
- 0, previewBox->h());
+ fileList->resize(fileList->x(), fileList->y(), p->w(), fileList->h());
+ errorBox->resize(errorBox->x(), errorBox->y(), p->w(), errorBox->h());
+ previewBox->resize(p->x()+p->w(), previewBox->y(), 0, previewBox->h());
previewBox->hide();
}
p->init_sizes();
@@ -1070,7 +1068,14 @@ Fl_File_Chooser::rescan()
okButton->deactivate();
// Build the file list...
- fileList->load(directory_, sort);
+ if ( fileList->load(directory_, sort) <= 0 ) {
+ if ( fileList->errmsg() ) errorBox->label(fileList->errmsg()); // show OS errormsg when possible
+ else errorBox->label("No files found...");
+ show_error_box(1);
+ } else {
+ show_error_box(0);
+ }
+
if (Fl::system_driver()->dot_file_hidden() && !showHiddenButton->value()) remove_hidden_files();
// Update the preview box...
update_preview();
@@ -1094,7 +1099,13 @@ void Fl_File_Chooser::rescan_keep_filename()
strlcpy(pathname, fn, sizeof(pathname));
// Build the file list...
- fileList->load(directory_, sort);
+ if (fileList->load(directory_, sort) <= 0) {
+ if ( fileList->errmsg() ) errorBox->label(fileList->errmsg()); // show OS errormsg when possible
+ else errorBox->label("No files found...");
+ show_error_box(1);
+ } else {
+ show_error_box(0);
+ }
if (Fl::system_driver()->dot_file_hidden() && !showHiddenButton->value()) remove_hidden_files();
// Update the preview box...
update_preview();
diff --git a/src/Fl_System_Driver.H b/src/Fl_System_Driver.H
index 0474154d4..77a58971f 100644
--- a/src/Fl_System_Driver.H
+++ b/src/Fl_System_Driver.H
@@ -128,7 +128,9 @@ public:
virtual int event_key(int k) {return 0;}
virtual int get_key(int k) {return 0;}
// implement scandir-like function
- virtual int filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **) ) {return -1;}
+ virtual int filename_list(const char *d, dirent ***list,
+ int (*sort)(struct dirent **, struct dirent **),
+ char *errmsg=NULL, int errmsg_sz=0) {return -1;}
// the default implementation of filename_expand() may be enough
virtual int filename_expand(char *to, int tolen, const char *from);
// to implement
@@ -162,7 +164,9 @@ public:
// implement to support Fl_File_Browser::load()
virtual int file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon) {return 0;}
// the default implementation of file_browser_load_directory() should be enough
- virtual int file_browser_load_directory(const char *directory, char *filename, size_t name_size, dirent ***pfiles, Fl_File_Sort_F *sort);
+ virtual int file_browser_load_directory(const char *directory, char *filename, size_t name_size,
+ dirent ***pfiles, Fl_File_Sort_F *sort,
+ char *errmsg=NULL, int errmsg_sz=0);
// implement to support Fl_Preferences
virtual void newUUID(char *uuidBuffer) { uuidBuffer[0] = 0; }
// implement to support Fl_Preferences
diff --git a/src/Fl_System_Driver.cxx b/src/Fl_System_Driver.cxx
index f2b3c9584..a68d3b381 100644
--- a/src/Fl_System_Driver.cxx
+++ b/src/Fl_System_Driver.cxx
@@ -449,9 +449,11 @@ int Fl_System_Driver::filename_expand(char *to,int tolen, const char *from) {
}
int Fl_System_Driver::file_browser_load_directory(const char *directory, char *filename,
- size_t name_size, dirent ***pfiles, Fl_File_Sort_F *sort)
+ size_t name_size, dirent ***pfiles,
+ Fl_File_Sort_F *sort,
+ char *errmsg, int errmsg_sz)
{
- return filename_list(directory, pfiles, sort);
+ return filename_list(directory, pfiles, sort, errmsg, errmsg_sz);
}
int Fl_System_Driver::file_type(const char *filename)
diff --git a/src/drivers/Android/Fl_Android_System_Driver.H b/src/drivers/Android/Fl_Android_System_Driver.H
index 2a8682ddb..198d7a2b3 100644
--- a/src/drivers/Android/Fl_Android_System_Driver.H
+++ b/src/drivers/Android/Fl_Android_System_Driver.H
@@ -70,7 +70,9 @@ public:
// these 2 are in Fl_get_key_win32.cxx
virtual int event_key(int k);
virtual int get_key(int k);
- virtual int filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **) );
+ virtual int filename_list(const char *d, dirent ***list,
+ int (*sort)(struct dirent **, struct dirent **),
+ char *errmsg, int errmsg_sz);
virtual int filename_expand(char *to,int tolen, const char *from);
virtual int filename_relative(char *to, int tolen, const char *from, const char *base);
virtual int filename_absolute(char *to, int tolen, const char *from);
@@ -80,7 +82,9 @@ public:
virtual int open_uri(const char *uri, char *msg, int msglen);
virtual int use_recent_tooltip_fix() {return 1;}
virtual int file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon);
- virtual int file_browser_load_directory(const char *directory, char *filename, size_t name_size, dirent ***pfiles, Fl_File_Sort_F *sort);
+ virtual int file_browser_load_directory(const char *directory, char *filename, size_t name_size,
+ dirent ***pfiles, Fl_File_Sort_F *sort,
+ char *errmsg=NULL, int errmsg_sz=0);
virtual void newUUID(char *uuidBuffer);
virtual char *preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor,
const char *application);
diff --git a/src/drivers/Android/Fl_Android_System_Driver.cxx b/src/drivers/Android/Fl_Android_System_Driver.cxx
index e6aa970e4..0fa9671c5 100644
--- a/src/drivers/Android/Fl_Android_System_Driver.cxx
+++ b/src/drivers/Android/Fl_Android_System_Driver.cxx
@@ -486,11 +486,13 @@ int Fl_WinAPI_System_Driver::clocale_printf(FILE *output, const char *format, va
return retval;
}
-int Fl_WinAPI_System_Driver::filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **) ) {
+int Fl_WinAPI_System_Driver::filename_list(const char *d, dirent ***list,
+ int (*sort)(struct dirent **, struct dirent **),
+ char *errmsg, int errmsg_sz ) {
// For Windows we have a special scandir implementation that uses
// the Win32 "wide" functions for lookup, avoiding the code page mess
// entirely. It also fixes up the trailing '/'.
- return fl_scandir(d, list, 0, sort);
+ return fl_scandir(d, list, 0, sort, errmsg, errmsg_sz);
}
int Fl_WinAPI_System_Driver::filename_expand(char *to, int tolen, const char *from) {
@@ -747,7 +749,9 @@ int Fl_WinAPI_System_Driver::file_browser_load_filesystem(Fl_File_Browser *brows
}
int Fl_WinAPI_System_Driver::file_browser_load_directory(const char *directory, char *filename,
- size_t name_size, dirent ***pfiles, Fl_File_Sort_F *sort)
+ size_t name_size, dirent ***pfiles,
+ Fl_File_Sort_F *sort,
+ char *errmsg, int errmsg_sz)
{
strlcpy(filename, directory, name_size);
int i = (int) (strlen(filename) - 1);
@@ -756,7 +760,7 @@ int Fl_WinAPI_System_Driver::file_browser_load_directory(const char *directory,
filename[2] = '/';
else if (filename[i] != '/' && filename[i] != '\\')
strlcat(filename, "/", name_size);
- return filename_list(filename, pfiles, sort);
+ return filename_list(filename, pfiles, sort, errmsg, errmsg_sz);
}
void Fl_WinAPI_System_Driver::newUUID(char *uuidBuffer)
diff --git a/src/drivers/Darwin/Fl_Darwin_System_Driver.H b/src/drivers/Darwin/Fl_Darwin_System_Driver.H
index ee7ab30ea..548277901 100644
--- a/src/drivers/Darwin/Fl_Darwin_System_Driver.H
+++ b/src/drivers/Darwin/Fl_Darwin_System_Driver.H
@@ -52,7 +52,9 @@ public:
// these 2 are in Fl_get_key_mac.cxx
virtual int event_key(int k);
virtual int get_key(int k);
- virtual int filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **) );
+ virtual int filename_list(const char *d, dirent ***list,
+ int (*sort)(struct dirent **, struct dirent **),
+ char *errmsg=NULL, int errmsg_sz=0);
virtual int open_uri(const char *uri, char *msg, int msglen);
virtual int need_test_shortcut_extra() {return 1;}
virtual int file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon);
diff --git a/src/drivers/Darwin/Fl_Darwin_System_Driver.cxx b/src/drivers/Darwin/Fl_Darwin_System_Driver.cxx
index 51a416b87..0c1a9de9e 100644
--- a/src/drivers/Darwin/Fl_Darwin_System_Driver.cxx
+++ b/src/drivers/Darwin/Fl_Darwin_System_Driver.cxx
@@ -15,6 +15,7 @@
//
#include "Fl_Darwin_System_Driver.H"
+#include <src/flstring.h>
#include <FL/platform.H>
#include <FL/Fl.H>
#include <FL/Fl_File_Browser.H>
@@ -139,7 +140,9 @@ void *Fl_Darwin_System_Driver::get_carbon_function(const char *function_name) {
return (carbon ? dlsym(carbon, function_name) : NULL);
}
-int Fl_Darwin_System_Driver::filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **) ) {
+int Fl_Darwin_System_Driver::filename_list(const char *d, dirent ***list,
+ int (*sort)(struct dirent **, struct dirent **),
+ char *errmsg, int errmsg_sz) {
int dirlen;
char *dirloc;
// Assume that locale encoding is no less dense than UTF-8
@@ -150,6 +153,10 @@ int Fl_Darwin_System_Driver::filename_list(const char *d, dirent ***list, int (*
# else
int n = scandir(dirloc, list, 0, (int(*)(const void*,const void*))sort);
# endif
+ if (n==-1) {
+ if (errmsg) fl_snprintf(errmsg, errmsg_sz, "%s", strerror(errno));
+ return -1;
+ }
// convert every filename to UTF-8, and append a '/' to all
// filenames that are directories
int i;
diff --git a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H
index e6446923d..91b230d5f 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H
+++ b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H
@@ -68,7 +68,9 @@ public:
// these 2 are in Fl_get_key_win32.cxx
virtual int event_key(int k);
virtual int get_key(int k);
- virtual int filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **) );
+ virtual int filename_list(const char *d, dirent ***list,
+ int (*sort)(struct dirent **, struct dirent **),
+ char *errmsg=NULL, int errmsg_sz=0);
virtual int filename_expand(char *to,int tolen, const char *from);
virtual int filename_relative(char *to, int tolen, const char *from, const char *base);
virtual int filename_absolute(char *to, int tolen, const char *from);
@@ -78,7 +80,9 @@ public:
virtual int open_uri(const char *uri, char *msg, int msglen);
virtual int use_recent_tooltip_fix() {return 1;}
virtual int file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon);
- virtual int file_browser_load_directory(const char *directory, char *filename, size_t name_size, dirent ***pfiles, Fl_File_Sort_F *sort);
+ virtual int file_browser_load_directory(const char *directory, char *filename, size_t name_size,
+ dirent ***pfiles, Fl_File_Sort_F *sort,
+ char *errmsg=NULL, int errmsg_sz=0);
virtual void newUUID(char *uuidBuffer);
virtual char *preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor,
const char *application);
diff --git a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx
index ab20cfe32..592e192e3 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx
+++ b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx
@@ -61,7 +61,8 @@ static wchar_t *wbuf1 = NULL;
extern "C" {
int fl_scandir(const char *dirname, struct dirent ***namelist,
int (*select)(struct dirent *),
- int (*compar)(struct dirent **, struct dirent **));
+ int (*compar)(struct dirent **, struct dirent **),
+ char *errmsg, int errmsg_len);
}
/*
@@ -488,11 +489,13 @@ int Fl_WinAPI_System_Driver::clocale_printf(FILE *output, const char *format, va
return retval;
}
-int Fl_WinAPI_System_Driver::filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **) ) {
+int Fl_WinAPI_System_Driver::filename_list(const char *d, dirent ***list,
+ int (*sort)(struct dirent **, struct dirent **),
+ char *errmsg, int errmsg_sz) {
// For Windows we have a special scandir implementation that uses
// the Win32 "wide" functions for lookup, avoiding the code page mess
// entirely. It also fixes up the trailing '/'.
- return fl_scandir(d, list, 0, sort);
+ return fl_scandir(d, list, 0, sort, errmsg, errmsg_sz);
}
int Fl_WinAPI_System_Driver::filename_expand(char *to, int tolen, const char *from) {
@@ -749,7 +752,9 @@ int Fl_WinAPI_System_Driver::file_browser_load_filesystem(Fl_File_Browser *brows
}
int Fl_WinAPI_System_Driver::file_browser_load_directory(const char *directory, char *filename,
- size_t name_size, dirent ***pfiles, Fl_File_Sort_F *sort)
+ size_t name_size, dirent ***pfiles,
+ Fl_File_Sort_F *sort,
+ char *errmsg, int errmsg_sz)
{
strlcpy(filename, directory, name_size);
int i = (int) (strlen(filename) - 1);
@@ -758,7 +763,7 @@ int Fl_WinAPI_System_Driver::file_browser_load_directory(const char *directory,
filename[2] = '/';
else if (filename[i] != '/' && filename[i] != '\\')
strlcat(filename, "/", name_size);
- return filename_list(filename, pfiles, sort);
+ return filename_list(filename, pfiles, sort, errmsg, errmsg_sz);
}
void Fl_WinAPI_System_Driver::newUUID(char *uuidBuffer)
diff --git a/src/drivers/X11/Fl_X11_System_Driver.H b/src/drivers/X11/Fl_X11_System_Driver.H
index 7c2306a28..f8fddc741 100644
--- a/src/drivers/X11/Fl_X11_System_Driver.H
+++ b/src/drivers/X11/Fl_X11_System_Driver.H
@@ -34,7 +34,9 @@ public:
// these 2 are in Fl_get_key.cxx
virtual int event_key(int k);
virtual int get_key(int k);
- virtual int filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **) );
+ virtual int filename_list(const char *d, dirent ***list,
+ int (*sort)(struct dirent **, struct dirent **),
+ char *errmsg=NULL, int errmsg_sz=0);
virtual int need_menu_handle_part1_extra() {return 1;}
virtual int open_uri(const char *uri, char *msg, int msglen);
virtual int use_tooltip_timeout_condition() {return 1;}
diff --git a/src/drivers/X11/Fl_X11_System_Driver.cxx b/src/drivers/X11/Fl_X11_System_Driver.cxx
index 0714ff753..28827bcfc 100644
--- a/src/drivers/X11/Fl_X11_System_Driver.cxx
+++ b/src/drivers/X11/Fl_X11_System_Driver.cxx
@@ -25,7 +25,8 @@
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
-
+#include <string.h> // strerror(errno)
+#include <errno.h> // errno
#if defined(_AIX)
extern "C" {
@@ -56,7 +57,8 @@ extern "C" {
extern "C" {
int fl_scandir(const char *dirname, struct dirent ***namelist,
int (*select)(struct dirent *),
- int (*compar)(struct dirent **, struct dirent **));
+ int (*compar)(struct dirent **, struct dirent **),
+ char *errmsg, int errmsg_sz);
}
#endif
@@ -444,10 +446,19 @@ int Fl_X11_System_Driver::XParseGeometry(const char* string, int* x, int* y,
return ::XParseGeometry(string, x, y, width, height);
}
-int Fl_X11_System_Driver::filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **) ) {
+//
+// Needs some docs
+// Returns -1 on error, errmsg will contain OS error if non-NULL.
+//
+int Fl_X11_System_Driver::filename_list(const char *d,
+ dirent ***list,
+ int (*sort)(struct dirent **, struct dirent **),
+ char *errmsg, int errmsg_sz) {
int dirlen;
char *dirloc;
+ if (errmsg && errmsg_sz>0) errmsg[0] = '\0';
+
// Assume that locale encoding is no less dense than UTF-8
dirlen = strlen(d);
dirloc = (char *)malloc(dirlen + 1);
@@ -476,6 +487,11 @@ int Fl_X11_System_Driver::filename_list(const char *d, dirent ***list, int (*sor
free(dirloc);
+ if (n==-1) {
+ if (errmsg) fl_snprintf(errmsg, errmsg_sz, "%s", strerror(errno));
+ return -1;
+ }
+
// convert every filename to UTF-8, and append a '/' to all
// filenames that are directories
int i;
diff --git a/src/filename_isdir.cxx b/src/filename_isdir.cxx
index fad66b3c7..47e1de58f 100644
--- a/src/filename_isdir.cxx
+++ b/src/filename_isdir.cxx
@@ -57,6 +57,7 @@ int Fl_System_Driver::filename_isdir_quick(const char* n) {
}
+// TODO: This should probably handle errors better (like permission denied) -erco
int Fl_System_Driver::filename_isdir(const char* n) {
struct stat s;
char fn[FL_PATH_MAX];
diff --git a/src/filename_list.cxx b/src/filename_list.cxx
index 2ad240996..4c8204fe7 100644
--- a/src/filename_list.cxx
+++ b/src/filename_list.cxx
@@ -63,9 +63,10 @@ int fl_casealphasort(struct dirent **a, struct dirent **b) {
to put unpadded numbers in consecutive order; upper and lowercase letters are compared
according to their ASCII ordering - uppercase before lowercase.
\return the number of entries if no error, a negative value otherwise.
+ \todo should support returning OS error messages
*/
int fl_filename_list(const char *d, dirent ***list, Fl_File_Sort_F *sort) {
- return Fl::system_driver()->filename_list(d, list, sort);
+ return Fl::system_driver()->filename_list(d, list, sort, NULL, 0);
}
/**
diff --git a/src/scandir_posix.c b/src/scandir_posix.c
index cf58c4195..b311c72e1 100644
--- a/src/scandir_posix.c
+++ b/src/scandir_posix.c
@@ -128,11 +128,16 @@ readentry(DIR *dirp, struct dirent **entryp, size_t *len)
}
-/* ========================================================================== */
+/*
+ * This could use some docs.
+ *
+ * Returns -1 on error, errmsg returns error string (if non-NULL)
+ */
int
fl_scandir(const char *dir, struct dirent ***namelist,
int (*sel)(struct dirent *),
- int (*compar)(struct dirent **, struct dirent **))
+ int (*compar)(struct dirent **, struct dirent **),
+ char *errmsg, int errmsg_sz) {
{
int result = -1;
DIR *dirp;
@@ -140,64 +145,62 @@ fl_scandir(const char *dir, struct dirent ***namelist,
struct dirent *entryp, **entries, **p;
entries = (struct dirent **) malloc(sizeof(*entries) * max);
- if (NULL != entries)
+ if (NULL == entries) {
+ if (errmsg) fl_snprintf(errmsg, errmsg_sz, "out of memory");
+ return -1;
+ }
+
+ /* Open directory 'dir' (and verify that it really is a directory) */
+ dirp = opendir(dir);
+ if (NULL == dirp) {
+ if (errmsg) fl_snprintf(errmsg, errmsg_sz, "%s", strerror(errno));
+ return -1;
+ }
+
+ /* Read next directory entry */
+ while (!readentry(dirp, &entryp, &len))
{
- /* Open directory 'dir' (and verify that it really is a directory) */
- dirp = opendir(dir);
- if (NULL != dirp)
+ if (NULL == entryp)
{
- /* Read next directory entry */
- while (!readentry(dirp, &entryp, &len))
- {
- if (NULL == entryp)
- {
- /* EOD => Return number of directory entries */
- result = (int) num;
- break;
- }
- /* Apply select function if there is one provided */
- if (NULL != sel) { if (!sel(entryp)) continue; }
- entries[num++] = entryp;
- if (num >= max)
- {
- /* Allocate exponentially increasing sized memory chunks */
- if (INT_MAX / 2 >= (int) max) { max *= (size_t) 2; }
- else
- {
- errno = ENOMEM;
- break;
- }
- p = (struct dirent **) realloc((void *) entries,
- sizeof(*entries) * max);
- if (NULL != p) { entries = p; }
- else break;
- }
- }
- closedir(dirp);
- /*
- * A standard compliant 'closedir()' is allowed to fail with 'EINTR',
- * but the state of the directory structure is undefined in this case.
- * Therefore we ignore the return value because we can't call 'closedir()'
- * again and must hope that the system has released all resources.
- */
+ /* EOD => Return number of directory entries */
+ result = (int) num;
+ break;
}
- /* Sort entries in array if there is a compare function provided */
- if (NULL != compar)
- {
- qsort((void *) entries, num, sizeof(*entries),
- (int (*)(const void *, const void *)) compar);
+ /* Apply select function if there is one provided */
+ if (NULL != sel) { if (!sel(entryp)) continue; }
+ entries[num++] = entryp;
+ if (num >= max) {
+ /* Allocate exponentially increasing sized memory chunks */
+ if (INT_MAX / 2 >= (int) max) { max *= (size_t) 2; }
+ else {
+ errno = ENOMEM;
+ break;
+ }
+ p = (struct dirent **) realloc((void *)entries, sizeof(*entries)*max);
+ if (NULL != p) { entries = p; }
+ else break;
}
- *namelist = entries;
}
-
+ closedir(dirp);
+ /*
+ * A standard compliant 'closedir()' is allowed to fail with 'EINTR',
+ * but the state of the directory structure is undefined in this case.
+ * Therefore we ignore the return value because we can't call 'closedir()'
+ * again and must hope that the system has released all resources.
+ */
+
+ /* Sort entries in array if there is a compare function provided */
+ if (NULL != compar) {
+ qsort((void *) entries, num, sizeof(*entries),
+ (int (*)(const void *, const void *)) compar);
+ }
+ *namelist = entries;
/* Check for error */
- if (-1 == result)
- {
+ if (-1 == result) {
/* Free all memory we have allocated */
while (num--) { free(entries[num]); }
free(entries);
}
-
return result;
}
diff --git a/src/scandir_win32.c b/src/scandir_win32.c
index 2663e30dc..822770234 100644
--- a/src/scandir_win32.c
+++ b/src/scandir_win32.c
@@ -15,16 +15,59 @@
*/
#ifndef __CYGWIN__
-/* Emulation of POSIX scandir() call */
+/* Emulation of POSIX scandir() call with error messages */
#include <FL/platform_types.h>
#include <FL/fl_utf8.h>
#include "flstring.h"
#include <windows.h>
#include <stdlib.h>
+/* Get error message string for last failed WIN32 operation
+ * in 'errmsg' (if non-NULL), string size limited to errmsg_sz.
+ *
+ * NOTE: Copied from: fluid/ExternalCodeEditor_WIN32.cxx
+ *
+ * TODO: Verify works in different languages, with utf8 strings.
+ * TODO: This should be made available globally to the FLTK internals, in case
+ * other parts of FLTK need OS error messages..
+ */
+static void get_ms_errmsg(char *errmsg, int errmsg_sz) {
+ DWORD lastErr = GetLastError();
+ DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM;
+ DWORD langid = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
+ LPSTR mbuf = 0;
+
+ // Early exit if parent doesn't want an errmsg
+ if (!errmsg || errmsg_sz<=0 ) return;
+ // Get error message from Windows
+ DWORD size = FormatMessageA(flags, 0, lastErr, langid, (LPSTR)&mbuf, 0, NULL);
+ if ( size == 0 ) {
+ fl_snprintf(errmsg, errmsg_sz, "Error #%lu", (unsigned long)lastErr);
+ } else {
+ int cnt = 0;
+ /* Copy mbuf -> errmsg, remove '\r's -- they screw up fl_alert()) */
+ for ( char *src=mbuf, *dst=errmsg; 1; src++ ) {
+ if ( *src == '\0' ) { *dst = '\0'; break; }
+ if ( *src != '\r' ) {
+ if ( ++cnt >= errmsg_sz ) { *dst = '\0'; break; } // trunc on overflow
+ *dst++ = *src;
+ }
+ }
+ LocalFree(mbuf); /* Free the buffer allocated by the system */
+ }
+}
+
+/*
+ * This could use some docs.
+ *
+ * Returns -1 on error, errmsg returns error string (if non-NULL)
+ */
int fl_scandir(const char *dirname, struct dirent ***namelist,
int (*select)(struct dirent *),
- int (*compar)(struct dirent **, struct dirent **)) {
+ int (*compar)(struct dirent **, struct dirent **),
+ char *errmsg, int errmsg_sz) {
int len;
char *findIn, *d, is_dir = 0;
WIN32_FIND_DATAW findw;
@@ -33,9 +76,14 @@ int fl_scandir(const char *dirname, struct dirent ***namelist,
struct dirent **dir = 0, *selectDir;
unsigned long ret;
+ if (errmsg && errmsg_sz>0) errmsg[0] = '\0';
len = (int) strlen(dirname);
findIn = (char *)malloc((size_t)(len+10));
- if (!findIn) return -1;
+ if (!findIn) {
+ /* win32 malloc() docs: "malloc sets errno to ENOMEM if allocation fails" */
+ if (errmsg) fl_snprintf(errmsg, errmsg_sz, "%s", strerror(errno));
+ return -1;
+ }
strcpy(findIn, dirname);
/* #if defined(__GNUC__) */
@@ -49,7 +97,7 @@ int fl_scandir(const char *dirname, struct dirent ***namelist,
if ((len>1) && (d[-1]=='.') && (d[-2]=='\\')) { d[-1] = '*'; is_dir = 1; }
if (!is_dir) { /* this file may still be a directory that we need to list */
DWORD attr = GetFileAttributes(findIn);
- if (attr&FILE_ATTRIBUTE_DIRECTORY)
+ if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY) )
strcpy(d, "\\*");
}
{ /* Create a block to limit the scope while we find the initial "wide" filename */
@@ -64,55 +112,54 @@ int fl_scandir(const char *dirname, struct dirent ***namelist,
h = FindFirstFileW(wbuf, &findw); /* get a handle to the first filename in the search */
free(wbuf); /* release the "wide" buffer before the pointer goes out of scope */
}
+
if (h==INVALID_HANDLE_VALUE) {
free(findIn);
ret = GetLastError();
if (ret != ERROR_NO_MORE_FILES) {
nDir = -1;
+ get_ms_errmsg(errmsg, errmsg_sz); /* return OS error msg */
}
*namelist = dir;
return nDir;
}
do {
- int l = (int) wcslen(findw.cFileName);
- int dstlen = l * 5 + 1;
- selectDir=(struct dirent*)malloc(sizeof(struct dirent)+dstlen);
+ int l = (int) wcslen(findw.cFileName);
+ int dstlen = l * 5 + 1;
+ selectDir=(struct dirent*)malloc(sizeof(struct dirent)+dstlen);
- /* l = fl_unicode2utf(findw.cFileName, l, selectDir->d_name); */
- l = fl_utf8fromwc(selectDir->d_name, dstlen, findw.cFileName, l);
+ /* l = fl_unicode2utf(findw.cFileName, l, selectDir->d_name); */
+ l = fl_utf8fromwc(selectDir->d_name, dstlen, findw.cFileName, l);
- selectDir->d_name[l] = 0;
- if (findw.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- /* Append a trailing slash to directory names... */
- strcat(selectDir->d_name, "/");
- }
- if (!select || (*select)(selectDir)) {
- if (nDir==NDir) {
+ selectDir->d_name[l] = 0;
+ if (findw.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ /* Append a trailing slash to directory names... */
+ strcat(selectDir->d_name, "/");
+ }
+ if (!select || (*select)(selectDir)) {
+ if (nDir==NDir) {
struct dirent **tempDir = (struct dirent **)calloc(sizeof(struct dirent*), (size_t)(NDir+33));
if (NDir) memcpy(tempDir, dir, sizeof(struct dirent*)*NDir);
if (dir) free(dir);
dir = tempDir;
NDir += 32;
- }
- dir[nDir] = selectDir;
- nDir++;
- dir[nDir] = 0;
- } else {
- free(selectDir);
- }
- } while (FindNextFileW(h, &findw));
+ }
+ dir[nDir] = selectDir;
+ nDir++;
+ dir[nDir] = 0;
+ } else {
+ free(selectDir);
+ }
+ } while (FindNextFileW(h, &findw));
ret = GetLastError();
if (ret != ERROR_NO_MORE_FILES) {
/* don't return an error code, because the dir list may still be valid
up to this point */
}
FindClose(h);
-
free (findIn);
-
if (compar) qsort(dir, (size_t)nDir, sizeof(*dir),
(int(*)(const void*, const void*))compar);
-
*namelist = dir;
return nDir;
}