X-Git-Url: https://git.jsancho.org/?a=blobdiff_plain;f=Source%2FMacCompatibility.cpp;h=8a295fddd281bf1dc96e5c6032a864cfeab1b44c;hb=44146d06c780d3aaa283672fedb08b8870ebe1b9;hp=86d8dff2d45922f144f755142a5e29eac6b0d952;hpb=40a3dd7b76b6b10ae05dbd074f1f80ea7b4aa96d;p=lugaru.git diff --git a/Source/MacCompatibility.cpp b/Source/MacCompatibility.cpp index 86d8dff..8a295fd 100644 --- a/Source/MacCompatibility.cpp +++ b/Source/MacCompatibility.cpp @@ -1,10 +1,63 @@ +/* +Copyright (C) 2003, 2010 - Wolfire Games + +This file is part of Lugaru. + +Lugaru is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#if !PLATFORM_MACOSX + /**> HEADER FILES <**/ #include "MacCompatibility.h" + +#ifdef WIN32 #include +#endif + #include #include #include +#include +#include +#if PLATFORM_UNIX +#include +#include +#include +#include +typedef long long __int64; +typedef __int64 LARGE_INTEGER; +static int QueryPerformanceFrequency(LARGE_INTEGER *liptr) +{ + assert(sizeof (__int64) == 8); + assert(sizeof (LARGE_INTEGER) == 8); + *liptr = 1000; + return(1); +} + +static int QueryPerformanceCounter(LARGE_INTEGER *liptr) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + *liptr = ( (((LARGE_INTEGER) tv.tv_sec) * 1000) + + (((LARGE_INTEGER) tv.tv_usec) / 1000) ); + return(1); +} +#endif class AppTime { @@ -22,7 +75,6 @@ public: static AppTime g_appTime; - void CopyCStringToPascal( const char* src, unsigned char dst[256]) { int len = strlen( src); @@ -90,9 +142,148 @@ Duration AbsoluteDeltaToDuration( AbsoluteTime& a, AbsoluteTime& b) } -static char g_filename[ 256]; -char* ConvertFileName( const char* orgfilename) +#if PLATFORM_UNIX +#include +#include +#include +#include +#include + +// some but not all of this is code from PhysicsFS: http://icculus.org/physfs/ +// the zlib license on physfs allows this cut-and-pasting. +static int locateOneElement(char *buf) +{ + char *ptr; + char **rc; + char **i; + DIR *dirp; + + //if (PHYSFS_exists(buf)) + if (access(buf, F_OK) == 0) + return(1); /* quick rejection: exists in current case. */ + + ptr = strrchr(buf, '/'); /* find entry at end of path. */ + if (ptr == NULL) + { + dirp = opendir("."); + ptr = buf; + } /* if */ + else + { + *ptr = '\0'; + dirp = opendir(buf); + *ptr = '/'; + ptr++; /* point past dirsep to entry itself. */ + } /* else */ + + struct dirent *dent; + while ((dent = readdir(dirp)) != NULL) + { + if (stricmp(dent->d_name, ptr) == 0) + { + strcpy(ptr, dent->d_name); /* found a match. Overwrite with this case. */ + closedir(dirp); + return(1); + } /* if */ + } /* for */ + + /* no match at all... */ + closedir(dirp); + return(0); +} /* locateOneElement */ + + +static inline const char *getUserDirByUID(void) +{ + struct passwd *pw = getpwuid(getuid()); + if (pw != NULL) + return(pw->pw_dir); + return(NULL); +} /* getUserDirByUID */ + + +static inline const char *getPrefPath(void) +{ + static char *prefpath = NULL; + if (prefpath == NULL) + { + const char *homedir = getenv("HOME"); + if (homedir == NULL) + homedir = getUserDirByUID(); + if (homedir == NULL) + homedir = "."; // oh well. + +#if (defined(__APPLE__) && defined(__MACH__)) + const char *PREFPATHNAME = "Library/Application Support/Lugaru"; +#else + const char *PREFPATHNAME = ".lugaru"; +#endif + size_t len = strlen(homedir) + strlen(PREFPATHNAME) + 2; + prefpath = new char[len]; + snprintf(prefpath, len, "%s/%s", homedir, PREFPATHNAME); + } + return(prefpath); +} + +static int locateCorrectCase(char *buf, bool makedirs) +{ + int rc; + char *ptr; + char *prevptr; + + ptr = prevptr = buf; + while (ptr = strchr(ptr + 1, '/')) + { + *ptr = '\0'; /* block this path section off */ + rc = locateOneElement(buf); + if (!rc) + { + if (makedirs) /* normal if we're writing; build dirs! */ + mkdir(buf, S_IRWXU); + else + { + *ptr = '/'; /* restore path separator */ + return(-2); /* missing element in path. */ + } /* else */ + } /* if */ + *ptr = '/'; /* restore path separator */ + } /* while */ + + /* check final element... */ + return(locateOneElement(buf) ? 0 : -1); +} + + +static int locateCorrectFile(char *buf, const char *mode) { + if (*buf == '\0') + return(0); /* Uh...I guess that's failure. */ + + assert((mode[0] == 'w') || (mode[0] == 'r')); + + bool iswriting = (mode[0] == 'w'); + const char *prefpath = getPrefPath(); + size_t len = strlen(buf) + strlen(prefpath) + 2; + char *prefpathfile = (char *) alloca(len); + snprintf(prefpathfile, len, "%s/%s", prefpath, buf); + + int rc = locateCorrectCase(prefpathfile, iswriting); /* favor prefpath. */ + if ( (rc == 0) || ((rc == -1) && (iswriting)) ) // found or create? + strcpy(buf, prefpathfile); + else if ((rc < 0) && (!iswriting)) /* not writing? Try game dir... */ + rc = locateCorrectCase(buf, iswriting); + + return(rc); +} /* locateCorrectFile */ +#endif + + +static char g_filename[4096]; +char* ConvertFileName( const char* orgfilename, const char *mode) +{ + if (orgfilename == g_filename) // recursion? + return g_filename; + // translate filename into proper path name if (orgfilename[ 0] == ':') orgfilename++; @@ -102,7 +293,18 @@ char* ConvertFileName( const char* orgfilename) { if (g_filename[ n] == ':') g_filename[ n] = '/'; + + else if (g_filename[ n] == '\\') + g_filename[ n] = '/'; } + #if PLATFORM_UNIX + locateCorrectFile(g_filename, mode); + #endif + return g_filename; } + +#endif + +