+
+#include "quakedef.h"
+
+// LordHavoc: some portable directory listing code I wrote for lmp2pcx, now used in darkplaces to load id1/*.pak and such...
+
+int matchpattern(char *in, char *pattern)
+{
+ while (*pattern)
+ {
+ switch (*pattern)
+ {
+ case '?': // match any single character
+ if (!*in)
+ return 0; // no match
+ in++;
+ pattern++;
+ break;
+ case '*': // match anything until following string
+ if (!*in)
+ return 1; // match
+ while (*pattern == '*')
+ pattern++;
+ if (*pattern == '?')
+ {
+ // *? (weird)
+ break;
+ }
+ else if (*pattern)
+ {
+ // *text (typical)
+ while (*in && *in != *pattern)
+ in++;
+ }
+ else
+ {
+ // *null (* at end of pattern)
+ return 1;
+ }
+ break;
+ default:
+ if (*in != *pattern)
+ return 0; // no match
+ in++;
+ pattern++;
+ break;
+ }
+ }
+ if (*in)
+ return 0; // reached end of pattern but not end of input
+ return 1; // success
+}
+
+// a little chained strings system
+stringlist_t *stringlistappend(stringlist_t *current, char *text)
+{
+ stringlist_t *newitem;
+ newitem = Z_Malloc(strlen(text) + 1 + sizeof(stringlist_t));
+ newitem->next = NULL;
+ newitem->text = (char *)(newitem + 1);
+ strcpy(newitem->text, text);
+ if (current)
+ current->next = newitem;
+ return newitem;
+}
+
+void stringlistfree(stringlist_t *current)
+{
+ stringlist_t *next;
+ while (current)
+ {
+ next = current->next;
+ Z_Free(current);
+ current = next;
+ }
+}
+
+stringlist_t *stringlistsort(stringlist_t *start)
+{
+ int notdone;
+ stringlist_t *current, *previous, *temp2, *temp3, *temp4;
+ notdone = 1;
+ while (notdone)
+ {
+ current = start;
+ notdone = 0;
+ previous = NULL;
+ while (current && current->next)
+ {
+ if (strcmp(current->text, current->next->text) > 0)
+ {
+ // current is greater than next
+ notdone = 1;
+ temp2 = current->next;
+ temp3 = current;
+ temp4 = current->next->next;
+ if (previous)
+ previous->next = temp2;
+ else
+ start = temp2;
+ temp2->next = temp3;
+ temp3->next = temp4;
+ break;
+ }
+ previous = current;
+ current = current->next;
+ }
+ }
+ return start;
+}
+
+// operating system specific code
+#ifdef WIN32
+#include <io.h>
+stringlist_t *listdirectory(char *path)
+{
+ char pattern[4096];
+ struct _finddata_t n_file;
+ long hFile;
+ stringlist_t *start, *current;
+ strcpy(pattern, path);
+ strcat(pattern, "\\*");
+ // ask for the directory listing handle
+ hFile = _findfirst(pattern, &n_file);
+ if(hFile != -1)
+ {
+ // start a new chain with the the first name
+ start = current = stringlistappend(NULL, n_file.name);
+ // iterate through the directory
+ while (_findnext(hFile, &n_file) == 0)
+ current = stringlistappend(current, n_file.name);
+ _findclose(hFile);
+ // sort the list alphanumerically
+ return stringlistsort(start);
+ }
+ else
+ return NULL;
+}
+#else
+#include <dirent.h>
+stringlist_t *listdirectory(char *path)
+{
+ DIR *dir;
+ struct dirent *ent;
+ stringlist_t *start, *current;
+ dir = opendir(path);
+ if (!dir)
+ return NULL;
+ ent = readdir(dir);
+ if (!ent)
+ {
+ closedir(dir);
+ return NULL;
+ }
+ start = current = stringlistappend(NULL, ent->d_name);
+ while((ent = readdir(dir)))
+ current = stringlistappend(current, ent->d_name);
+ closedir(dir);
+ // sort the list alphanumerically
+ return stringlistsort(start);
+}
+#endif
+
+void freedirectory(stringlist_t *list)
+{
+ stringlistfree(list);
+}
\ No newline at end of file