Tweak themes for more color consistency.
[ntk.git] / src / filename_list.cxx
blob6434d6792496fec48b38f03c44ac6d169b674654
1 //
2 // "$Id: filename_list.cxx 8192 2011-01-05 16:50:10Z manolo $"
3 //
4 // Filename list routines for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2010 by Bill Spitzak and others.
7 //
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
21 // USA.
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>
32 #include "flstring.h"
33 #include <stdlib.h>
36 extern "C" {
37 #ifndef HAVE_SCANDIR
38 int fl_scandir (const char *dir, dirent ***namelist,
39 int (*select)(dirent *),
40 int (*compar)(dirent **, dirent **));
41 #endif
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);
53 /**
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.
62 \b Include:
63 \code
64 #include <FL/filename.H>
65 \endcode
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);
90 #else // WIN32
92 int dirlen;
93 char *dirloc;
95 // Assume that locale encoding is no less dense than UTF-8
96 dirlen = strlen(d);
97 #ifdef __APPLE__
98 dirloc = (char *)d;
99 #else
100 dirloc = (char *)malloc(dirlen + 1);
101 fl_utf8to_mb(d, dirlen, dirloc, dirlen + 1);
102 #endif
104 #ifndef HAVE_SCANDIR
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__)
111 // OSF, DU 4.0x
112 int n = scandir(dirloc, list, 0, (int(*)(dirent **, dirent **))sort);
113 #elif defined(_AIX)
114 // AIX is almost standard...
115 int n = scandir(dirloc, list, 0, (int(*)(void*, void*))sort);
116 #elif defined(__sgi)
117 int n = scandir(dirloc, list, 0, sort);
118 #else
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
121 // changes:
122 int n = scandir(dirloc, list, 0, (int(*)(const void*,const void*))sort);
123 #endif
125 #ifndef __APPLE__
126 free(dirloc);
127 #endif
129 // convert every filename to utf-8, and append a '/' to all
130 // filenames that are directories
131 int i;
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]!='/')
138 *name++ = '/';
140 for (i=0; i<n; i++) {
141 int newlen;
142 dirent *de = (*list)[i];
143 int len = strlen(de->d_name);
144 #ifdef __APPLE__
145 newlen = len;
146 #else
147 newlen = fl_utf8from_mb(NULL, 0, de->d_name, len);
148 #endif
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);
153 #ifdef __APPLE__
154 strcpy(newde->d_name, de->d_name);
155 #else
156 fl_utf8from_mb(newde->d_name, newlen + 1, de->d_name, len);
157 #endif
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;
166 *dst++ = '/';
167 *dst = 0;
171 free(de);
172 (*list)[i] = newde;
174 free(fullname);
176 return n;
178 #endif // WIN32
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)
192 if (n<0) return;
194 int i;
195 for (i = 0; i < n; i ++) {
196 if ((*list)[i])
197 free((*list)[i]);
199 free(*list);
200 *list = 0;
205 // End of "$Id: filename_list.cxx 8192 2011-01-05 16:50:10Z manolo $".