Merge branch 'issue-99a': add OS error messages to Fl_File_Chooser

Pulling in Greg & Albrecht's work on PR #99 and PR #103.

This includes supporting operating system error messages
in the user's local language, which took some extra effort.
This commit is contained in:
Greg Ercolano
2020-07-14 11:34:18 -07:00
24 changed files with 374 additions and 167 deletions
+7 -13
View File
@@ -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_
+3
View File
@@ -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);
+14 -9
View File
@@ -7,6 +7,7 @@
#include <FL/Fl.H> // Fl_Timeout_Handler.. #include <FL/Fl.H> // Fl_Timeout_Handler..
#include <FL/fl_ask.H> // fl_alert() #include <FL/fl_ask.H> // fl_alert()
#include <FL/fl_utf8.h> // fl_utf8fromwc()
#include "ExternalCodeEditor_WIN32.h" #include "ExternalCodeEditor_WIN32.h"
@@ -19,22 +20,26 @@ static Fl_Timeout_Handler L_update_timer_cb = 0; // app's update timer ca
// [Static/Local] Get error message string for last failed WIN32 function. // [Static/Local] Get error message string for last failed WIN32 function.
// Returns a string pointing to static memory. // Returns a string pointing to static memory.
// //
// TODO: Is more code needed here to convert returned string to utf8? -erco
//
static const char *get_ms_errmsg() { static const char *get_ms_errmsg() {
static char emsg[1024]; static char emsg[1024];
DWORD lastErr = GetLastError(); DWORD lastErr = GetLastError();
DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_SYSTEM; FORMAT_MESSAGE_FROM_SYSTEM;
LPSTR mbuf = 0; DWORD langid = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
DWORD size = FormatMessageA(flags, 0, lastErr, MAKELANGID(LANG_NEUTRAL, LPWSTR mbuf = 0;
SUBLANG_DEFAULT), (LPSTR)&mbuf, 0, NULL); DWORD msize = 0;
if ( size == 0 ) {
_snprintf(emsg, sizeof(emsg), "Error Code %ld", long(lastErr)); // Get error message from Windows
msize = FormatMessageW(flags, 0, lastErr, langid, (LPWSTR)&mbuf, 0, NULL);
if ( msize == 0 ) {
_snprintf(emsg, sizeof(emsg), "Error #%ld", (unsigned long)lastErr);
} else { } else {
// Copy mbuf -> emsg (with '\r's removed -- they screw up fl_alert()) // Convert message to UTF-8
for ( char *src=mbuf, *dst=emsg; 1; src++ ) { int mlen = fl_utf8fromwc(emsg, sizeof(emsg), mbuf, msize);
// Remove '\r's -- they screw up fl_alert()
char *src = emsg, *dst = emsg;
for ( ; 1; src++ ) {
if ( *src == '\0' ) { *dst = '\0'; break; } if ( *src == '\0' ) { *dst = '\0'; break; }
if ( *src != '\r' ) { *dst++ = *src; } if ( *src != '\r' ) { *dst++ = *src; }
} }
+2
View File
@@ -39,6 +39,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <locale.h> // setlocale()..
#include <time.h> // time(), localtime(), etc. #include <time.h> // time(), localtime(), etc.
#include "../src/flstring.h" #include "../src/flstring.h"
@@ -1748,6 +1749,7 @@ static void sigint(SIGARG) {
int main(int argc,char **argv) { int main(int argc,char **argv) {
int i = 1; int i = 1;
setlocale(LC_ALL, ""); // enable multilanguage errors in file chooser
if (!Fl::args(argc,argv,i,arg) || i < argc-1) { if (!Fl::args(argc,argv,i,arg) || i < argc-1) {
static const char *msg = static const char *msg =
"usage: %s <switches> name.fl\n" "usage: %s <switches> name.fl\n"
+55 -22
View File
@@ -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) ||
+23
View File
@@ -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
View File
@@ -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
View File
@@ -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();
+6 -2
View File
@@ -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
+4 -2
View File
@@ -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)
+3 -1
View File
@@ -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;
+6 -2
View File
@@ -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);
+10 -5
View File
@@ -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)
+3 -1
View File
@@ -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;}
+19 -3
View File
@@ -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;
+1
View File
@@ -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];
+2 -1
View File
@@ -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);
} }
/** /**
+35 -20
View File
@@ -128,24 +128,47 @@ 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;
size_t len, num = 0, max = ENTRIES_MIN; size_t len, num = 0, max = ENTRIES_MIN;
struct dirent *entryp, **entries, **p; struct dirent *entryp, **entries, **p;
if (errmsg && errmsg_sz>0) errmsg[0] = '\0';
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));
// XXX: This would be a thread safe alternative to the above, but commented
// out because we can get either GNU or POSIX versions on linux,
// which AFAICT are incompatible: GNU doesn't guarantee errmsg is used
// at all, whereas POSIX /only/ fills buffer. The two calls are not really
// compatible but have the same name and different return values.. wtf?
//
// if (errmsg && errmsg_sz > 0) {
// strerror_r(errno, errmsg, errmsg_sz); // thread safe. Might be GNU, might be POSIX
// errmsg[errmsg_sz-1] = '\0'; // force null term b/c XSI does not specify
// }
return -1;
}
/* Read next directory entry */ /* Read next directory entry */
while (!readentry(dirp, &entryp, &len)) while (!readentry(dirp, &entryp, &len))
{ {
@@ -158,17 +181,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 +200,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;
} }
+55 -8
View File
@@ -1,7 +1,7 @@
/* /*
* Windows scandir function for the Fast Light Tool Kit (FLTK). * Windows scandir function for the Fast Light Tool Kit (FLTK).
* *
* Copyright 1998-2018 by Bill Spitzak and others. * Copyright 1998-2020 by Bill Spitzak and others.
* *
* This library is free software. Distribution and use rights are outlined in * This library is free software. Distribution and use rights are outlined in
* the file "COPYING" which should have been included with this file. If this * the file "COPYING" which should have been included with this file. If this
@@ -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);
LPWSTR mbuf = 0;
DWORD msize = 0;
/* Early exit if parent doesn't want an errmsg */
if (!errmsg || errmsg_sz <= 0 ) return;
/* Get error message from Windows */
msize = FormatMessageW(flags, 0, lastErr, langid, (LPWSTR)&mbuf, 0, NULL);
if ( msize == 0 ) {
fl_snprintf(errmsg, errmsg_sz, "Error #%lu", (unsigned long)lastErr);
} else {
/* convert message to UTF-8 */
int mlen = fl_utf8fromwc(errmsg, errmsg_sz, mbuf, msize);
/* Remove '\r's -- they screw up fl_alert()) */
char *src = errmsg, *dst = errmsg;
for ( ; 1; src++ ) {
if ( *src == '\0' ) { *dst = '\0'; break; }
if ( *src != '\r' ) { *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;
} }
+2
View File
@@ -39,6 +39,7 @@
#include <FL/Fl_Double_Window.H> #include <FL/Fl_Double_Window.H>
#include <FL/Fl_Simple_Terminal.H> #include <FL/Fl_Simple_Terminal.H>
#include <string.h> #include <string.h>
#include <locale.h> // setlocale()..
#define TERMINAL_HEIGHT 120 #define TERMINAL_HEIGHT 120
#define TERMINAL_GREEN "\033[32m" #define TERMINAL_GREEN "\033[32m"
@@ -92,6 +93,7 @@ main(int argc, // I - Number of command-line arguments
// Make the file chooser... // Make the file chooser...
setlocale(LC_ALL, ""); // enable multilanguage errors in file chooser
Fl::scheme(NULL); Fl::scheme(NULL);
Fl_File_Icon::load_system_icons(); Fl_File_Icon::load_system_icons();
+3
View File
@@ -23,10 +23,12 @@
#include <FL/Fl_Printer.H> #include <FL/Fl_Printer.H>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <locale.h> // setlocale()..
#include <FL/Fl_File_Chooser.H> #include <FL/Fl_File_Chooser.H>
#include <FL/fl_message.H> #include <FL/fl_message.H>
#include <FL/Fl_SVG_File_Surface.H> #include <FL/Fl_SVG_File_Surface.H>
#include <FL/Fl_Native_File_Chooser.H> #include <FL/Fl_Native_File_Chooser.H>
Fl_Box *b; Fl_Box *b;
Fl_Double_Window *w; Fl_Double_Window *w;
Fl_Shared_Image *img; Fl_Shared_Image *img;
@@ -124,6 +126,7 @@ int arg(int, char **argv, int &i) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
int i = 1; int i = 1;
setlocale(LC_ALL, ""); // enable multilanguage errors in file chooser
fl_register_images(); fl_register_images();
Fl::args(argc,argv,i,arg); Fl::args(argc,argv,i,arg);