ref: 533e3726f0fdeb0f679fedd96ab4877f80922456
parent: 8f956718644e9f6e59c1ac3e9d527a7799e55d87
author: Fabian Greffrath <fabian@greffrath.com>
date: Tue Nov 22 18:53:48 EST 2016
Try multiple capitalizations when searching for WADs. Add M_FileCaseExists() that checks if a file exists by trying multiple different capitalization formats, and change WAD search code to use this when locating WAD files.
--- a/src/d_iwad.c
+++ b/src/d_iwad.c
@@ -459,13 +459,15 @@
static char *CheckDirectoryHasIWAD(char *dir, char *iwadname)
{
char *filename;
+ char *probe;
// As a special case, the "directory" may refer directly to an
// IWAD file if the path comes from DOOMWADDIR or DOOMWADPATH.
- if (DirIsFile(dir, iwadname) && M_FileExists(dir))
+ probe = M_FileCaseExists(dir);
+ if (DirIsFile(dir, iwadname) && probe != NULL)
{
- return M_StringDuplicate(dir);
+ return probe;
}
// Construct the full path to the IWAD if it is located in
@@ -480,9 +482,10 @@
filename = M_StringJoin(dir, DIR_SEPARATOR_S, iwadname, NULL);
}
- if (M_FileExists(filename))
+ probe = M_FileCaseExists(filename);
+ if (probe != NULL)
{
- return filename;
+ return probe;
}
free(filename);
@@ -709,13 +712,15 @@
char *D_FindWADByName(char *name)
{
char *path;
+ char *probe;
int i;
// Absolute path?
- if (M_FileExists(name))
+ probe = M_FileCaseExists(name);
+ if (probe != NULL)
{
- return name;
+ return probe;
}
BuildIWADDirList();
@@ -728,9 +733,10 @@
// the "directory" may actually refer directly to an IWAD
// file.
- if (DirIsFile(iwad_dirs[i], name) && M_FileExists(iwad_dirs[i]))
+ probe = M_FileCaseExists(iwad_dirs[i]);
+ if (DirIsFile(iwad_dirs[i], name) && probe != NULL)
{
- return M_StringDuplicate(iwad_dirs[i]);
+ return probe;
}
// Construct a string for the full path
@@ -737,9 +743,10 @@
path = M_StringJoin(iwad_dirs[i], DIR_SEPARATOR_S, name, NULL);
- if (M_FileExists(path))
+ probe = M_FileCaseExists(path);
+ if (probe != NULL)
{
- return path;
+ return probe;
}
free(path);
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -83,6 +83,75 @@
}
}
+// Check if a file exists by probing for common case variation of its filename.
+// Returns a newly allocated string that the caller is responsible for freeing.
+
+char *M_FileCaseExists(char *path)
+{
+ char *path_dup, *filename, *ext;
+
+ path_dup = M_StringDuplicate(path);
+
+ // 0: actual path
+ if (M_FileExists(path_dup))
+ {
+ return path_dup;
+ }
+
+ filename = strrchr(path_dup, DIR_SEPARATOR);
+ if (filename != NULL)
+ {
+ filename++;
+ }
+ else
+ {
+ filename = path_dup;
+ }
+
+ // 1: lowercase filename, e.g. doom2.wad
+ M_ForceLowercase(filename);
+
+ if (M_FileExists(path_dup))
+ {
+ return path_dup;
+ }
+
+ // 2: uppercase filename, e.g. DOOM2.WAD
+ M_ForceUppercase(filename);
+
+ if (M_FileExists(path_dup))
+ {
+ return path_dup;
+ }
+
+ // 3. uppercase basename with lowercase extension, e.g. DOOM2.wad
+ ext = strrchr(path_dup, '.');
+ if (ext != NULL && ext > filename)
+ {
+ M_ForceLowercase(ext + 1);
+
+ if (M_FileExists(path_dup))
+ {
+ return path_dup;
+ }
+ }
+
+ // 4. lowercase filename with uppercase first letter, e.g. Doom2.wad
+ if (strlen(filename) > 1)
+ {
+ M_ForceLowercase(filename + 1);
+
+ if (M_FileExists(path_dup))
+ {
+ return path_dup;
+ }
+ }
+
+ // 5. no luck
+ free(path_dup);
+ return NULL;
+}
+
//
// Determine the length of an open file.
//
@@ -247,6 +316,24 @@
for (p = text; *p != '\0'; ++p)
{
*p = toupper(*p);
+ }
+}
+
+//---------------------------------------------------------------------------
+//
+// PROC M_ForceLowercase
+//
+// Change string to lowercase.
+//
+//---------------------------------------------------------------------------
+
+void M_ForceLowercase(char *text)
+{
+ char *p;
+
+ for (p = text; *p != '\0'; ++p)
+ {
+ *p = tolower(*p);
}
}
--- a/src/m_misc.h
+++ b/src/m_misc.h
@@ -30,10 +30,12 @@
void M_MakeDirectory(char *dir);
char *M_TempFile(char *s);
boolean M_FileExists(char *file);
+char *M_FileCaseExists(char *file);
long M_FileLength(FILE *handle);
boolean M_StrToInt(const char *str, int *result);
void M_ExtractFileBase(char *path, char *dest);
void M_ForceUppercase(char *text);
+void M_ForceLowercase(char *text);
char *M_StrCaseStr(char *haystack, char *needle);
char *M_StringDuplicate(const char *orig);
boolean M_StringCopy(char *dest, const char *src, size_t dest_size);