From 1c83503f63868a30f2090ce88e0bc0d76dd6dc16 Mon Sep 17 00:00:00 2001 From: black Date: Fri, 15 Feb 2008 15:03:06 +0000 Subject: [PATCH] New attempt to change listdirectory. FS_Search now also correctly processes wildcards everywhere (models/players/*/*.skin works now). git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@8100 d7cf8633-e32d-0410-b094-e92efae38249 --- common.h | 2 +- filematch.c | 22 ++++++++----- fs.c | 93 ++++++++++++++++++++++++++++++++++++++++++++--------- menu.c | 5 +-- 4 files changed, 94 insertions(+), 28 deletions(-) diff --git a/common.h b/common.h index 1a9659a9..b5e6fc0f 100644 --- a/common.h +++ b/common.h @@ -318,7 +318,7 @@ void stringlistinit(stringlist_t *list); void stringlistfreecontents(stringlist_t *list); void stringlistappend(stringlist_t *list, const char *text); void stringlistsort(stringlist_t *list); -void listdirectory(stringlist_t *list, const char *path); +void listdirectory(stringlist_t *list, const char *basepath, const char *path); char *SearchInfostring(const char *infostring, const char *key); diff --git a/filematch.c b/filematch.c index 2a22cb0f..9092f551 100644 --- a/filematch.c +++ b/filematch.c @@ -76,6 +76,7 @@ void stringlistfreecontents(stringlist_t *list) list->maxstrings = 0; if (list->strings) Z_Free(list->strings); + list->strings = NULL; } void stringlistappend(stringlist_t *list, const char *text) @@ -119,29 +120,32 @@ void stringlistsort(stringlist_t *list) } // operating system specific code -static void adddirentry(stringlist_t *list, const char *name) +static void adddirentry(stringlist_t *list, const char *path, const char *name) { if (strcmp(name, ".") && strcmp(name, "..")) { - stringlistappend(list, name); + char temp[MAX_OSPATH]; + dpsnprintf( temp, sizeof( temp ), "%s%s", path, name ); + stringlistappend(list, temp); } } #ifdef WIN32 #include -void listdirectory(stringlist_t *list, const char *path) +void listdirectory(stringlist_t *list, const char *basepath, const char *path) { int i; char pattern[4096], *c; struct _finddata_t n_file; long hFile; - strlcpy (pattern, path, sizeof (pattern)); + strlcpy (pattern, basepath, sizeof(pattern)); + strlcat (pattern, path, sizeof (pattern)); strlcat (pattern, "*", sizeof (pattern)); // ask for the directory listing handle hFile = _findfirst(pattern, &n_file); if(hFile == -1) return; do { - adddirentry(list, n_file.name ); + adddirentry(list, path, n_file.name ); } while (_findnext(hFile, &n_file) == 0); _findclose(hFile); @@ -153,15 +157,17 @@ void listdirectory(stringlist_t *list, const char *path) } #else #include -void listdirectory(stringlist_t *list, const char *path) +void listdirectory(stringlist_t *list, const char *basepath, const char *path) { + char fullpath[MAX_OSPATH]; DIR *dir; struct dirent *ent; - dir = opendir(path); + dpsnprintf(fullpath, "%s%s", sizeof(fullpath), basepath, *path ? path : "./"); + dir = opendir(fullpath); if (!dir) return; while ((ent = readdir(dir))) - adddirentry(list, ent->d_name); + adddirentry(list, path, ent->d_name); closedir(dir); } #endif diff --git a/fs.c b/fs.c index eee8a47d..ad806685 100644 --- a/fs.c +++ b/fs.c @@ -960,12 +960,11 @@ void FS_AddGameDirectory (const char *dir) int i; stringlist_t list; searchpath_t *search; - char pakfile[MAX_OSPATH]; strlcpy (fs_gamedir, dir, sizeof (fs_gamedir)); stringlistinit(&list); - listdirectory(&list, dir); + listdirectory(&list, "", dir); stringlistsort(&list); // add any PAK package in the directory @@ -973,8 +972,7 @@ void FS_AddGameDirectory (const char *dir) { if (!strcasecmp(FS_FileExtension(list.strings[i]), "pak")) { - dpsnprintf (pakfile, sizeof (pakfile), "%s%s", dir, list.strings[i]); - FS_AddPack_Fullpath(pakfile, NULL, false); + FS_AddPack_Fullpath(list.strings[i], NULL, false); } } @@ -983,8 +981,7 @@ void FS_AddGameDirectory (const char *dir) { if (!strcasecmp(FS_FileExtension(list.strings[i]), "pk3")) { - dpsnprintf (pakfile, sizeof (pakfile), "%s%s", dir, list.strings[i]); - FS_AddPack_Fullpath(pakfile, NULL, false); + FS_AddPack_Fullpath(list.strings[i], NULL, false); } } @@ -1322,7 +1319,7 @@ qboolean FS_CheckGameDir(const char *gamedir) qboolean success; stringlist_t list; stringlistinit(&list); - listdirectory(&list, va("%s%s/", fs_basedir, gamedir)); + listdirectory(&list, va("%s%s/", fs_basedir, gamedir), ""); success = list.numstrings > 0; stringlistfreecontents(&list); return success; @@ -2530,7 +2527,6 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet) stringlist_t dirlist; const char *slash, *backslash, *colon, *separator; char *basepath; - char netpath[MAX_OSPATH]; char temp[MAX_OSPATH]; for (i = 0;pattern[i] == '.' || pattern[i] == ':' || pattern[i] == '/' || pattern[i] == '\\';i++) @@ -2599,13 +2595,80 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet) } else { - // get a directory listing and look at each name - dpsnprintf(netpath, sizeof (netpath), "%s%s", searchpath->filename, basepath); - stringlistinit(&dirlist); - listdirectory(&dirlist, netpath); - for (dirlistindex = 0;dirlistindex < dirlist.numstrings;dirlistindex++) + stringlist_t matchedSet, foundSet; + int resultindex = 0; + const char *start = pattern; + + stringlistinit(&matchedSet); + stringlistinit(&foundSet); + // add a first entry to the set + stringlistappend(&matchedSet, ""); + // iterate through pattern's path + while (*start) { - dpsnprintf(temp, sizeof(temp), "%s%s", basepath, dirlist.strings[dirlistindex]); + const char *asterisk, *wildcard, *nextseparator, *prevseparator; + char subpath[MAX_OSPATH]; + char subpattern[MAX_OSPATH]; + + // find the next wildcard + wildcard = strchr(start, '?'); + asterisk = strchr(start, '*'); + if (asterisk && (!wildcard || asterisk < wildcard)) + { + wildcard = asterisk; + } + + if (wildcard) + { + nextseparator = strchr( wildcard, '/' ); + } + else + { + nextseparator = NULL; + } + + if( !nextseparator ) { + nextseparator = start + strlen( start ); + } + + // copy everything up except nextseperator + strlcpy(subpattern, pattern, min(sizeof(subpattern), nextseparator - pattern + 1)); + // find the last / + prevseparator = strrchr( subpattern, '/' ) + 1; + if (!prevseparator) + { + prevseparator = subpattern; + } + // copy everything including the last '/' + strlcpy(subpath, start, min(sizeof(subpath), (prevseparator - subpattern) - (start - pattern) + 1)); + + // prevseparator points to the one right before the wildcard and nextseparator to the one following it (or past the end of the string (at \0)) + // start to prevseparator can be opened now and added to the other resultset + for( dirlistindex = 0 ; dirlistindex < matchedSet.numstrings ; dirlistindex++ ) { + strlcpy( temp, matchedSet.strings[ dirlistindex ], sizeof(temp) ); + strlcat( temp, subpath, sizeof(temp) ); + listdirectory( &foundSet, searchpath->filename, temp ); + } + if( dirlistindex == 0 ) { + break; + } + // reset the current result set + stringlistfreecontents( &matchedSet ); + // match against the pattern + for( dirlistindex = 0 ; dirlistindex < foundSet.numstrings ; dirlistindex++ ) { + const char *direntry = foundSet.strings[ dirlistindex ]; + if (matchpattern(direntry, subpattern, true)) { + stringlistappend( &matchedSet, direntry ); + } + } + stringlistfreecontents( &foundSet ); + + start = nextseparator; + } + + for (dirlistindex = 0;dirlistindex < matchedSet.numstrings;dirlistindex++) + { + const char *temp = matchedSet.strings[dirlistindex]; if (matchpattern(temp, (char *)pattern, true)) { for (resultlistindex = 0;resultlistindex < resultlist.numstrings;resultlistindex++) @@ -2619,7 +2682,7 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet) } } } - stringlistfreecontents(&dirlist); + stringlistfreecontents( &matchedSet ); } } diff --git a/menu.c b/menu.c index afae9ad2..c8ffdb54 100644 --- a/menu.c +++ b/menu.c @@ -4468,10 +4468,7 @@ void ModList_RebuildList(void) stringlist_t list; stringlistinit(&list); - if (fs_basedir[0]) - listdirectory(&list, fs_basedir); - else - listdirectory(&list, "./"); + listdirectory(&list, fs_basedir, ""); stringlistsort(&list); modlist_count = 0; modlist_numenabled = fs_numgamedirs; -- 2.39.2