diff options
| author | Manolo Gouy <Manolo> | 2011-01-05 16:50:10 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2011-01-05 16:50:10 +0000 |
| commit | 18ae07b181bf67191dc77563e01d64c63ee9ec2d (patch) | |
| tree | 3b795442b66711b35bdb8ed1f933fc94c12f2b4c /src | |
| parent | 3d470e8c0df71d5e671573250f7ab4cbb64e77d9 (diff) | |
Fix STR #2507. Applied supplied patch modified for Mac OS X. Checked OK on Linux.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@8192 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
| -rw-r--r-- | src/filename_list.cxx | 99 | ||||
| -rw-r--r-- | src/fl_utf.c | 11 | ||||
| -rw-r--r-- | src/scandir.c | 3 |
3 files changed, 77 insertions, 36 deletions
diff --git a/src/filename_list.cxx b/src/filename_list.cxx index 3de968ea2..497579da3 100644 --- a/src/filename_list.cxx +++ b/src/filename_list.cxx @@ -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> @@ -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 } @@ -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 } /** diff --git a/src/fl_utf.c b/src/fl_utf.c index d487ff668..9d6d48b81 100644 --- a/src/fl_utf.c +++ b/src/fl_utf.c @@ -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) @@ -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; } @@ -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. @@ -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; } diff --git a/src/scandir.c b/src/scandir.c index 622e4ddb8..197f63fd6 100644 --- a/src/scandir.c +++ b/src/scandir.c @@ -21,7 +21,6 @@ USA. */ #else # include "flstring.h" -# include <FL/fl_utf8.h> # if !HAVE_SCANDIR # include <stdlib.h> @@ -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; |
