2 // "$Id: filename_list.cxx 8192 2011-01-05 16:50:10Z manolo $"
4 // Filename list routines for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2010 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
28 // Wrapper for scandir with const-correct function prototypes.
30 #include <FL/filename.H>
31 #include <FL/fl_utf8.h>
38 int fl_scandir (const char *dir
, dirent
***namelist
,
39 int (*select
)(dirent
*),
40 int (*compar
)(dirent
**, dirent
**));
44 int fl_alphasort(struct dirent
**a
, struct dirent
**b
) {
45 return strcmp((*a
)->d_name
, (*b
)->d_name
);
48 int fl_casealphasort(struct dirent
**a
, struct dirent
**b
) {
49 return strcasecmp((*a
)->d_name
, (*b
)->d_name
);
54 Portable and const-correct wrapper for the scandir() function.
55 For each file in that directory a "dirent" structure is created.
56 The only portable thing about a dirent is that dirent.d_name is the nul-terminated file name.
57 An pointers array to these dirent's is created and a pointer to the array is returned in *list.
58 The number of entries is given as a return value.
59 If there is an error reading the directory a number less than zero is returned,
60 and errno has the reason; errno does not work under WIN32.
64 #include <FL/filename.H>
67 \param[in] d the name of the directory to list. It does not matter if it has a trailing slash.
68 \param[out] list table containing the resulting directory listing
69 \param[in] sort sorting functor:
70 - fl_alphasort: The files are sorted in ascending alphabetical order;
71 upper and lowercase letters are compared according to their ASCII ordering uppercase before lowercase.
72 - fl_casealphasort: The files are sorted in ascending alphabetical order;
73 upper and lowercase letters are compared equally case is not significant.
74 - fl_casenumericsort: The files are sorted in ascending "alphanumeric" order, where an attempt is made
75 to put unpadded numbers in consecutive order; upper and lowercase letters
76 are compared equally case is not significant.
77 - fl_numericsort: The files are sorted in ascending "alphanumeric" order, where an attempt is made
78 to put unpadded numbers in consecutive order; upper and lowercase letters are compared
79 according to their ASCII ordering - uppercase before lowercase.
80 \return the number of entries if no error, a negative value otherwise.
82 int fl_filename_list(const char *d
, dirent
***list
,
83 Fl_File_Sort_F
*sort
) {
84 #if defined(WIN32) && !defined(__CYGWIN__) && !defined(HAVE_SCANDIR)
85 // For Windows we have a special scandir implementation that uses
86 // the Win32 "wide" functions for lookup, avoiding the code page mess
87 // entirely. It also fixes up the trailing '/'.
88 return fl_scandir(d
, list
, 0, sort
);
95 // Assume that locale encoding is no less dense than UTF-8
100 dirloc
= (char *)malloc(dirlen
+ 1);
101 fl_utf8to_mb(d
, dirlen
, dirloc
, dirlen
+ 1);
105 // This version is when we define our own scandir
106 int n
= fl_scandir(dirloc
, list
, 0, sort
);
107 #elif defined(HAVE_SCANDIR_POSIX) && !defined(__APPLE__)
108 // POSIX (2008) defines the comparison function like this:
109 int n
= scandir(dirloc
, list
, 0, (int(*)(const dirent
**, const dirent
**))sort
);
110 #elif defined(__osf__)
112 int n
= scandir(dirloc
, list
, 0, (int(*)(dirent
**, dirent
**))sort
);
114 // AIX is almost standard...
115 int n
= scandir(dirloc
, list
, 0, (int(*)(void*, void*))sort
);
117 int n
= scandir(dirloc
, list
, 0, sort
);
119 // The vast majority of UNIX systems want the sort function to have this
120 // prototype, most likely so that it can be passed to qsort without any
122 int n
= scandir(dirloc
, list
, 0, (int(*)(const void*,const void*))sort
);
129 // convert every filename to utf-8, and append a '/' to all
130 // filenames that are directories
132 char *fullname
= (char*)malloc(dirlen
+FL_PATH_MAX
+3); // Add enough extra for two /'s and a nul
133 // Use memcpy for speed since we already know the length of the string...
134 memcpy(fullname
, d
, dirlen
+1);
136 char *name
= fullname
+ dirlen
;
137 if (name
!=fullname
&& name
[-1]!='/')
140 for (i
=0; i
<n
; i
++) {
142 dirent
*de
= (*list
)[i
];
143 int len
= strlen(de
->d_name
);
147 newlen
= fl_utf8from_mb(NULL
, 0, de
->d_name
, len
);
149 dirent
*newde
= (dirent
*)malloc(de
->d_name
- (char*)de
+ newlen
+ 2); // Add space for a / and a nul
151 // Conversion to UTF-8
152 memcpy(newde
, de
, de
->d_name
- (char*)de
);
154 strcpy(newde
->d_name
, de
->d_name
);
156 fl_utf8from_mb(newde
->d_name
, newlen
+ 1, de
->d_name
, len
);
159 // Check if dir (checks done on "old" name as we need to interact with
160 // the underlying OS)
161 if (de
->d_name
[len
-1]!='/' && len
<=FL_PATH_MAX
) {
162 // Use memcpy for speed since we already know the length of the string...
163 memcpy(name
, de
->d_name
, len
+1);
164 if (fl_filename_isdir(fullname
)) {
165 char *dst
= newde
->d_name
+ newlen
;
182 \brief Free the list of filenames that is generated by fl_filename_list().
184 Free everything that was allocated by a previous call to fl_filename_list().
185 Use the return values as parameters for this function.
187 \param[in,out] list table containing the resulting directory listing
188 \param[in] n number of entries in the list
190 void fl_filename_free_list(struct dirent
***list
, int n
)
195 for (i
= 0; i
< n
; i
++) {
205 // End of "$Id: filename_list.cxx 8192 2011-01-05 16:50:10Z manolo $".