1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2024-11-25 17:53:47 +00:00
Aquaria/BBGE/OSFunctions.cpp
fgenesis 8472718fb7 Major include refactor; changes to pretty much everything
This untangles some of the gigantic kitchen sink headers
in an attempt to split things into smaller files.
Also don't include gl.h, glext.h, windows.h,
and other such nonsense *everywhere*.

Lots of cleanups on the way too. More dead/unused code removal.

Remove incrFlag(), decrFlag() Lua functions.
2016-07-09 04:18:40 +02:00

430 lines
8.3 KiB
C++

#include "OSFunctions.h"
#include "Base.h"
#include <sstream>
#include "ttvfs_stdio.h"
#ifdef BBGE_BUILD_WINDOWS
# define WIN32_LEAN_AND_MEAN
# define WIN32_NOMINMAX
# include <windows.h>
# undef min
# undef max
#include <shellapi.h>
#elif BBGE_BUILD_LINUX
# include <sys/types.h>
# include <stdint.h>
#endif
#ifdef _MSC_VER
# include <intrin.h>
#endif
#if defined(BBGE_BUILD_UNIX)
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>
#include <pwd.h>
#include <fcntl.h>
#include <unistd.h>
#endif
#if defined(BBGE_BUILD_MACOSX)
#include <Carbon/Carbon.h>
#include <CoreFoundation/CFLocale.h>
#include <CoreFoundation/CFString.h>
// veeery clunky.
static std::string _CFToStdString(CFStringRef cs)
{
char buf[1024];
CFStringGetCString(cs, &buf[0], 1024, kCFStringEncodingUTF8);
return &buf[0];
}
#endif
#ifdef BBGE_BUILD_VFS
#include "ttvfs.h"
#endif
#include "SDL.h"
void openURL(const std::string &url)
{
#ifdef BBGE_BUILD_WINDOWS
ShellExecute(NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
#endif
#if defined(BBGE_BUILD_MACOSX)
CFStringRef str = CFStringCreateWithCString (0, url.c_str(), 0);
CFURLRef ref = CFURLCreateWithString(kCFAllocatorDefault, str, NULL);
LSOpenCFURLRef(ref, 0);
CFRelease(ref);
CFRelease(str);
#elif BBGE_BUILD_UNIX
std::string cmd("PATH=$PATH:. xdg-open '");
cmd += url;
cmd += "'";
if (system(cmd.c_str()) != 0)
debugLog("system(xdg_open '" + url + "') failed");
#endif
}
void triggerBreakpoint()
{
#ifdef _MSC_VER
__debugbreak();
#elif defined(__GNUC__) && ((__i386__) || (__x86_64__))
__asm__ __volatile__ ( "int $3\n\t" );
#else
raise(SIGTRAP);
#endif
}
bool createDir(const std::string& d)
{
bool success = false;
int err = 0;
#if defined(BBGE_BUILD_UNIX)
if (!mkdir(d.c_str(), S_IRWXU))
success = true;
else
{
err = errno;
if (err == EEXIST)
success = true;
}
#elif defined(BBGE_BUILD_WINDOWS)
if (CreateDirectoryA(d.c_str(), NULL))
success = true;
else
{
err = GetLastError();
if(err == ERROR_ALREADY_EXISTS)
success = true;
}
#endif
if (!success)
{
std::ostringstream os;
os << "Failed to create directory: [" << d << "], error code: " << err;
debugLog(os.str());
}
return success;
}
#if defined(BBGE_BUILD_MACOSX) && !SDL_VERSION_ATLEAST(2,0,0)
void cocoaMessageBox(const std::string &title, const std::string &msg);
#endif
void messageBox(const std::string& title, const std::string &msg)
{
#ifdef BBGE_BUILD_WINDOWS
MessageBox (0,msg.c_str(),title.c_str(),MB_OK);
#elif SDL_VERSION_ATLEAST(2,0,0)
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, title.c_str(),
msg.c_str(), NULL);
#elif defined(BBGE_BUILD_MACOSX)
cocoaMessageBox(title, msg);
#elif defined(BBGE_BUILD_UNIX)
// !!! FIXME: probably don't want the whole GTK+ dependency in here...
fprintf(stderr, "%s: %s\n", title.c_str(), msg.c_str());
#else
#error Please define your platform.
#endif
}
#ifdef BBGE_BUILD_VFS
struct vfscallback_s
{
const std::string *path;
const char *ext;
intptr_t param;
void (*callback)(const std::string &filename, intptr_t param);
};
void forEachFile_vfscallback(VFILE *vf, void *user)
{
vfscallback_s *d = (vfscallback_s*)user;
if(d->ext)
{
const char *e = strrchr(vf->name(), '.');
if(e && nocasecmp(d->ext, e))
return;
}
d->callback(*(d->path) + vf->name(), d->param);
}
#endif
void forEachFile(const std::string& inpath, std::string type, void callback(const std::string &filename, intptr_t param), intptr_t param)
{
if (inpath.empty()) return;
#ifdef BBGE_BUILD_VFS
ttvfs::DirView view;
if(!vfs.FillDirView(inpath.c_str(), view))
{
debugLog("Path '" + inpath + "' does not exist");
return;
}
vfscallback_s dat;
dat.path = &inpath;
dat.ext = type.length() ? type.c_str() : NULL;
dat.param = param;
dat.callback = callback;
view.forEachFile(forEachFile_vfscallback, &dat, true);
return;
// -------------------------------------
#endif
stringToLower(type);
std::string path = adjustFilenameCase(inpath.c_str());
debugLog("forEachFile - path: " + path + " type: " + type);
#if defined(BBGE_BUILD_UNIX)
DIR *dir=0;
dir = opendir(path.c_str());
if (dir)
{
dirent *file=0;
while ( (file=readdir(dir)) != NULL )
{
if (file->d_name && strlen(file->d_name) > 4)
{
debugLog(file->d_name);
char *extension=strrchr(file->d_name,'.');
if (extension)
{
debugLog(extension);
if (extension!=NULL)
{
if (strcasecmp(extension,type.c_str())==0)
{
callback(path + std::string(file->d_name), param);
}
}
}
}
}
closedir(dir);
}
else
{
debugLog("FAILED TO OPEN DIR");
}
#endif
#ifdef BBGE_BUILD_WINDOWS
BOOL fFinished;
HANDLE hList;
TCHAR szDir[MAX_PATH+1];
WIN32_FIND_DATA FileData;
int end = path.size()-1;
if (path[end] != '/')
path[end] += '/';
// Get the proper directory path
// \\ %s\\*
if (type.find('.')==std::string::npos)
{
type = "." + type;
}
sprintf(szDir, "%s\\*", path.c_str());
stringToUpper(type);
// Get the first file
hList = FindFirstFile(szDir, &FileData);
if (hList == INVALID_HANDLE_VALUE)
{
debugLog("No files of type " + type + " found in path " + path);
}
else
{
// Traverse through the directory structure
fFinished = FALSE;
while (!fFinished)
{
// Check the object is a directory or not
//printf("%*s%s\n", indent, "", FileData.cFileName);
std::string filename = FileData.cFileName;
if (filename.size()>4)
{
std::string filetype = filename.substr(filename.size()-4, filename.size());
stringToUpper(filetype);
if (filetype==type)
{
callback(path+filename, param);
}
}
if (!FindNextFile(hList, &FileData))
{
fFinished = TRUE;
}
}
}
FindClose(hList);
#endif
}
#if BBGE_BUILD_UNIX
// based on code I wrote for PhysicsFS: http://icculus.org/physfs/
// the zlib license on physfs allows this cut-and-pasting.
static int locateOneElement(char *buf)
{
char *ptr;
DIR *dirp;
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;
}
else
{
*ptr = '\0';
dirp = opendir(buf);
*ptr = '/';
ptr++; // point past dirsep to entry itself.
}
struct dirent *dent;
while ((dent = readdir(dirp)) != NULL)
{
if (strcasecmp(dent->d_name, ptr) == 0)
{
strcpy(ptr, dent->d_name); // found a match. Overwrite with this case.
closedir(dirp);
return(1);
}
}
// no match at all...
closedir(dirp);
return(0);
}
#endif
std::string adjustFilenameCase(const std::string& s)
{
return adjustFilenameCase(s.c_str());
}
std::string adjustFilenameCase(const char *_buf)
{
#ifdef BBGE_BUILD_UNIX // any case is fine if not Linux.
int rc = 1;
char *buf = (char *) alloca(strlen(_buf) + 1);
strcpy(buf, _buf);
char *ptr = buf;
while ((ptr = strchr(ptr + 1, '/')) != 0)
{
*ptr = '\0'; // block this path section off
rc = locateOneElement(buf);
*ptr = '/'; // restore path separator
if (!rc)
break; // missing element in path.
}
// check final element...
if (rc)
rc = locateOneElement(buf);
#if 0
if (strcmp(_buf, buf) != 0)
{
fprintf(stderr, "Corrected filename case: '%s' => '%s (%s)'\n",
_buf, buf, rc ? "found" : "not found");
}
#endif
return std::string(buf);
#else
return std::string(_buf);
#endif
}
std::string getSystemLocale()
{
std::string localeStr;
#ifdef BBGE_BUILD_WINDOWS
LCID lcid = GetThreadLocale();
char buf[100];
char ctry[100];
if (GetLocaleInfo(lcid, LOCALE_SISO639LANGNAME, buf, sizeof buf) != 0)
{
localeStr = buf;
if (GetLocaleInfo(lcid, LOCALE_SISO3166CTRYNAME, ctry, sizeof ctry) != 0)
{
localeStr += "_";
localeStr += ctry;
}
}
#elif BBGE_BUILD_MACOSX
CFLocaleRef locale = CFLocaleCopyCurrent();
CFStringRef buf;
if ((buf = (CFStringRef)CFLocaleGetValue(locale, kCFLocaleLanguageCode)) != NULL)
{
localeStr = _CFToStdString(buf);
if ((buf = (CFStringRef)CFLocaleGetValue(locale, kCFLocaleCountryCode)) != NULL)
{
localeStr += "_";
localeStr += _CFToStdString(buf);
}
}
CFRelease(locale);
#else
const char *lang = (const char *)getenv("LANG");
if (lang && *lang)
{
localeStr = lang;
size_t found = localeStr.find('.');
if (found != std::string::npos)
localeStr.resize(found);
}
#endif
return localeStr;
}