+ return filename; // no separator found: filename has no path
+}
+
+char *getBaseName(char *filename)
+{
+ return getStringCopy(getBaseNamePtr(filename));
+}
+
+char *getBaseNameNoSuffix(char *filename)
+{
+ char *basename = getStringCopy(getBaseNamePtr(filename));
+
+ // remove trailing suffix (separated by dot or hyphen)
+ if (basename[0] != '.' && basename[0] != '-')
+ {
+ if (strchr(basename, '.') != NULL)
+ *strchr(basename, '.') = '\0';
+
+ if (strchr(basename, '-') != NULL)
+ *strchr(basename, '-') = '\0';
+ }
+
+ return basename;
+}
+
+char *getBasePath(char *filename)
+{
+ char *basepath = getStringCopy(filename);
+ char *last_separator = getLastPathSeparatorPtr(basepath);
+
+ // if no separator was found, use current directory
+ if (last_separator == NULL)
+ {
+ free(basepath);
+
+ return getStringCopy(".");
+ }
+
+ // separator found: strip basename
+ *last_separator = '\0';
+
+ return basepath;
+}
+
+
+// ----------------------------------------------------------------------------
+// various string functions
+// ----------------------------------------------------------------------------
+
+char *getStringCat2WithSeparator(const char *s1,
+ const char *s2,
+ const char *sep)
+{
+ if (s1 == NULL || s2 == NULL || sep == NULL)
+ return NULL;
+
+ char *complete_string = checked_malloc(strlen(s1) + strlen(sep) +
+ strlen(s2) + 1);
+
+ sprintf(complete_string, "%s%s%s", s1, sep, s2);
+
+ return complete_string;
+}
+
+char *getStringCat3WithSeparator(const char *s1,
+ const char *s2,
+ const char *s3,
+ const char *sep)
+{
+ if (s1 == NULL || s2 == NULL || s3 == NULL || sep == NULL)
+ return NULL;
+
+ char *complete_string = checked_malloc(strlen(s1) + strlen(sep) +
+ strlen(s2) + strlen(sep) +
+ strlen(s3) + 1);
+
+ sprintf(complete_string, "%s%s%s%s%s", s1, sep, s2, sep, s3);
+
+ return complete_string;
+}
+
+char *getStringCat2(const char *s1, const char *s2)
+{
+ return getStringCat2WithSeparator(s1, s2, "");
+}
+
+char *getStringCat3(const char *s1, const char *s2, const char *s3)
+{
+ return getStringCat3WithSeparator(s1, s2, s3, "");
+}
+
+char *getPath2(const char *path1, const char *path2)
+{
+#if defined(PLATFORM_ANDROID)
+ // workaround for reading from assets directory -- skip "." subdirs in path
+ if (strEqual(path1, "."))
+ return getStringCopy(path2);
+ else if (strEqual(path2, "."))
+ return getStringCopy(path1);
+#endif
+
+ return getStringCat2WithSeparator(path1, path2, STRING_PATH_SEPARATOR);
+}
+
+char *getPath3(const char *path1, const char *path2, const char *path3)
+{
+#if defined(PLATFORM_ANDROID)
+ // workaround for reading from assets directory -- skip "." subdirs in path
+ if (strEqual(path1, "."))
+ return getStringCat2WithSeparator(path2, path3, STRING_PATH_SEPARATOR);
+ else if (strEqual(path2, "."))
+ return getStringCat2WithSeparator(path1, path3, STRING_PATH_SEPARATOR);
+ else if (strEqual(path3, "."))
+ return getStringCat2WithSeparator(path1, path2, STRING_PATH_SEPARATOR);
+#endif
+
+ return getStringCat3WithSeparator(path1, path2, path3, STRING_PATH_SEPARATOR);
+}
+
+static char *getPngOrPcxIfNotExists(char *filename)
+{
+ // switch from PNG to PCX file and vice versa, if file does not exist
+ // (backwards compatibility with PCX files used in previous versions)
+
+ if (!fileExists(filename) && strSuffix(filename, ".png"))
+ strcpy(&filename[strlen(filename) - 3], "pcx");
+ else if (!fileExists(filename) && strSuffix(filename, ".pcx"))
+ strcpy(&filename[strlen(filename) - 3], "png");
+
+ return filename;
+}
+
+char *getImg2(const char *path1, const char *path2)
+{
+ return getPngOrPcxIfNotExists(getPath2(path1, path2));
+}
+
+char *getImg3(const char *path1, const char *path2, const char *path3)
+{
+ return getPngOrPcxIfNotExists(getPath3(path1, path2, path3));
+}
+
+char *getStringCopy(const char *s)
+{
+ char *s_copy;
+
+ if (s == NULL)
+ return NULL;
+
+ s_copy = checked_malloc(strlen(s) + 1);
+ strcpy(s_copy, s);
+
+ return s_copy;
+}
+
+char *getStringCopyN(const char *s, int n)
+{
+ char *s_copy;
+ int s_len = MAX(0, n);
+
+ if (s == NULL)
+ return NULL;
+
+ s_copy = checked_malloc(s_len + 1);
+ strncpy(s_copy, s, s_len);
+ s_copy[s_len] = '\0';
+
+ return s_copy;
+}
+
+char *getStringCopyNStatic(const char *s, int n)
+{
+ static char *s_copy = NULL;
+
+ checked_free(s_copy);
+
+ s_copy = getStringCopyN(s, n);
+
+ return s_copy;
+}
+
+char *getStringToUpper(const char *s)
+{
+ char *s_copy = checked_malloc(strlen(s) + 1);
+ char *s_ptr = s_copy;
+
+ while (*s)
+ *s_ptr++ = toupper(*s++);
+ *s_ptr = '\0';
+
+ return s_copy;
+}
+
+char *getStringToLower(const char *s)
+{
+ char *s_copy = checked_malloc(strlen(s) + 1);
+ char *s_ptr = s_copy;
+
+ while (*s)
+ *s_ptr++ = tolower(*s++);
+ *s_ptr = '\0';
+
+ return s_copy;
+}
+
+static char *getStringVPrint(char *format, va_list ap)
+{
+ char s[MAX_LINE_LEN];
+
+ vsnprintf(s, MAX_LINE_LEN, format, ap); // may truncate output string
+
+ return getStringCopy(s);