DO NOT REPLY TO THIS MESSAGE.  INSTEAD, POST ANY RESPONSES TO THE LINK BELOW.

[STR New]

Link: http://www.fltk.org/str.php?L2507
Version: 1.3-current


File name encodings are a bit of a pain as there is no clear right way.
What other toolkits do is to assume the file names are encoded according
to locale. FLTK assumes that they are always in UTF-8 though.

On Windows, this handling is already in place (although some of the heavy
lifting is done by Windows itself). The interface there is that FLTK
always expects UTF-8 encoded file names, and does all the necessary voodoo
to interface with Windows.

The attached patch fixes this issue for the other platforms as well. This
makes the FLTK interface consistent in that FLTK always expects UTF-8 file
names, not just on one of the platforms. It also means that the file
chooser shows files the same way that e.g. GTK+ does.


The patch basically fixes three things:

1. fl_utf8to_mb()/fl_utf8from_mb() has a stupid behaviour where it behaves
different on utf-8 systems and can segfault if the caller doesn't check
this first.

2. The non-win32 fl_scandir() had a useless call to fl_utf2mbcs() (which
does nothing on the platforms used here).

3. Shuffles around fl_filename_list() a bit and gives it a consistent
UTF-8 interface.


Link: http://www.fltk.org/str.php?L2507
Version: 1.3-current
diff -up ./src/filename_list.cxx.scandir ./src/filename_list.cxx
--- ./src/filename_list.cxx.scandir     2010-11-28 22:06:39.000000000 +0100
+++ ./src/filename_list.cxx     2011-01-04 13:35:59.006471987 +0100
@@ -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,82 @@ int fl_casealphasort(struct dirent **a, 
 */
 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
+
+  // Assume that locale encoding is no less dense than UTF-8
+  int dirlen = strlen(d); 
+  char dirloc[dirlen + 1];
+
+  fl_utf8to_mb(d, dirlen, dirloc, sizeof(dirloc));
+
 #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);
+  // 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++) {
     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;
+    int newlen = fl_utf8from_mb(NULL, 0, de->d_name, len);
+    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);
+    fl_utf8from_mb(newde->d_name, newlen + 1, de->d_name, len);
+
+    // 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 -up ./src/fl_utf.c.scandir ./src/fl_utf.c
--- ./src/fl_utf.c.scandir      2010-11-28 22:06:39.000000000 +0100
+++ ./src/fl_utf.c      2011-01-04 13:22:46.244287623 +0100
@@ -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, u
     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, u
     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, unsig
     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 -up ./src/scandir.c.scandir ./src/scandir.c
--- ./src/scandir.c.scandir     2008-09-19 19:40:20.000000000 +0200
+++ ./src/scandir.c     2011-01-03 18:06:19.103432937 +0100
@@ -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 diren
           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;
_______________________________________________
fltk-bugs mailing list
fltk-bugs@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk-bugs

Reply via email to