typedef struct
{
int folder;
char *name;
} DIRENTRY;
DIRENTRY *readdirectoryfilt(char *dir, int *N, int hidden, char *filt)
{
DIRENTRY *answer;
DIRENTRY *fulldir;
int j = 0;
int i;
fulldir = readdirectory(dir, N, hidden);
if (!fulldir)
{
*N = 0;
return 0;
}
answer = bbx_malloc(*N * sizeof(DIRENTRY));
for(i=0;i<*N;i++)
{
if(fulldir[i].folder == 1 || wildcard_match_icase(fulldir[i].name, filt))
{
answer[j].folder = fulldir[i].folder;
answer[j].name = bbx_strdup(fulldir[i].name);
j++;
}
}
killentries(fulldir, *N);
*N = j;
answer = bbx_realloc(answer, j * sizeof(DIRENTRY));
return answer;
}
#include <assert.h>
DIRENTRY *readdirectory(char *dir, int *N, int hidden)
{
WIN32_FIND_DATA ffd;
LARGE_INTEGER filesize;
TCHAR szDir[MAX_PATH];
size_t length_of_arg;
HANDLE hFind = INVALID_HANDLE_VALUE;
DWORD dwError = 0;
int Nch;
int Nread = 0;
int i, j;
char *ptr;
int len;
int count;
DIRENTRY *answer = 0;
if (!strcmp(dir, "\\"))
{
GetLogicalDriveStrings(MAX_PATH, szDir);
i = 0;
while (szDir[i])
{
Nread++;
while (szDir[i])
i++;
i++;
}
answer = bbx_malloc(Nread * sizeof(DIRENTRY));
i = 0;
count = 0;
while (szDir[i])
{
Nch = 0;
j = i;
while (szDir[j])
{
Nch += bbx_utf8_charwidth(szDir[j]);
j++;
}
answer[count].name = bbx_malloc(Nch + 1);
Nch = 0;
j = i;
while (szDir[j])
{
Nch += bbx_utf8_putch(answer[count].name + Nch, szDir[j]);
j++;
}
answer[count].name[Nch] = 0;
answer[count].folder = 1;
answer[count].name[strlen(answer[count].name) - 1] = 0;
i = j+1;
count++;
}
*N = Nread;
return answer;
}
Nch = bbx_utf8_Nchars(dir);
ptr = dir;
for (i = 0; i < Nch; i++)
{
szDir[i] = bbx_utf8_getch(ptr);
ptr += bbx_utf8_skip(ptr);
}
szDir[i] = '\\';
szDir[i + 1] = '*';
szDir[i + 2] = 0;
// Find the first file in the directory.
hFind = FindFirstFile(szDir, &ffd);
if (INVALID_HANDLE_VALUE == hFind)
{
answer = bbx_malloc(sizeof(DIRENTRY));
answer[0].name = bbx_strdup("..");
answer[0].folder = 1;
*N = 1;
return answer;
}
// List all the files in the directory with some info about them.
do
{
if ( (ffd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) && !hidden)
continue;
answer = bbx_realloc(answer, (Nread + 1) * sizeof(DIRENTRY));
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
answer[Nread].folder = 1;
else
answer[Nread].folder = 0;
len = 0;
for (i = 0; ffd.cFileName[i]; i++)
{
len += bbx_utf8_charwidth(ffd.cFileName[i]);
}
answer[Nread].name = bbx_malloc(len + 1);
ptr = answer[Nread].name;
for (i = 0; ffd.cFileName[i]; i++)
ptr += bbx_utf8_putch(ptr, ffd.cFileName[i]);
*ptr = 0;
Nread++;
} while (FindNextFile(hFind, &ffd) != 0);
dwError = GetLastError();
if (dwError != ERROR_NO_MORE_FILES)
{
return 0;
}
FindClose(hFind);
for (i = 0; i < Nread;i++)
if (!strcmp(answer[i].name, ".."))
break;
if (i == Nread)
{
answer = bbx_realloc(answer, (Nread + 1)*sizeof(DIRENTRY));
answer[Nread].name = bbx_strdup("..");
answer[Nread].folder = 1;
Nread++;
}
*N = Nread;
return answer;
}
/*
DIRENTRY *readdirectory(char *dir, int *N, int hidden)
{
struct dirent *de=NULL;
struct stat statbuf;
DIR *d = NULL;
DIRENTRY *answer = bbx_malloc(100 * sizeof(DIRENTRY));
DIRENTRY *temp;
int capacity = 100;
int Nread = 0;
char path[FILENAME_MAX];
d=opendir(dir);
if(d == NULL)
{
*N = 0;
return 0;
}
// Loop while not NULL
while( (de = readdir(d)) )
{
makepath(path, FILENAME_MAX, dir, de->d_name);
if (stat(path, &statbuf) == -1)
continue;
if(hidden == 0 && is_hidden(de->d_name))
continue;
if(S_ISDIR(statbuf.st_mode))
answer[Nread].folder = 1;
else
answer[Nread].folder = 0;
answer[Nread].name = bbx_strdup(de->d_name);
Nread++;
if(Nread == capacity)
{
temp = bbx_realloc(answer, (capacity * 2) * sizeof(DIRENTRY));
if(!temp)
{
*N = Nread;
return answer;
}
answer = temp;
capacity *= 2;
}
}
closedir(d);
qsort(answer, Nread, sizeof(DIRENTRY), compentries);
*N = Nread;
return answer;
}
*/
static int compentries(const void *e1, const void *e2)
{
const DIRENTRY *d1 = e1;
const DIRENTRY *d2 = e2;
if(d1->folder != d2->folder)
return d2->folder - d1->folder;
else
return strcmp(d1->name, d2->name);
}
void killentries(DIRENTRY *entries, int N)
{
int i;
if(entries)
{
for(i=0;i<N;i++)
free(entries[i].name);
free(entries);
}
}
/*
static int validdirectory(char *dir)
{
struct stat statbuf;
if (stat(dir, &statbuf) == -1)
return 0;
if(!S_ISDIR(statbuf.st_mode))
return 0;
return 1;
}
*/
static int is_hidden(char *fname)
{
int len;
if(fname && fname[0] == '.')
{
if(!strcmp(fname, ".") || !strcmp(fname, ".."))
return 0;
return 1;
}
if(fname)
{
len = strlen(fname);
if(len > 0 && fname[len-1] == '~')
return 1;
}
return 0;
}
static void makepath(char *out, int N, char *dir, char *sub)
{
strcpy(out, dir);
strcat(out, "/");
strcat(out, sub);
}
static void goupafolder(char *dir)
{
char *sep;
sep = strrchr(dir, '\\');
if(sep && sep != dir)
*sep = 0;
if(sep == dir)
sep[1] = 0;
if (!sep)
strcpy(dir, "\\");
}
static void godownafolder(char *dir, char *sub)
{
if (!strcmp(dir, "\\"))
strcpy(dir, sub);
else
{
strcat(dir, "\\");
strcat(dir, sub);
}
}
static int fileexists(char *path)
{
struct stat statbuf;
return stat(path, &statbuf) == -1 ? 0 : 1;
}
static void trim(char *str)
{
size_t len;
size_t i;
len = strlen(str);
while(len && isspace( (unsigned char) str[len-1]))
str[len-- -1] = 0;
for(i=0;i<len;i++)
if(!isspace( (unsigned char) str[i]) )
break;
if(i > 0)
memmove(str, str + i, len - i + 1);
}
/*
static int is_hidden(char *fname)
{
int len;
if(fname && fname[0] == '.')
{
if(!strcmp(fname, ".") || !strcmp(fname, ".."))
return 0;
return 1;
}
if(fname)
{
len = strlen(fname);
if(len > 0 && fname[len-1] == '~')
return 1;
}
return 0;
}
*/
/*
* This code would not have been possible without the prior work and
* suggestions of various sourced. Special thanks to Robey for
* all his time/help tracking down bugs and his ever-helpful advice.
*
* 04/09: Fixed the "*\*" against "*a" bug (caused an endless loop)
*
* Chris Fuller (aka Fred1@IRC & Fwitz@IRC)
*
* I hereby release this code into the public domain
*
*/
#include <ctype.h>
#define WILDS '*' /* matches 0 or more characters (including spaces) */
#define WILDQ '?' /* matches ecactly one character */
#define NOMATCH 0
#define MATCH (match+sofar)
static int wildcard_match_int(const char *data, const char *mask, int icase)
{
const char *ma = mask, *na = data, *lsm = 0, *lsn = 0;
int match = 1;
int sofar = 0;
/* null strings should never match */
if ((ma == 0) || (na == 0) || (!*ma) || (!*na))
return NOMATCH;
/* find the end of each string */
while (*(++mask));
mask--;
while (*(++data));
data--;
while (data >= na) {
/* If the mask runs out of chars before the string, fall back on
* a wildcard or fail. */
if (mask < ma) {
if (lsm) {
data = --lsn;
mask = lsm;
if (data < na)
lsm = 0;
sofar = 0;
}
else
return NOMATCH;
}
switch (*mask) {
case WILDS: /* Matches anything */
do
mask--; /* Zap redundant wilds */
while ((mask >= ma) && (*mask == WILDS));
lsm = mask;
lsn = data;
match += sofar;
sofar = 0; /* Update fallback pos */
if (mask < ma)
return MATCH;
continue; /* Next char, please */
case WILDQ:
mask--;
data--;
continue; /* '?' always matches */
}
if (icase ? (toupper(*mask) == toupper(*data)) :
(*mask == *data)) { /* If matching char */
mask--;
data--;
sofar++; /* Tally the match */
continue; /* Next char, please */
}
if (lsm) { /* To to fallback on '*' */
data = --lsn;
mask = lsm;
if (data < na)
lsm = 0; /* Rewind to saved pos */
sofar = 0;
continue; /* Next char, please */
}
return NOMATCH; /* No fallback=No match */
}
while ((mask >= ma) && (*mask == WILDS))
mask--; /* Zap leftover %s & *s */
return (mask >= ma) ? NOMATCH : MATCH; /* Start of both = match */
}
int wildcard_match(const char *data, const char *mask)
{
return wildcard_match_int(data, mask, 0) != 0;
}
int wildcard_match_icase(const char *data, const char *mask)
{
return wildcard_match_int(data, mask, 1) != 0;
}
Here we go.
I just ripped it out of Baby X.
It's got references to the utf8 handling functions - I can give them to you if you use UTF8 internally,
or you can just replace them with wide char alternatives. utf8_skip and utf8_Nchars thus become
return 1 and wstrlen()