Skip to content

Commit

Permalink
Fix STR #2507. Applied supplied patch modified for Mac OS X. Checked …
Browse files Browse the repository at this point in the history
…OK on Linux.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@8192 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
  • Loading branch information
Manolo Gouy authored and Manolo Gouy committed Jan 5, 2011
1 parent 3d470e8 commit 18ae07b
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 36 deletions.
99 changes: 73 additions & 26 deletions src/filename_list.cxx
Expand Up @@ -28,6 +28,7 @@
// Wrapper for scandir with const-correct function prototypes.

#include <FL/filename.H>
#include <FL/fl_utf8.h>
#include "flstring.h"
#include <stdlib.h>

Expand All @@ -37,7 +38,6 @@ extern "C" {
int fl_scandir (const char *dir, dirent ***namelist,
int (*select)(dirent *),
int (*compar)(dirent **, dirent **));
# define scandir fl_scandir
#endif
}

Expand Down Expand Up @@ -81,54 +81,101 @@ int fl_casealphasort(struct dirent **a, struct dirent **b) {
*/
int fl_filename_list(const char *d, dirent ***list,
Fl_File_Sort_F *sort) {
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(HAVE_SCANDIR)
// For Windows we have a special scandir implementation that uses
// the Win32 "wide" functions for lookup, avoiding the code page mess
// entirely. It also fixes up the trailing '/'.
return fl_scandir(d, list, 0, sort);

#else // WIN32

int dirlen;
char *dirloc;

// Assume that locale encoding is no less dense than UTF-8
dirlen = strlen(d);
#ifdef __APPLE__
dirloc = (char *)d;
#else
dirloc = (char *)malloc(dirlen + 1);
fl_utf8to_mb(d, dirlen, dirloc, dirlen + 1);
#endif

#ifndef HAVE_SCANDIR
int n = scandir(d, list, 0, sort);
// This version is when we define our own scandir
int n = fl_scandir(dirloc, list, 0, sort);
#elif defined(HAVE_SCANDIR_POSIX) && !defined(__APPLE__)
// POSIX (2008) defines the comparison function like this:
int n = scandir(d, list, 0, (int(*)(const dirent **, const dirent **))sort);
int n = scandir(dirloc, list, 0, (int(*)(const dirent **, const dirent **))sort);
#elif defined(__osf__)
// OSF, DU 4.0x
int n = scandir(d, list, 0, (int(*)(dirent **, dirent **))sort);
int n = scandir(dirloc, list, 0, (int(*)(dirent **, dirent **))sort);
#elif defined(_AIX)
// AIX is almost standard...
int n = scandir(d, list, 0, (int(*)(void*, void*))sort);
#elif !defined(__sgi)
int n = scandir(dirloc, list, 0, (int(*)(void*, void*))sort);
#elif defined(__sgi)
int n = scandir(dirloc, list, 0, sort);
#else
// The vast majority of UNIX systems want the sort function to have this
// prototype, most likely so that it can be passed to qsort without any
// changes:
int n = scandir(d, list, 0, (int(*)(const void*,const void*))sort);
#else
// This version is when we define our own scandir (WIN32 and perhaps
// some Unix systems) and apparently on IRIX:
int n = scandir(d, list, 0, sort);
int n = scandir(dirloc, list, 0, (int(*)(const void*,const void*))sort);
#endif

#if defined(WIN32) && !defined(__CYGWIN__)
// we did this already during fl_scandir/win32
#else
// append a '/' to all filenames that are directories
int i, dirlen = strlen(d);
#ifndef __APPLE__
free(dirloc);
#endif

// convert every filename to utf-8, and append a '/' to all
// filenames that are directories
int i;
char *fullname = (char*)malloc(dirlen+FL_PATH_MAX+3); // Add enough extra for two /'s and a nul
// Use memcpy for speed since we already know the length of the string...
memcpy(fullname, d, dirlen+1);

char *name = fullname + dirlen;
if (name!=fullname && name[-1]!='/') *name++ = '/';
if (name!=fullname && name[-1]!='/')
*name++ = '/';

for (i=0; i<n; i++) {
int newlen;
dirent *de = (*list)[i];
int len = strlen(de->d_name);
if (de->d_name[len-1]=='/' || len>FL_PATH_MAX) continue;
// Use memcpy for speed since we already know the length of the string...
memcpy(name, de->d_name, len+1);
if (fl_filename_isdir(fullname)) {
(*list)[i] = de = (dirent*)realloc(de, de->d_name - (char*)de + len + 2);
char *dst = de->d_name + len;
*dst++ = '/';
*dst = 0;
#ifdef __APPLE__
newlen = len;
#else
newlen = fl_utf8from_mb(NULL, 0, de->d_name, len);
#endif
dirent *newde = (dirent*)malloc(de->d_name - (char*)de + newlen + 2); // Add space for a / and a nul

// Conversion to UTF-8
memcpy(newde, de, de->d_name - (char*)de);
#ifdef __APPLE__
strcpy(newde->d_name, de->d_name);
#else
fl_utf8from_mb(newde->d_name, newlen + 1, de->d_name, len);
#endif

// Check if dir (checks done on "old" name as we need to interact with
// the underlying OS)
if (de->d_name[len-1]!='/' && len<=FL_PATH_MAX) {
// Use memcpy for speed since we already know the length of the string...
memcpy(name, de->d_name, len+1);
if (fl_filename_isdir(fullname)) {
char *dst = newde->d_name + newlen;
*dst++ = '/';
*dst = 0;
}
}

free(de);
(*list)[i] = newde;
}
free(fullname);
#endif

return n;

#endif // WIN32
}

/**
Expand Down
11 changes: 3 additions & 8 deletions src/fl_utf.c
Expand Up @@ -692,8 +692,6 @@ int fl_utf8locale(void) {
needed.
If fl_utf8locale() returns true then this does not change the data.
It is copied and truncated as necessary to
the destination buffer and \p srclen is always returned.
*/
unsigned fl_utf8to_mb(const char* src, unsigned srclen,
char* dst, unsigned dstlen)
Expand Down Expand Up @@ -747,8 +745,7 @@ unsigned fl_utf8to_mb(const char* src, unsigned srclen,
memcpy(dst, src, srclen);
dst[srclen] = 0;
} else {
memcpy(dst, src, dstlen-1);
dst[dstlen-1] = 0;
// Buffer insufficent or buffer query
}
return srclen;
}
Expand All @@ -765,8 +762,7 @@ unsigned fl_utf8to_mb(const char* src, unsigned srclen,
needed.
On Unix or on Windows when a UTF-8 locale is in effect, this
does not change the data. It is copied and truncated as necessary to
the destination buffer and \p srclen is always returned.
does not change the data.
You may also want to check if fl_utf8test() returns non-zero, so that
the filesystem can store filenames in UTF-8 encoding regardless of
the locale.
Expand Down Expand Up @@ -813,8 +809,7 @@ unsigned fl_utf8from_mb(char* dst, unsigned dstlen,
memcpy(dst, src, srclen);
dst[srclen] = 0;
} else {
memcpy(dst, src, dstlen-1);
dst[dstlen-1] = 0;
// Buffer insufficent or buffer query
}
return srclen;
}
Expand Down
3 changes: 1 addition & 2 deletions src/scandir.c
Expand Up @@ -21,7 +21,6 @@ USA. */
#else

# include "flstring.h"
# include <FL/fl_utf8.h>

# if !HAVE_SCANDIR
# include <stdlib.h>
Expand Down Expand Up @@ -50,7 +49,7 @@ fl_scandir(const char *dir, struct dirent ***namelist,
int (*select)(struct dirent *),
int (*compar)(struct dirent **, struct dirent **))
{
DIR *dp = opendir (fl_utf2mbcs(dir));
DIR *dp = opendir (dir);
struct dirent **v = NULL;
size_t vsize = 0, i;
struct dirent *d;
Expand Down

0 comments on commit 18ae07b

Please sign in to comment.