#include <FL/Fl_File_Chooser.H>
#include "Fl_System_Driver.H"
#include <FL/Fl.H>
#include <FL/filename.H>
#include <FL/fl_ask.H>
#include <FL/platform.H>
#include <FL/Fl_Shared_Image.H>
#include <FL/fl_draw.H>
#include <FL/fl_string_functions.h>
#include <stdio.h>
#include <stdlib.h>
#include "flstring.h"
#include <errno.h>
#include <sys/stat.h>
Fl_Preferences* Fl_File_Chooser::prefs_ = NULL;
const char *Fl_File_Chooser::add_favorites_label = "Add to Favorites";
const char *Fl_File_Chooser::all_files_label = "All Files (*)";
const char *Fl_File_Chooser::custom_filter_label = "Custom Filter";
const char *Fl_File_Chooser::existing_file_label = "Please choose an existing file!";
const char *Fl_File_Chooser::favorites_label = "Favorites";
const char *Fl_File_Chooser::filename_label = "Filename:";
const char *Fl_File_Chooser::filesystems_label = Fl::system_driver()->filesystems_label();
const char *Fl_File_Chooser::manage_favorites_label = "Manage Favorites";
const char *Fl_File_Chooser::new_directory_label = "New Directory?";
const char *Fl_File_Chooser::new_directory_tooltip = "Create a new directory.";
const char *Fl_File_Chooser::preview_label = "Preview";
const char *Fl_File_Chooser::save_label = "Save";
const char *Fl_File_Chooser::show_label = "Show:";
const char *Fl_File_Chooser::hidden_label = "Show hidden files";
Fl_File_Sort_F *Fl_File_Chooser::sort = fl_numericsort;
static int compare_dirnames(const char *a, const char *b);
static void quote_pathname(char *, const char *, int);
static void unquote_pathname(char *, const char *, int);
int Fl_File_Chooser::count() {
int i; int fcount; const char *filename;
filename = fileName->value();
if (!(type_ & MULTI)) {
if (!filename || !filename[0]) return 0;
else return 1;
}
for (i = 1, fcount = 0; i <= fileList->size(); i ++)
if (fileList->selected(i)) {
fcount ++;
}
if (fcount) return fcount;
else if (!filename || !filename[0]) return 0;
else return 1;
}
void
Fl_File_Chooser::directory(const char *d){
char *dirptr; char fixpath[FL_PATH_MAX];
if (d == NULL)
d = ".";
if (Fl::system_driver()->backslash_as_slash()) {
char *slash; if (strchr(d, '\\')) {
strlcpy(fixpath, d, sizeof(fixpath));
for (slash = strchr(fixpath, '\\'); slash; slash = strchr(slash + 1, '\\'))
*slash = '/';
d = fixpath;
}
}
if (d[0] != '\0')
{
if (d[0] != '/' && d[0] != '\\' && ( !Fl::system_driver()->colon_is_drive() || d[1] != ':' ) )
fl_filename_absolute(directory_, d);
else
strlcpy(directory_, d, sizeof(directory_));
dirptr = directory_ + strlen(directory_) - 1;
if ((*dirptr == '/' || *dirptr == '\\') && dirptr > directory_)
*dirptr = '\0';
dirptr = directory_ + strlen(directory_) - 3;
if (dirptr >= directory_ && strcmp(dirptr, "/..") == 0) {
*dirptr = '\0';
while (dirptr > directory_) {
if (*dirptr == '/') break;
dirptr --;
}
if (dirptr >= directory_ && *dirptr == '/')
*dirptr = '\0';
} else if ((dirptr + 1) >= directory_ && strcmp(dirptr + 1, "/.") == 0) {
dirptr[1] = '\0';
}
}
else
directory_[0] = '\0';
if (shown()) {
rescan();
}
}
void
Fl_File_Chooser::favoritesButtonCB()
{
int v; char pathname[FL_PATH_MAX], menuname[FL_PATH_MAX];
v = favoritesButton->value();
if (!v) {
if (Fl::system_driver()->home_directory_name()) v = favoritesButton->size() - 5;
else v = favoritesButton->size() - 4;
snprintf(menuname, FL_PATH_MAX, "favorite%02d", v);
prefs_->set(menuname, directory_);
prefs_->flush();
update_favorites();
if (favoritesButton->size() > 104) {
((Fl_Menu_Item *)favoritesButton->menu())[0].deactivate();
}
} else if (v == 1) {
favoritesCB(0);
} else if (v == 2) {
directory("");
} else {
unquote_pathname(pathname, favoritesButton->text(v), sizeof(pathname));
directory(pathname);
}
}
void
Fl_File_Chooser::favoritesCB(Fl_Widget *w)
{
int i; char name[32], pathname[1024];
if (!w) {
favList->clear();
favList->deselect();
for (i = 0; i < 100; i ++) {
snprintf(name, sizeof(name), "favorite%02d", i);
prefs_->get(name, pathname, "", sizeof(pathname));
if (!pathname[0]) break;
favList->add(pathname,
Fl_File_Icon::find(pathname, Fl_File_Icon::DIRECTORY));
}
favUpButton->deactivate();
favDeleteButton->deactivate();
favDownButton->deactivate();
favOkButton->deactivate();
favWindow->hotspot(favList);
favWindow->show();
} else if (w == favList) {
i = favList->value();
if (i) {
if (i > 1) favUpButton->activate();
else favUpButton->deactivate();
favDeleteButton->activate();
if (i < favList->size()) favDownButton->activate();
else favDownButton->deactivate();
} else {
favUpButton->deactivate();
favDeleteButton->deactivate();
favDownButton->deactivate();
}
} else if (w == favUpButton) {
i = favList->value();
favList->insert(i - 1, favList->text(i), favList->data(i));
favList->remove(i + 1);
favList->select(i - 1);
if (i == 2) favUpButton->deactivate();
favDownButton->activate();
favOkButton->activate();
} else if (w == favDeleteButton) {
i = favList->value();
favList->remove(i);
if (i > favList->size()) i --;
favList->select(i);
if (i < favList->size()) favDownButton->activate();
else favDownButton->deactivate();
if (i > 1) favUpButton->activate();
else favUpButton->deactivate();
if (!i) favDeleteButton->deactivate();
favOkButton->activate();
} else if (w == favDownButton) {
i = favList->value();
favList->insert(i + 2, favList->text(i), favList->data(i));
favList->remove(i);
favList->select(i + 1);
if ((i + 1) == favList->size()) favDownButton->deactivate();
favUpButton->activate();
favOkButton->activate();
} else if (w == favOkButton) {
for (i = 0; i < favList->size(); i ++) {
snprintf(name, sizeof(name), "favorite%02d", i);
prefs_->set(name, favList->text(i + 1));
}
for (; i < 100; i ++) {
snprintf(name, sizeof(name), "favorite%02d", i);
prefs_->get(name, pathname, "", sizeof(pathname));
if (pathname[0]) prefs_->set(name, "");
else break;
}
update_favorites();
prefs_->flush();
favWindow->hide();
}
}
void
Fl_File_Chooser::fileListCB()
{
char *filename, pathname[FL_PATH_MAX + 4];
filename = (char *)fileList->text(fileList->value());
if (!filename)
return;
if (!directory_[0]) {
strlcpy(pathname, filename, sizeof(pathname));
} else if (strcmp(directory_, "/") == 0) {
snprintf(pathname, sizeof(pathname), "/%s", filename);
} else {
snprintf(pathname, sizeof(pathname), "%s/%s", directory_, filename);
}
if (Fl::event_clicks()) {
int condition = 0;
if (Fl::system_driver()->colon_is_drive() && strlen(pathname) == 2 && pathname[1] == ':') condition = 1;
if (!condition) condition = Fl::system_driver()->filename_isdir_quick(pathname);
if (condition)
{
directory(pathname);
Fl::event_clicks(-1);
}
else
{
window->hide();
if (callback_) (*callback_)(this, data_);
}
}
else
{
filename = pathname + strlen(pathname) - 1;
if ((type_ & MULTI) && !(type_ & DIRECTORY)) {
if (*filename == '/') {
int i = fileList->value();
fileList->deselect();
fileList->select(i);
} else {
int i;
const char *temp;
for (i = 1; i <= fileList->size(); i ++) {
if (i != fileList->value() && fileList->selected(i)) {
temp = fileList->text(i);
temp += strlen(temp) - 1;
if (*temp == '/') break; }
}
if (i <= fileList->size()) {
i = fileList->value();
fileList->deselect();
fileList->select(i);
}
}
}
if (*filename == '/') *filename = '\0';
fileName->value(pathname);
Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this);
Fl::add_timeout(1.0, (Fl_Timeout_Handler)previewCB, this);
if (callback_) (*callback_)(this, data_);
if (!Fl::system_driver()->filename_isdir_quick(pathname) || (type_ & DIRECTORY))
okButton->activate();
else
okButton->deactivate();
}
}
void
Fl_File_Chooser::fileNameCB()
{
char *filename, *slash, pathname[FL_PATH_MAX], matchname[FL_PATH_MAX]; int i, min_match, max_match, num_files, first_line; const char *file;
filename = (char *)fileName->value();
if (!filename || !filename[0]) {
okButton->deactivate();
return;
}
if (strchr(filename, '~') || strchr(filename, '$')) {
fl_filename_expand(pathname, sizeof(pathname), filename);
filename = pathname;
value(pathname);
}
int dirIsRelative = directory_[0] != '\0' && filename[0] != '/';
if (dirIsRelative && Fl::system_driver()->colon_is_drive()) dirIsRelative = !(isalpha(filename[0] & 255) && (!filename[1] || filename[1] == ':'));
if (dirIsRelative) {
fl_filename_absolute(pathname, sizeof(pathname), filename);
value(pathname);
int flen = (int)strlen(pathname);
fileName->insert_position(flen, flen); } else if (filename != pathname) {
strlcpy(pathname, filename, sizeof(pathname));
}
filename = pathname;
if (Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter) {
int condition = 0;
if (Fl::system_driver()->colon_is_drive()) condition = isalpha(pathname[0] & 255) && pathname[1] == ':' && !pathname[2];
if (!condition) condition = ( Fl::system_driver()->filename_isdir_quick(pathname) && compare_dirnames(pathname, directory_) );
if (condition) {
directory(pathname);
} else if ((type_ & CREATE) || fl_access(pathname, 0) == 0) {
if (!Fl::system_driver()->filename_isdir_quick(pathname) || (type_ & DIRECTORY)) {
update_preview();
if (callback_) (*callback_)(this, data_);
window->hide();
}
} else {
fl_alert("%s",existing_file_label);
}
}
else if (Fl::event_key() != FL_Delete &&
Fl::event_key() != FL_BackSpace) {
if ((slash = strrchr(pathname, '/')) == NULL)
slash = strrchr(pathname, '\\');
if (!slash) return;
*slash++ = '\0';
filename = slash;
int condition = Fl::system_driver()->case_insensitive_filenames() ?
strcasecmp(pathname, directory_) : strcmp(pathname, directory_);
if (condition && (pathname[0] || strcmp("/", directory_))) {
int p = fileName->insert_position();
int m = fileName->mark();
directory(pathname);
if (filename[0]) {
char tempname[FL_PATH_MAX + 4];
snprintf(tempname, sizeof(tempname), "%s/%s", directory_, filename);
fileName->value(tempname);
strlcpy(pathname, tempname, sizeof(pathname));
}
fileName->insert_position(p, m);
}
num_files = fileList->size();
min_match = (int) strlen(filename);
max_match = min_match + 1;
first_line = 0;
for (i = 1; i <= num_files && max_match > min_match; i ++) {
file = fileList->text(i);
if ( (Fl::system_driver()->case_insensitive_filenames()?
strncasecmp(filename, file, min_match) : strncmp(filename, file, min_match)) == 0) {
if (!first_line) {
strlcpy(matchname, file, sizeof(matchname));
max_match = (int) strlen(matchname);
if (matchname[max_match - 1] == '/' && matchname[1] != 0 ) { max_match --;
matchname[max_match] = '\0';
}
fileList->topline(i);
first_line = i;
} else {
while (max_match > min_match)
if ( (Fl::system_driver()->case_insensitive_filenames()?
strncasecmp(file, matchname, max_match) : strncmp(file, matchname, max_match)) == 0)
break;
else
max_match --;
matchname[max_match] = '\0';
}
}
}
if (first_line > 0 && min_match == max_match &&
max_match == (int)strlen(fileList->text(first_line))) {
fileList->deselect(0);
fileList->select(first_line);
fileList->redraw();
} else if (max_match > min_match && first_line) {
fileName->replace(
(int) (filename - pathname),
(int) (filename - pathname + min_match),
matchname);
fileName->insert_position(
(int) (filename - pathname + max_match),
(int) (filename - pathname + min_match));
} else if (max_match == 0) {
fileList->deselect(0);
fileList->redraw();
}
if (((type_ & CREATE) || !fl_access(fileName->value(), 0)) &&
(!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY))) {
okButton->activate();
} else {
okButton->deactivate();
}
} else {
fileList->deselect(0);
fileList->redraw();
if (((type_ & CREATE) || !fl_access(fileName->value(), 0)) &&
(!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY))) {
okButton->activate();
} else {
okButton->deactivate();
}
}
}
void
Fl_File_Chooser::filter(const char *p) {
char *copyp, *start, *end; int allfiles; char temp[FL_PATH_MAX];
if (!p || !*p) p = "*";
copyp = fl_strdup(p);
showChoice->clear();
for (start = copyp, allfiles = 0; start && *start; start = end) {
end = strchr(start, '\t');
if (end) *end++ = '\0';
if (strcmp(start, "*") == 0) {
showChoice->add(all_files_label);
allfiles = 1;
} else {
quote_pathname(temp, start, sizeof(temp));
showChoice->add(temp);
if (strstr(start, "(*)") != NULL) allfiles = 1;
}
}
free(copyp);
if (!allfiles) showChoice->add(all_files_label);
showChoice->add(custom_filter_label);
showChoice->value(0);
showChoiceCB();
}
void
Fl_File_Chooser::newdir()
{
const char *dir; char pathname[FL_PATH_MAX + 4];
if ((dir = fl_input("%s", NULL, new_directory_label)) == NULL)
return;
if (dir[0] != '/' && dir[0] != '\\' && (!Fl::system_driver()->colon_is_drive() || dir[1] != ':') )
snprintf(pathname, sizeof(pathname), "%s/%s", directory_, dir);
else
strlcpy(pathname, dir, sizeof(pathname));
if (fl_mkdir(pathname, 0777))
if (errno != EEXIST)
{
fl_alert("%s", strerror(errno));
return;
}
directory(pathname);
}
void Fl_File_Chooser::preview(int e)
{
previewButton->value(e);
prefs_->set("preview", e);
prefs_->flush();
Fl_Group *p = previewBox->parent();
if (e) {
int w = p->w() * 2 / 3;
fileList->resize(fileList->x(), fileList->y(), w, fileList->h());
errorBox->resize(errorBox->x(), errorBox->y(), w, errorBox->h());
previewBox->resize(fileList->x()+w, previewBox->y(), p->w()-w, previewBox->h());
previewBox->show();
update_preview();
} else {
fileList->resize(fileList->x(), fileList->y(), p->w(), fileList->h());
errorBox->resize(errorBox->x(), errorBox->y(), p->w(), errorBox->h());
previewBox->resize(p->x()+p->w(), previewBox->y(), 0, previewBox->h());
previewBox->hide();
}
p->init_sizes();
fileList->parent()->redraw();
}
void
Fl_File_Chooser::previewCB(Fl_File_Chooser *fc) { fc->update_preview();
}
void
Fl_File_Chooser::rescan()
{
char pathname[FL_PATH_MAX];
strlcpy(pathname, directory_, sizeof(pathname));
if (pathname[0] && pathname[strlen(pathname) - 1] != '/') {
strlcat(pathname, "/", sizeof(pathname));
}
fileName->value(pathname);
if (type_ & DIRECTORY)
okButton->activate();
else
okButton->deactivate();
if ( fileList->load(directory_, sort) <= 0 ) {
if ( fileList->errmsg() ) errorBox->label(fileList->errmsg()); else errorBox->label("No files found...");
show_error_box(1);
} else {
show_error_box(0);
}
if (Fl::system_driver()->dot_file_hidden() && !showHiddenButton->value()) remove_hidden_files();
update_preview();
}
void Fl_File_Chooser::rescan_keep_filename()
{
const char *fn = fileName->value();
if (!fn || !*fn || fn[strlen(fn) - 1]=='/') {
rescan();
return;
}
int i;
char pathname[FL_PATH_MAX]; strlcpy(pathname, fn, sizeof(pathname));
if (fileList->load(directory_, sort) <= 0) {
if ( fileList->errmsg() ) errorBox->label(fileList->errmsg()); else errorBox->label("No files found...");
show_error_box(1);
} else {
show_error_box(0);
}
if (Fl::system_driver()->dot_file_hidden() && !showHiddenButton->value()) remove_hidden_files();
update_preview();
char found = 0;
char *slash = strrchr(pathname, '/');
if (slash)
slash++;
else
slash = pathname;
for (i = 1; i <= fileList->size(); i ++)
if ( (Fl::system_driver()->case_insensitive_filenames() ? strcasecmp(fileList->text(i), slash) : strcmp(fileList->text(i), slash)) == 0) {
fileList->topline(i);
fileList->select(i);
found = 1;
break;
}
if (found || type_ & CREATE)
okButton->activate();
else
okButton->deactivate();
}
void
Fl_File_Chooser::showChoiceCB()
{
const char *item, *patstart; char *patend; char temp[FL_PATH_MAX];
item = showChoice->text(showChoice->value());
if (strcmp(item, custom_filter_label) == 0) {
if ((item = fl_input("%s", pattern_, custom_filter_label)) != NULL) {
strlcpy(pattern_, item, sizeof(pattern_));
quote_pathname(temp, item, sizeof(temp));
showChoice->add(temp);
showChoice->value(showChoice->size() - 2);
}
} else if ((patstart = strchr(item, '(')) == NULL) {
strlcpy(pattern_, item, sizeof(pattern_));
} else {
strlcpy(pattern_, patstart + 1, sizeof(pattern_));
if ((patend = strrchr(pattern_, ')')) != NULL) *patend = '\0';
}
fileList->filter(pattern_);
if (shown()) {
rescan_keep_filename();
}
}
void
Fl_File_Chooser::update_favorites()
{
int i; char pathname[FL_PATH_MAX], menuname[2048]; const char *home;
favoritesButton->clear();
favoritesButton->add("bla");
favoritesButton->clear();
favoritesButton->add(add_favorites_label, FL_ALT + 'a', 0);
favoritesButton->add(manage_favorites_label, FL_ALT + 'm', 0, 0, FL_MENU_DIVIDER);
favoritesButton->add(filesystems_label, FL_ALT + 'f', 0);
if ((home = Fl::system_driver()->home_directory_name()) != NULL) {
quote_pathname(menuname, home, sizeof(menuname));
favoritesButton->add(menuname, FL_ALT + 'h', 0);
}
for (i = 0; i < 100; i ++) {
snprintf(menuname, sizeof(menuname), "favorite%02d", i);
prefs_->get(menuname, pathname, "", sizeof(pathname));
if (!pathname[0]) break;
quote_pathname(menuname, pathname, sizeof(menuname));
if (i < 10) favoritesButton->add(menuname, FL_ALT + '0' + i, 0);
else favoritesButton->add(menuname);
}
if (i == 100) ((Fl_Menu_Item *)favoritesButton->menu())[0].deactivate();
}
void
Fl_File_Chooser::update_preview()
{
const char *filename; const char *newlabel = 0; Fl_Shared_Image *image = 0, *oldimage; int pbw, pbh; int w, h; int set = 0;
if (!previewButton->value()) return;
filename = value();
if (filename == NULL) {
set = 1;
} else if (fl_filename_isdir(filename)) {
newlabel = "@fileopen";
set = 1;
} else {
struct stat s;
if (fl_stat(filename, &s)==0) {
if ((s.st_mode & S_IFREG) == 0) {
newlabel = "@-3refresh"; set = 1;
} else if (s.st_size==0) {
newlabel = "<empty file>";
set = 1;
} else {
window->cursor(FL_CURSOR_WAIT);
Fl::check();
image = Fl_Shared_Image::get(filename);
if (image) {
window->cursor(FL_CURSOR_DEFAULT);
Fl::check();
set = 1;
}
}
}
}
oldimage = (Fl_Shared_Image *)previewBox->image();
if (oldimage) oldimage->release();
previewBox->image(0);
if (!set) {
FILE *fp;
int bytes;
char *ptr;
if (filename) fp = fl_fopen(filename, "rb");
else fp = NULL;
if (fp != NULL) {
bytes = (int) fread(preview_text_, 1, sizeof(preview_text_) - 1, fp);
preview_text_[bytes] = '\0';
fclose(fp);
} else {
preview_text_[0] = '\0';
}
window->cursor(FL_CURSOR_DEFAULT);
Fl::check();
for (ptr = preview_text_; *ptr; ptr++) {
uchar c = uchar(*ptr);
if ( (c&0x80)==0 ) {
if (!isprint(c&255) && !isspace(c&255)) break;
} else if ( (c&0xe0)==0xc0 ) {
if (ptr[1] && (ptr[1]&0xc0)!=0x80) break;
ptr++;
} else if ( (c&0xf0)==0xe0 ) {
if (ptr[1] && (ptr[1]&0xc0)!=0x80) break;
ptr++;
if (ptr[1] && (ptr[1]&0xc0)!=0x80) break;
ptr++;
} else if ( (c&0xf8)==0xf0 ) {
if (ptr[1] && (ptr[1]&0xc0)!=0x80) break;
ptr++;
if (ptr[1] && (ptr[1]&0xc0)!=0x80) break;
ptr++;
if (ptr[1] && (ptr[1]&0xc0)!=0x80) break;
ptr++;
}
}
if (*ptr || ptr == preview_text_) {
for (ptr = preview_text_;
*ptr && (isprint(*ptr & 255) || isspace(*ptr & 255));
ptr ++) {}
}
if (*ptr || ptr == preview_text_) {
previewBox->label(filename ? "?" : 0);
previewBox->align(FL_ALIGN_CLIP);
previewBox->labelsize(75);
previewBox->labelfont(FL_HELVETICA);
} else {
int size = previewBox->h() / 20;
if (size < 6) size = 6;
else if (size > FL_NORMAL_SIZE) size = FL_NORMAL_SIZE;
previewBox->label(preview_text_);
previewBox->align((Fl_Align)(FL_ALIGN_CLIP | FL_ALIGN_INSIDE |
FL_ALIGN_LEFT | FL_ALIGN_TOP));
previewBox->labelsize(size);
previewBox->labelfont(FL_COURIER);
}
} else if (image && ( (image->w() <= 0) ||
(image->h() <= 0) ||
(image->d() < 0) ||
(image->count() <= 0))) {
image->release();
previewBox->label("X");
previewBox->align(FL_ALIGN_CLIP);
previewBox->labelsize(70);
previewBox->labelfont(FL_HELVETICA);
previewBox->redraw();
} else if (image) {
pbw = previewBox->w() - 20;
pbh = previewBox->h() - 20;
if (image->w() > pbw || image->h() > pbh) {
w = pbw;
h = w * image->h() / image->w();
if (h > pbh) {
h = pbh;
w = h * image->w() / image->h();
}
oldimage = (Fl_Shared_Image *)image->copy(w, h);
previewBox->image((Fl_Image *)oldimage);
image->release();
} else {
previewBox->image((Fl_Image *)image);
}
previewBox->align(FL_ALIGN_CLIP);
previewBox->label(0);
} else if (newlabel) {
previewBox->label(newlabel);
previewBox->align(FL_ALIGN_CLIP);
previewBox->labelsize(newlabel[0]=='@'?75:12);
previewBox->labelfont(FL_HELVETICA);
}
previewBox->redraw();
}
const char * Fl_File_Chooser::value(int f) {
int i; int fcount; const char *name; static char pathname[FL_PATH_MAX + 4];
name = fileName->value();
if (!(type_ & MULTI)) {
if (!name || !name[0]) return NULL;
else return name;
}
for (i = 1, fcount = 0; i <= fileList->size(); i ++)
if (fileList->selected(i)) {
name = fileList->text(i);
fcount ++;
if (fcount == f) {
if (directory_[0]) {
snprintf(pathname, sizeof(pathname), "%s/%s", directory_, name);
} else {
strlcpy(pathname, name, sizeof(pathname));
}
return pathname;
}
}
if (!name || !name[0]) return NULL;
else return name;
}
void
Fl_File_Chooser::value(const char *filename)
{
int i, fcount; char *slash; char pathname[FL_PATH_MAX];
if (filename == NULL || !filename[0]) {
directory(filename);
fileName->value("");
okButton->deactivate();
return;
}
char fixpath[FL_PATH_MAX]; if (Fl::system_driver()->backslash_as_slash()) {
if (strchr(filename, '\\')) {
strlcpy(fixpath, filename, sizeof(fixpath));
for (slash = strchr(fixpath, '\\'); slash; slash = strchr(slash + 1, '\\'))
*slash = '/';
filename = fixpath;
}
}
fl_filename_absolute(pathname, sizeof(pathname), filename);
if ((slash = strrchr(pathname, '/')) != NULL) {
if (!fl_filename_isdir(pathname)) *slash++ = '\0';
directory(pathname);
if (*slash == '/') slash = pathname;
} else {
directory(".");
slash = pathname;
}
if (slash > pathname) slash[-1] = '/';
fileName->value(pathname);
fileName->insert_position(0, (int) strlen(pathname));
okButton->activate();
fcount = fileList->size();
fileList->deselect(0);
fileList->redraw();
for (i = 1; i <= fcount; i ++)
if ( ( Fl::system_driver()->case_insensitive_filenames() ? strcasecmp(fileList->text(i), slash) : strcmp(fileList->text(i), slash)) == 0) {
fileList->topline(i);
fileList->select(i);
break;
}
}
void Fl_File_Chooser::show()
{
window->hotspot(fileList);
window->show();
Fl::flush();
fl_cursor(FL_CURSOR_WAIT);
rescan_keep_filename();
fl_cursor(FL_CURSOR_DEFAULT);
fileName->take_focus();
if (!Fl::system_driver()->dot_file_hidden()) showHiddenButton->hide();
}
void Fl_File_Chooser::hide() {
Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this);
Fl_Shared_Image *oldimage = (Fl_Shared_Image*)previewBox->image();
if (oldimage) oldimage->release();
previewBox->image(NULL);
window->hide();
}
void Fl_File_Chooser::showHidden(int value)
{
if (value) {
fileList->load(directory());
} else {
remove_hidden_files();
fileList->redraw();
}
}
void Fl_File_Chooser::remove_hidden_files()
{
int count = fileList->size();
for(int num = count; num >= 1; num--) {
const char *p = fileList->text(num);
if (*p == '.' && strcmp(p, "../") != 0) fileList->remove(num);
}
fileList->topline(1);
}
static int
compare_dirnames(const char *a, const char *b) {
int alen, blen;
alen = (int) (strlen(a) - 1);
blen = (int) (strlen(b) - 1);
if (alen < 0 || blen < 0) return alen - blen;
if (a[alen] != '/') alen ++;
if (b[blen] != '/') blen ++;
if (alen != blen) return alen - blen;
return Fl::system_driver()->case_insensitive_filenames() ? strncasecmp(a, b, alen) : strncmp(a, b, alen);
}
static void
quote_pathname(char *dst, const char *src, int dstsize) {
dstsize--;
while (*src && dstsize > 1) {
if (*src == '\\') {
*dst++ = '\\';
*dst++ = '/';
dstsize -= 2;
src ++;
} else {
if (*src == '/') {
*dst++ = '\\';
dstsize--;
}
*dst++ = *src++;
dstsize--;
}
}
*dst = '\0';
}
static void
unquote_pathname(char *dst, const char *src, int dstsize) {
dstsize--;
while (*src && dstsize > 0) {
if (*src == '\\') src++;
*dst++ = *src++;
dstsize--;
}
*dst = '\0';
}