2 * "$Id: scandir_win32.c 8347 2011-02-01 01:06:27Z greg.ercolano $"
4 * WIN32 scandir function 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
29 /* Emulation of posix scandir() call */
30 #include <FL/fl_utf8.h>
31 #include <FL/filename.H>
36 int fl_scandir(const char *dirname
, struct dirent
***namelist
,
37 int (*select
)(struct dirent
*),
38 int (*compar
)(struct dirent
**, struct dirent
**)) {
40 char *findIn
, *d
, is_dir
= 0;
41 WIN32_FIND_DATAW findw
;
43 int nDir
= 0, NDir
= 0;
44 struct dirent
**dir
= 0, *selectDir
;
47 len
= strlen(dirname
);
48 findIn
= (char *)malloc((size_t)(len
+10));
49 if (!findIn
) return -1;
50 strcpy(findIn
, dirname
);
52 /* #if defined(__GNUC__) */
53 /* #warning FIXME This probably needs to be MORE UTF8 aware now */
55 for (d
= findIn
; *d
; d
++) if (*d
=='/') *d
='\\';
56 if ((len
==0)) { strcpy(findIn
, ".\\*"); }
57 if ((len
==2)&&findIn
[1]==':'&&isalpha(findIn
[0])) { *d
++ = '\\'; *d
= 0; }
58 if ((len
==1)&& (d
[-1]=='.')) { strcpy(findIn
, ".\\*"); is_dir
= 1; }
59 if ((len
>0) && (d
[-1]=='\\')) { *d
++ = '*'; *d
= 0; is_dir
= 1; }
60 if ((len
>1) && (d
[-1]=='.') && (d
[-2]=='\\')) { d
[-1] = '*'; is_dir
= 1; }
61 if (!is_dir
) { /* this file may still be a directory that we need to list */
62 DWORD attr
= GetFileAttributes(findIn
);
63 if (attr
&FILE_ATTRIBUTE_DIRECTORY
)
66 { /* Create a block to limit the scope while we find the initial "wide" filename */
67 /* unsigned short * wbuf = (unsigned short*)malloc(sizeof(short) *(len + 10)); */
68 /* wbuf[fl_utf2unicode(findIn, strlen(findIn), wbuf)] = 0; */
69 unsigned short *wbuf
= NULL
;
70 unsigned wlen
= fl_utf8toUtf16(findIn
, strlen(findIn
), NULL
, 0); /* Pass NULL to query length */
71 wlen
++; /* add a little extra for termination etc. */
72 wbuf
= (unsigned short*)malloc(sizeof(unsigned short)*wlen
);
73 wlen
= fl_utf8toUtf16(findIn
, strlen(findIn
), wbuf
, wlen
); /* actually convert the filename */
74 wbuf
[wlen
] = 0; /* NULL terminate the resultant string */
75 h
= FindFirstFileW(wbuf
, &findw
); /* get a handle to the first filename in the search */
76 free(wbuf
); /* release the "wide" buffer before the pointer goes out of scope */
78 if (h
==INVALID_HANDLE_VALUE
) {
81 if (ret
!= ERROR_NO_MORE_FILES
) {
88 int l
= wcslen(findw
.cFileName
);
89 int dstlen
= l
* 5 + 1;
90 selectDir
=(struct dirent
*)malloc(sizeof(struct dirent
)+dstlen
);
92 /* l = fl_unicode2utf(findw.cFileName, l, selectDir->d_name); */
93 l
= fl_utf8fromwc(selectDir
->d_name
, dstlen
, findw
.cFileName
, l
);
95 selectDir
->d_name
[l
] = 0;
96 if (findw
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
97 /* Append a trailing slash to directory names... */
98 strcat(selectDir
->d_name
, "/");
100 if (!select
|| (*select
)(selectDir
)) {
102 struct dirent
**tempDir
= (struct dirent
**)calloc(sizeof(struct dirent
*), (size_t)(NDir
+33));
103 if (NDir
) memcpy(tempDir
, dir
, sizeof(struct dirent
*)*NDir
);
108 dir
[nDir
] = selectDir
;
114 } while (FindNextFileW(h
, &findw
));
115 ret
= GetLastError();
116 if (ret
!= ERROR_NO_MORE_FILES
) {
117 /* don't return an error code, because the dir list may still be valid
124 if (compar
) qsort(dir
, (size_t)nDir
, sizeof(*dir
),
125 (int(*)(const void*, const void*))compar
);
134 * End of "$Id: scandir_win32.c 8347 2011-02-01 01:06:27Z greg.ercolano $".