mirror of
https://github.com/fltk/fltk.git
synced 2026-05-31 22:04:26 +08:00
First pass at fixing issue 99
A lot of code touched because low level functions needed to pass up
error messages reliably, and this had to propagate up the entire
driver hierarchy.
Tested OK *in English* on:
> Linux
> OSX 10.10.x
> Windows VS2017
> Windows mingw64
I have no way to test on Android, but it might work.
TODO: Needs testing in other languages to verify proper UTF8 error messages,
esp. with Windows VS, due to complexities with FormatMessage() -- see get_ms_errmsg()
This commit is contained in:
committed by
Albrecht Schlosser
parent
9925b0f128
commit
0693c70f57
+7
-13
@@ -40,6 +40,7 @@ class FL_EXPORT Fl_File_Browser : public Fl_Browser {
|
|||||||
const char *directory_;
|
const char *directory_;
|
||||||
uchar iconsize_;
|
uchar iconsize_;
|
||||||
const char *pattern_;
|
const char *pattern_;
|
||||||
|
const char *errmsg_;
|
||||||
|
|
||||||
int full_height() const;
|
int full_height() const;
|
||||||
int item_height(void *) const;
|
int item_height(void *) const;
|
||||||
@@ -50,11 +51,8 @@ class FL_EXPORT Fl_File_Browser : public Fl_Browser {
|
|||||||
public:
|
public:
|
||||||
enum { FILES, DIRECTORIES };
|
enum { FILES, DIRECTORIES };
|
||||||
|
|
||||||
/**
|
|
||||||
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(int, int, int, int, const char * = 0);
|
Fl_File_Browser(int, int, int, int, const char * = 0);
|
||||||
|
~Fl_File_Browser();
|
||||||
|
|
||||||
/** Sets or gets the size of the icons. The default size is 20 pixels. */
|
/** Sets or gets the size of the icons. The default size is 20 pixels. */
|
||||||
uchar iconsize() const { return (iconsize_); };
|
uchar iconsize() const { return (iconsize_); };
|
||||||
@@ -73,16 +71,7 @@ public:
|
|||||||
function in FLTK.
|
function in FLTK.
|
||||||
*/
|
*/
|
||||||
const char *filter() const { return (pattern_); };
|
const char *filter() const { return (pattern_); };
|
||||||
|
|
||||||
/**
|
|
||||||
Loads the specified directory into the browser. If icons have been
|
|
||||||
loaded then the correct icon is associated with each file in the list.
|
|
||||||
|
|
||||||
<P>The sort argument specifies a sort function to be used with
|
|
||||||
fl_filename_list().
|
|
||||||
*/
|
|
||||||
int load(const char *directory, Fl_File_Sort_F *sort = fl_numericsort);
|
int load(const char *directory, Fl_File_Sort_F *sort = fl_numericsort);
|
||||||
|
|
||||||
Fl_Fontsize textsize() const { return Fl_Browser::textsize(); };
|
Fl_Fontsize textsize() const { return Fl_Browser::textsize(); };
|
||||||
void textsize(Fl_Fontsize s) { Fl_Browser::textsize(s); iconsize_ = (uchar)(3 * s / 2); };
|
void textsize(Fl_Fontsize s) { Fl_Browser::textsize(s); iconsize_ = (uchar)(3 * s / 2); };
|
||||||
|
|
||||||
@@ -100,6 +89,11 @@ public:
|
|||||||
shown.
|
shown.
|
||||||
*/
|
*/
|
||||||
void filetype(int t) { filetype_ = t; };
|
void filetype(int t) { filetype_ = t; };
|
||||||
|
void errmsg(const char *emsg);
|
||||||
|
/**
|
||||||
|
Returns OS error messages, or NULL if none. Use when advised.
|
||||||
|
*/
|
||||||
|
const char* errmsg() const { return errmsg_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !_Fl_File_Browser_H_
|
#endif // !_Fl_File_Browser_H_
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ private:
|
|||||||
Fl_File_Browser *fileList;
|
Fl_File_Browser *fileList;
|
||||||
inline void cb_fileList_i(Fl_File_Browser*, void*);
|
inline void cb_fileList_i(Fl_File_Browser*, void*);
|
||||||
static void cb_fileList(Fl_File_Browser*, void*);
|
static void cb_fileList(Fl_File_Browser*, void*);
|
||||||
|
Fl_Box *errorBox;
|
||||||
Fl_Box *previewBox;
|
Fl_Box *previewBox;
|
||||||
public:
|
public:
|
||||||
Fl_Check_Button *previewButton;
|
Fl_Check_Button *previewButton;
|
||||||
@@ -231,6 +232,8 @@ private:
|
|||||||
Fl_Widget* ext_group;
|
Fl_Widget* ext_group;
|
||||||
public:
|
public:
|
||||||
Fl_Widget* add_extra(Fl_Widget* gr);
|
Fl_Widget* add_extra(Fl_Widget* gr);
|
||||||
|
protected:
|
||||||
|
void show_error_box(int val);
|
||||||
};
|
};
|
||||||
FL_EXPORT char *fl_dir_chooser(const char *message,const char *fname,int relative=0);
|
FL_EXPORT char *fl_dir_chooser(const char *message,const char *fname,int relative=0);
|
||||||
FL_EXPORT char *fl_file_chooser(const char *message,const char *pat,const char *fname,int relative=0);
|
FL_EXPORT char *fl_file_chooser(const char *message,const char *pat,const char *fname,int relative=0);
|
||||||
|
|||||||
+55
-22
@@ -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
|
Fl_File_Browser::Fl_File_Browser(int X, // I - Upper-lefthand X coordinate
|
||||||
int Y, // I - Upper-lefthand Y coordinate
|
int Y, // I - Upper-lefthand Y coordinate
|
||||||
int W, // I - Width in pixels
|
int W, // I - Width in pixels
|
||||||
@@ -370,13 +370,40 @@ Fl_File_Browser::Fl_File_Browser(int X, // I - Upper-lefthand X coordina
|
|||||||
directory_ = "";
|
directory_ = "";
|
||||||
iconsize_ = (uchar)(3 * textsize() / 2);
|
iconsize_ = (uchar)(3 * textsize() / 2);
|
||||||
filetype_ = FILES;
|
filetype_ = FILES;
|
||||||
|
errmsg_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
// DTOR
|
||||||
// 'Fl_File_Browser::load()' - Load a directory into the browser.
|
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
|
int // O - Number of files loaded
|
||||||
Fl_File_Browser::load(const char *directory,// I - Directory to load
|
Fl_File_Browser::load(const char *directory,// I - Directory to load
|
||||||
Fl_File_Sort_F *sort) // I - Sort function to use
|
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
|
char filename[4096]; // Current file
|
||||||
Fl_File_Icon *icon; // Icon to use
|
Fl_File_Icon *icon; // Icon to use
|
||||||
|
|
||||||
|
errmsg(NULL); // clear errors first
|
||||||
|
|
||||||
// printf("Fl_File_Browser::load(\"%s\")\n", directory);
|
// 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;
|
directory_ = directory;
|
||||||
|
|
||||||
if (!directory)
|
if (!directory) {
|
||||||
return (0);
|
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
|
// No directory specified; for UNIX list all mount points. For DOS
|
||||||
// list all valid drive letters...
|
// 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)
|
if ((icon = Fl_File_Icon::find("any", Fl_File_Icon::DEVICE)) == NULL)
|
||||||
icon = Fl_File_Icon::find("any", Fl_File_Icon::DIRECTORY);
|
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);
|
num_files = Fl::system_driver()->file_browser_load_filesystem(this, filename, (int)sizeof(filename), icon);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
dirent **files; // Files in in directory
|
dirent **files; // Files in in directory
|
||||||
//
|
char emsg[1024] = "";
|
||||||
// Build the file list...
|
|
||||||
//
|
// Build the file list, check for errors
|
||||||
num_files = Fl::system_driver()->file_browser_load_directory(directory_, filename, sizeof(filename), &files, sort);
|
num_files = Fl::system_driver()->file_browser_load_directory(directory_,
|
||||||
if (num_files <= 0)
|
filename, sizeof(filename),
|
||||||
return (0);
|
&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 ++) {
|
for (i = 0, num_dirs = 0; i < num_files; i ++) {
|
||||||
if (strcmp(files[i]->d_name, "./")) {
|
if (strcmp(files[i]->d_name, "./")) {
|
||||||
snprintf(filename, sizeof(filename), "%s/%s", directory_,
|
fl_snprintf(filename, sizeof(filename), "%s/%s", directory_, files[i]->d_name);
|
||||||
files[i]->d_name);
|
|
||||||
|
|
||||||
icon = Fl_File_Icon::find(filename);
|
icon = Fl_File_Icon::find(filename);
|
||||||
if ((icon && icon->type() == Fl_File_Icon::DIRECTORY) ||
|
if ((icon && icon->type() == Fl_File_Icon::DIRECTORY) ||
|
||||||
|
|||||||
@@ -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_);
|
o->callback((Fl_Callback*)cb_);
|
||||||
{ fileList = new Fl_File_Browser(10, 45, 295, 225);
|
{ fileList = new Fl_File_Browser(10, 45, 295, 225);
|
||||||
fileList->type(2);
|
fileList->type(2);
|
||||||
|
fileList->box(FL_DOWN_BOX);
|
||||||
fileList->callback((Fl_Callback*)cb_fileList);
|
fileList->callback((Fl_Callback*)cb_fileList);
|
||||||
fileList->window()->hotspot(fileList);
|
fileList->window()->hotspot(fileList);
|
||||||
} // Fl_File_Browser* 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 = new Fl_Box(305, 45, 175, 225, "?");
|
||||||
previewBox->box(FL_DOWN_BOX);
|
previewBox->box(FL_DOWN_BOX);
|
||||||
previewBox->labelsize(100);
|
previewBox->labelsize(100);
|
||||||
@@ -471,3 +480,17 @@ Fl_Widget* Fl_File_Chooser::add_extra(Fl_Widget* gr) {
|
|||||||
}
|
}
|
||||||
return ret;
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+23
-6
@@ -66,7 +66,8 @@ class FL_EXPORT Fl_File_Chooser {open
|
|||||||
}
|
}
|
||||||
decl {void update_preview();} {private local
|
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_) {
|
code {if (!prefs_) {
|
||||||
prefs_ = new Fl_Preferences(Fl_Preferences::CORE_USER, "fltk.org", "filechooser");
|
prefs_ = new Fl_Preferences(Fl_Preferences::CORE_USER, "fltk.org", "filechooser");
|
||||||
}} {}
|
}} {}
|
||||||
@@ -77,11 +78,11 @@ class FL_EXPORT Fl_File_Chooser {open
|
|||||||
fileList->deselect();
|
fileList->deselect();
|
||||||
Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this);
|
Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this);
|
||||||
window->hide();} open
|
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);}
|
code0 {if (title) window->label(title);}
|
||||||
code1 {\#include <stdio.h>}
|
code1 {\#include <stdio.h>}
|
||||||
code2 {\#include <stdlib.h>}
|
code2 {\#include <stdlib.h>}
|
||||||
code3 {\#include <string.h>} modal
|
code3 {\#include <string.h>} modal visible
|
||||||
} {
|
} {
|
||||||
Fl_Group {} {open
|
Fl_Group {} {open
|
||||||
private xywh {10 10 470 25}
|
private xywh {10 10 470 25}
|
||||||
@@ -106,14 +107,18 @@ window->hide();} open
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Fl_Tile {} {
|
Fl_Tile {} {
|
||||||
callback {update_preview();}
|
callback {update_preview();} open
|
||||||
private xywh {10 45 470 225} resizable
|
private xywh {10 45 470 225} resizable
|
||||||
} {
|
} {
|
||||||
Fl_File_Browser fileList {
|
Fl_File_Browser fileList {
|
||||||
callback {fileListCB();}
|
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>}
|
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 {
|
Fl_Box previewBox {
|
||||||
label {?}
|
label {?}
|
||||||
private xywh {305 45 175 225} box DOWN_BOX labelsize 100 align 80
|
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);} {}
|
code {fileList->textfont(f);} {}
|
||||||
}
|
}
|
||||||
Function {textfont()} {selected return_type Fl_Font
|
Function {textfont()} {return_type Fl_Font
|
||||||
} {
|
} {
|
||||||
code {return (fileList->textfont());} {}
|
code {return (fileList->textfont());} {}
|
||||||
}
|
}
|
||||||
@@ -475,6 +480,18 @@ window->resizable(svres);} {}
|
|||||||
}
|
}
|
||||||
code {return ret;} {}
|
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
|
decl {FL_EXPORT char *fl_dir_chooser(const char *message,const char *fname,int relative=0);} {public local
|
||||||
|
|||||||
+21
-10
@@ -1020,17 +1020,15 @@ void Fl_File_Chooser::preview(int e)
|
|||||||
Fl_Group *p = previewBox->parent();
|
Fl_Group *p = previewBox->parent();
|
||||||
if (e) {
|
if (e) {
|
||||||
int w = p->w() * 2 / 3;
|
int w = p->w() * 2 / 3;
|
||||||
fileList->resize(fileList->x(), fileList->y(),
|
fileList->resize(fileList->x(), fileList->y(), w, fileList->h());
|
||||||
w, fileList->h());
|
errorBox->resize(errorBox->x(), errorBox->y(), w, errorBox->h());
|
||||||
previewBox->resize(fileList->x()+w, previewBox->y(),
|
previewBox->resize(fileList->x()+w, previewBox->y(), p->w()-w, previewBox->h());
|
||||||
p->w()-w, previewBox->h());
|
|
||||||
previewBox->show();
|
previewBox->show();
|
||||||
update_preview();
|
update_preview();
|
||||||
} else {
|
} else {
|
||||||
fileList->resize(fileList->x(), fileList->y(),
|
fileList->resize(fileList->x(), fileList->y(), p->w(), fileList->h());
|
||||||
p->w(), fileList->h());
|
errorBox->resize(errorBox->x(), errorBox->y(), p->w(), errorBox->h());
|
||||||
previewBox->resize(p->x()+p->w(), previewBox->y(),
|
previewBox->resize(p->x()+p->w(), previewBox->y(), 0, previewBox->h());
|
||||||
0, previewBox->h());
|
|
||||||
previewBox->hide();
|
previewBox->hide();
|
||||||
}
|
}
|
||||||
p->init_sizes();
|
p->init_sizes();
|
||||||
@@ -1070,7 +1068,14 @@ Fl_File_Chooser::rescan()
|
|||||||
okButton->deactivate();
|
okButton->deactivate();
|
||||||
|
|
||||||
// Build the file list...
|
// 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();
|
if (Fl::system_driver()->dot_file_hidden() && !showHiddenButton->value()) remove_hidden_files();
|
||||||
// Update the preview box...
|
// Update the preview box...
|
||||||
update_preview();
|
update_preview();
|
||||||
@@ -1094,7 +1099,13 @@ void Fl_File_Chooser::rescan_keep_filename()
|
|||||||
strlcpy(pathname, fn, sizeof(pathname));
|
strlcpy(pathname, fn, sizeof(pathname));
|
||||||
|
|
||||||
// Build the file list...
|
// 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();
|
if (Fl::system_driver()->dot_file_hidden() && !showHiddenButton->value()) remove_hidden_files();
|
||||||
// Update the preview box...
|
// Update the preview box...
|
||||||
update_preview();
|
update_preview();
|
||||||
|
|||||||
@@ -128,7 +128,9 @@ public:
|
|||||||
virtual int event_key(int k) {return 0;}
|
virtual int event_key(int k) {return 0;}
|
||||||
virtual int get_key(int k) {return 0;}
|
virtual int get_key(int k) {return 0;}
|
||||||
// implement scandir-like function
|
// 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
|
// the default implementation of filename_expand() may be enough
|
||||||
virtual int filename_expand(char *to, int tolen, const char *from);
|
virtual int filename_expand(char *to, int tolen, const char *from);
|
||||||
// to implement
|
// to implement
|
||||||
@@ -162,7 +164,9 @@ public:
|
|||||||
// implement to support Fl_File_Browser::load()
|
// 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;}
|
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
|
// 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
|
// implement to support Fl_Preferences
|
||||||
virtual void newUUID(char *uuidBuffer) { uuidBuffer[0] = 0; }
|
virtual void newUUID(char *uuidBuffer) { uuidBuffer[0] = 0; }
|
||||||
// implement to support Fl_Preferences
|
// implement to support Fl_Preferences
|
||||||
|
|||||||
@@ -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,
|
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)
|
int Fl_System_Driver::file_type(const char *filename)
|
||||||
|
|||||||
@@ -70,7 +70,9 @@ public:
|
|||||||
// these 2 are in Fl_get_key_win32.cxx
|
// these 2 are in Fl_get_key_win32.cxx
|
||||||
virtual int event_key(int k);
|
virtual int event_key(int k);
|
||||||
virtual int get_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_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_relative(char *to, int tolen, const char *from, const char *base);
|
||||||
virtual int filename_absolute(char *to, int tolen, const char *from);
|
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 open_uri(const char *uri, char *msg, int msglen);
|
||||||
virtual int use_recent_tooltip_fix() {return 1;}
|
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_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 void newUUID(char *uuidBuffer);
|
||||||
virtual char *preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor,
|
virtual char *preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor,
|
||||||
const char *application);
|
const char *application);
|
||||||
|
|||||||
@@ -486,11 +486,13 @@ int Fl_WinAPI_System_Driver::clocale_printf(FILE *output, const char *format, va
|
|||||||
return retval;
|
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
|
// For Windows we have a special scandir implementation that uses
|
||||||
// the Win32 "wide" functions for lookup, avoiding the code page mess
|
// the Win32 "wide" functions for lookup, avoiding the code page mess
|
||||||
// entirely. It also fixes up the trailing '/'.
|
// 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) {
|
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,
|
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);
|
strlcpy(filename, directory, name_size);
|
||||||
int i = (int) (strlen(filename) - 1);
|
int i = (int) (strlen(filename) - 1);
|
||||||
@@ -756,7 +760,7 @@ int Fl_WinAPI_System_Driver::file_browser_load_directory(const char *directory,
|
|||||||
filename[2] = '/';
|
filename[2] = '/';
|
||||||
else if (filename[i] != '/' && filename[i] != '\\')
|
else if (filename[i] != '/' && filename[i] != '\\')
|
||||||
strlcat(filename, "/", name_size);
|
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)
|
void Fl_WinAPI_System_Driver::newUUID(char *uuidBuffer)
|
||||||
|
|||||||
@@ -52,7 +52,9 @@ public:
|
|||||||
// these 2 are in Fl_get_key_mac.cxx
|
// these 2 are in Fl_get_key_mac.cxx
|
||||||
virtual int event_key(int k);
|
virtual int event_key(int k);
|
||||||
virtual int get_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 open_uri(const char *uri, char *msg, int msglen);
|
||||||
virtual int need_test_shortcut_extra() {return 1;}
|
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);
|
virtual int file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "Fl_Darwin_System_Driver.H"
|
#include "Fl_Darwin_System_Driver.H"
|
||||||
|
#include <src/flstring.h>
|
||||||
#include <FL/platform.H>
|
#include <FL/platform.H>
|
||||||
#include <FL/Fl.H>
|
#include <FL/Fl.H>
|
||||||
#include <FL/Fl_File_Browser.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);
|
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;
|
int dirlen;
|
||||||
char *dirloc;
|
char *dirloc;
|
||||||
// Assume that locale encoding is no less dense than UTF-8
|
// 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
|
# else
|
||||||
int n = scandir(dirloc, list, 0, (int(*)(const void*,const void*))sort);
|
int n = scandir(dirloc, list, 0, (int(*)(const void*,const void*))sort);
|
||||||
# endif
|
# 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
|
// convert every filename to UTF-8, and append a '/' to all
|
||||||
// filenames that are directories
|
// filenames that are directories
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
@@ -68,7 +68,9 @@ public:
|
|||||||
// these 2 are in Fl_get_key_win32.cxx
|
// these 2 are in Fl_get_key_win32.cxx
|
||||||
virtual int event_key(int k);
|
virtual int event_key(int k);
|
||||||
virtual int get_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_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_relative(char *to, int tolen, const char *from, const char *base);
|
||||||
virtual int filename_absolute(char *to, int tolen, const char *from);
|
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 open_uri(const char *uri, char *msg, int msglen);
|
||||||
virtual int use_recent_tooltip_fix() {return 1;}
|
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_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 void newUUID(char *uuidBuffer);
|
||||||
virtual char *preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor,
|
virtual char *preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor,
|
||||||
const char *application);
|
const char *application);
|
||||||
|
|||||||
@@ -61,7 +61,8 @@ static wchar_t *wbuf1 = NULL;
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
int fl_scandir(const char *dirname, struct dirent ***namelist,
|
int fl_scandir(const char *dirname, struct dirent ***namelist,
|
||||||
int (*select)(struct dirent *),
|
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;
|
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
|
// For Windows we have a special scandir implementation that uses
|
||||||
// the Win32 "wide" functions for lookup, avoiding the code page mess
|
// the Win32 "wide" functions for lookup, avoiding the code page mess
|
||||||
// entirely. It also fixes up the trailing '/'.
|
// 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) {
|
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,
|
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);
|
strlcpy(filename, directory, name_size);
|
||||||
int i = (int) (strlen(filename) - 1);
|
int i = (int) (strlen(filename) - 1);
|
||||||
@@ -758,7 +763,7 @@ int Fl_WinAPI_System_Driver::file_browser_load_directory(const char *directory,
|
|||||||
filename[2] = '/';
|
filename[2] = '/';
|
||||||
else if (filename[i] != '/' && filename[i] != '\\')
|
else if (filename[i] != '/' && filename[i] != '\\')
|
||||||
strlcat(filename, "/", name_size);
|
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)
|
void Fl_WinAPI_System_Driver::newUUID(char *uuidBuffer)
|
||||||
|
|||||||
@@ -34,7 +34,9 @@ public:
|
|||||||
// these 2 are in Fl_get_key.cxx
|
// these 2 are in Fl_get_key.cxx
|
||||||
virtual int event_key(int k);
|
virtual int event_key(int k);
|
||||||
virtual int get_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 need_menu_handle_part1_extra() {return 1;}
|
||||||
virtual int open_uri(const char *uri, char *msg, int msglen);
|
virtual int open_uri(const char *uri, char *msg, int msglen);
|
||||||
virtual int use_tooltip_timeout_condition() {return 1;}
|
virtual int use_tooltip_timeout_condition() {return 1;}
|
||||||
|
|||||||
@@ -25,7 +25,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#include <string.h> // strerror(errno)
|
||||||
|
#include <errno.h> // errno
|
||||||
|
|
||||||
#if defined(_AIX)
|
#if defined(_AIX)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -56,7 +57,8 @@ extern "C" {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
int fl_scandir(const char *dirname, struct dirent ***namelist,
|
int fl_scandir(const char *dirname, struct dirent ***namelist,
|
||||||
int (*select)(struct dirent *),
|
int (*select)(struct dirent *),
|
||||||
int (*compar)(struct dirent **, struct dirent **));
|
int (*compar)(struct dirent **, struct dirent **),
|
||||||
|
char *errmsg, int errmsg_sz);
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
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;
|
int dirlen;
|
||||||
char *dirloc;
|
char *dirloc;
|
||||||
|
|
||||||
|
if (errmsg && errmsg_sz>0) errmsg[0] = '\0';
|
||||||
|
|
||||||
// Assume that locale encoding is no less dense than UTF-8
|
// Assume that locale encoding is no less dense than UTF-8
|
||||||
dirlen = strlen(d);
|
dirlen = strlen(d);
|
||||||
dirloc = (char *)malloc(dirlen + 1);
|
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);
|
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
|
// convert every filename to UTF-8, and append a '/' to all
|
||||||
// filenames that are directories
|
// filenames that are directories
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
@@ -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) {
|
int Fl_System_Driver::filename_isdir(const char* n) {
|
||||||
struct stat s;
|
struct stat s;
|
||||||
char fn[FL_PATH_MAX];
|
char fn[FL_PATH_MAX];
|
||||||
|
|||||||
@@ -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
|
to put unpadded numbers in consecutive order; upper and lowercase letters are compared
|
||||||
according to their ASCII ordering - uppercase before lowercase.
|
according to their ASCII ordering - uppercase before lowercase.
|
||||||
\return the number of entries if no error, a negative value otherwise.
|
\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) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+23
-20
@@ -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
|
int
|
||||||
fl_scandir(const char *dir, struct dirent ***namelist,
|
fl_scandir(const char *dir, struct dirent ***namelist,
|
||||||
int (*sel)(struct dirent *),
|
int (*sel)(struct dirent *),
|
||||||
int (*compar)(struct dirent **, struct dirent **))
|
int (*compar)(struct dirent **, struct dirent **),
|
||||||
|
char *errmsg, int errmsg_sz) {
|
||||||
{
|
{
|
||||||
int result = -1;
|
int result = -1;
|
||||||
DIR *dirp;
|
DIR *dirp;
|
||||||
@@ -140,12 +145,18 @@ fl_scandir(const char *dir, struct dirent ***namelist,
|
|||||||
struct dirent *entryp, **entries, **p;
|
struct dirent *entryp, **entries, **p;
|
||||||
|
|
||||||
entries = (struct dirent **) malloc(sizeof(*entries) * max);
|
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) */
|
/* Open directory 'dir' (and verify that it really is a directory) */
|
||||||
dirp = opendir(dir);
|
dirp = opendir(dir);
|
||||||
if (NULL != dirp)
|
if (NULL == dirp) {
|
||||||
{
|
if (errmsg) fl_snprintf(errmsg, errmsg_sz, "%s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read next directory entry */
|
/* Read next directory entry */
|
||||||
while (!readentry(dirp, &entryp, &len))
|
while (!readentry(dirp, &entryp, &len))
|
||||||
{
|
{
|
||||||
@@ -158,17 +169,14 @@ fl_scandir(const char *dir, struct dirent ***namelist,
|
|||||||
/* Apply select function if there is one provided */
|
/* Apply select function if there is one provided */
|
||||||
if (NULL != sel) { if (!sel(entryp)) continue; }
|
if (NULL != sel) { if (!sel(entryp)) continue; }
|
||||||
entries[num++] = entryp;
|
entries[num++] = entryp;
|
||||||
if (num >= max)
|
if (num >= max) {
|
||||||
{
|
|
||||||
/* Allocate exponentially increasing sized memory chunks */
|
/* Allocate exponentially increasing sized memory chunks */
|
||||||
if (INT_MAX / 2 >= (int) max) { max *= (size_t) 2; }
|
if (INT_MAX / 2 >= (int) max) { max *= (size_t) 2; }
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
p = (struct dirent **) realloc((void *) entries,
|
p = (struct dirent **) realloc((void *)entries, sizeof(*entries)*max);
|
||||||
sizeof(*entries) * max);
|
|
||||||
if (NULL != p) { entries = p; }
|
if (NULL != p) { entries = p; }
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
@@ -180,24 +188,19 @@ fl_scandir(const char *dir, struct dirent ***namelist,
|
|||||||
* Therefore we ignore the return value because we can't call 'closedir()'
|
* Therefore we ignore the return value because we can't call 'closedir()'
|
||||||
* again and must hope that the system has released all resources.
|
* again and must hope that the system has released all resources.
|
||||||
*/
|
*/
|
||||||
}
|
|
||||||
/* Sort entries in array if there is a compare function provided */
|
/* Sort entries in array if there is a compare function provided */
|
||||||
if (NULL != compar)
|
if (NULL != compar) {
|
||||||
{
|
|
||||||
qsort((void *) entries, num, sizeof(*entries),
|
qsort((void *) entries, num, sizeof(*entries),
|
||||||
(int (*)(const void *, const void *)) compar);
|
(int (*)(const void *, const void *)) compar);
|
||||||
}
|
}
|
||||||
*namelist = entries;
|
*namelist = entries;
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for error */
|
/* Check for error */
|
||||||
if (-1 == result)
|
if (-1 == result) {
|
||||||
{
|
|
||||||
/* Free all memory we have allocated */
|
/* Free all memory we have allocated */
|
||||||
while (num--) { free(entries[num]); }
|
while (num--) { free(entries[num]); }
|
||||||
free(entries);
|
free(entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+54
-7
@@ -15,16 +15,59 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __CYGWIN__
|
#ifndef __CYGWIN__
|
||||||
/* Emulation of POSIX scandir() call */
|
/* Emulation of POSIX scandir() call with error messages */
|
||||||
#include <FL/platform_types.h>
|
#include <FL/platform_types.h>
|
||||||
#include <FL/fl_utf8.h>
|
#include <FL/fl_utf8.h>
|
||||||
#include "flstring.h"
|
#include "flstring.h"
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <stdlib.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 fl_scandir(const char *dirname, struct dirent ***namelist,
|
||||||
int (*select)(struct dirent *),
|
int (*select)(struct dirent *),
|
||||||
int (*compar)(struct dirent **, struct dirent **)) {
|
int (*compar)(struct dirent **, struct dirent **),
|
||||||
|
char *errmsg, int errmsg_sz) {
|
||||||
int len;
|
int len;
|
||||||
char *findIn, *d, is_dir = 0;
|
char *findIn, *d, is_dir = 0;
|
||||||
WIN32_FIND_DATAW findw;
|
WIN32_FIND_DATAW findw;
|
||||||
@@ -33,9 +76,14 @@ int fl_scandir(const char *dirname, struct dirent ***namelist,
|
|||||||
struct dirent **dir = 0, *selectDir;
|
struct dirent **dir = 0, *selectDir;
|
||||||
unsigned long ret;
|
unsigned long ret;
|
||||||
|
|
||||||
|
if (errmsg && errmsg_sz>0) errmsg[0] = '\0';
|
||||||
len = (int) strlen(dirname);
|
len = (int) strlen(dirname);
|
||||||
findIn = (char *)malloc((size_t)(len+10));
|
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);
|
strcpy(findIn, dirname);
|
||||||
|
|
||||||
/* #if defined(__GNUC__) */
|
/* #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 ((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 */
|
if (!is_dir) { /* this file may still be a directory that we need to list */
|
||||||
DWORD attr = GetFileAttributes(findIn);
|
DWORD attr = GetFileAttributes(findIn);
|
||||||
if (attr&FILE_ATTRIBUTE_DIRECTORY)
|
if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY) )
|
||||||
strcpy(d, "\\*");
|
strcpy(d, "\\*");
|
||||||
}
|
}
|
||||||
{ /* Create a block to limit the scope while we find the initial "wide" filename */
|
{ /* Create a block to limit the scope while we find the initial "wide" filename */
|
||||||
@@ -64,11 +112,13 @@ int fl_scandir(const char *dirname, struct dirent ***namelist,
|
|||||||
h = FindFirstFileW(wbuf, &findw); /* get a handle to the first filename in the search */
|
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 */
|
free(wbuf); /* release the "wide" buffer before the pointer goes out of scope */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h==INVALID_HANDLE_VALUE) {
|
if (h==INVALID_HANDLE_VALUE) {
|
||||||
free(findIn);
|
free(findIn);
|
||||||
ret = GetLastError();
|
ret = GetLastError();
|
||||||
if (ret != ERROR_NO_MORE_FILES) {
|
if (ret != ERROR_NO_MORE_FILES) {
|
||||||
nDir = -1;
|
nDir = -1;
|
||||||
|
get_ms_errmsg(errmsg, errmsg_sz); /* return OS error msg */
|
||||||
}
|
}
|
||||||
*namelist = dir;
|
*namelist = dir;
|
||||||
return nDir;
|
return nDir;
|
||||||
@@ -107,12 +157,9 @@ int fl_scandir(const char *dirname, struct dirent ***namelist,
|
|||||||
up to this point */
|
up to this point */
|
||||||
}
|
}
|
||||||
FindClose(h);
|
FindClose(h);
|
||||||
|
|
||||||
free (findIn);
|
free (findIn);
|
||||||
|
|
||||||
if (compar) qsort(dir, (size_t)nDir, sizeof(*dir),
|
if (compar) qsort(dir, (size_t)nDir, sizeof(*dir),
|
||||||
(int(*)(const void*, const void*))compar);
|
(int(*)(const void*, const void*))compar);
|
||||||
|
|
||||||
*namelist = dir;
|
*namelist = dir;
|
||||||
return nDir;
|
return nDir;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user