mirror of https://github.com/OpenRCT2/OpenRCT2.git
clang-format platform
This commit is contained in:
parent
bb3561f70b
commit
0b3edc70f2
|
@ -9,36 +9,41 @@
|
|||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
#include "platform.h"
|
||||
#include "../config/Config.h"
|
||||
#include "../localisation/Language.h"
|
||||
#include "../util/Util.h"
|
||||
#include <wchar.h>
|
||||
#include <jni.h>
|
||||
#include "platform.h"
|
||||
|
||||
#include <SDL.h>
|
||||
#include <jni.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#ifndef NO_TTF
|
||||
bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size)
|
||||
bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size)
|
||||
{
|
||||
STUB();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t platform_get_locale_language() {
|
||||
uint16_t platform_get_locale_language()
|
||||
{
|
||||
return LANGUAGE_ENGLISH_UK;
|
||||
}
|
||||
|
||||
uint8_t platform_get_locale_currency() {
|
||||
uint8_t platform_get_locale_currency()
|
||||
{
|
||||
return platform_get_currency_value(NULL);
|
||||
}
|
||||
|
||||
uint8_t platform_get_locale_measurement_format() {
|
||||
uint8_t platform_get_locale_measurement_format()
|
||||
{
|
||||
return MEASUREMENT_FORMAT_METRIC;
|
||||
}
|
||||
|
||||
float platform_get_default_scale() {
|
||||
JNIEnv *env = static_cast<JNIEnv *>(SDL_AndroidGetJNIEnv());
|
||||
float platform_get_default_scale()
|
||||
{
|
||||
JNIEnv* env = static_cast<JNIEnv*>(SDL_AndroidGetJNIEnv());
|
||||
|
||||
jobject activity = static_cast<jobject>(SDL_AndroidGetActivity());
|
||||
jclass activityClass = env->GetObjectClass(activity);
|
||||
|
@ -52,7 +57,7 @@ float platform_get_default_scale() {
|
|||
return displayScale;
|
||||
}
|
||||
|
||||
bool platform_get_steam_path(utf8 * outPath, size_t outSize)
|
||||
bool platform_get_steam_path(utf8* outPath, size_t outSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -14,41 +14,44 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <breakpad/client/windows/handler/exception_handler.h>
|
||||
#include <string>
|
||||
#include <ShlObj.h>
|
||||
#include <ShlObj.h>
|
||||
#include <breakpad/client/windows/handler/exception_handler.h>
|
||||
#include <string>
|
||||
#else
|
||||
#error Breakpad support not implemented yet for this platform
|
||||
#error Breakpad support not implemented yet for this platform
|
||||
#endif
|
||||
|
||||
#include "../Version.h"
|
||||
#include "../core/Console.hpp"
|
||||
#include "../localisation/Language.h"
|
||||
#include "../rct2/S6Exporter.h"
|
||||
#include "../scenario/Scenario.h"
|
||||
#include "../Version.h"
|
||||
#include "platform.h"
|
||||
|
||||
#define WSZ(x) L"" x
|
||||
|
||||
#ifdef OPENRCT2_COMMIT_SHA1_SHORT
|
||||
const wchar_t *_wszCommitSha1Short = WSZ(OPENRCT2_COMMIT_SHA1_SHORT);
|
||||
const wchar_t* _wszCommitSha1Short = WSZ(OPENRCT2_COMMIT_SHA1_SHORT);
|
||||
#else
|
||||
const wchar_t *_wszCommitSha1Short = WSZ("");
|
||||
const wchar_t* _wszCommitSha1Short = WSZ("");
|
||||
#endif
|
||||
|
||||
// OPENRCT2_ARCHITECTURE is required to be defined in version.h
|
||||
const wchar_t *_wszArchitecture = WSZ(OPENRCT2_ARCHITECTURE);
|
||||
const wchar_t* _wszArchitecture = WSZ(OPENRCT2_ARCHITECTURE);
|
||||
|
||||
static bool OnCrash(const wchar_t * dumpPath,
|
||||
const wchar_t * miniDumpId,
|
||||
void * context,
|
||||
EXCEPTION_POINTERS * exinfo,
|
||||
MDRawAssertionInfo * assertion,
|
||||
bool succeeded)
|
||||
static bool OnCrash(
|
||||
const wchar_t* dumpPath,
|
||||
const wchar_t* miniDumpId,
|
||||
void* context,
|
||||
EXCEPTION_POINTERS* exinfo,
|
||||
MDRawAssertionInfo* assertion,
|
||||
bool succeeded)
|
||||
{
|
||||
if (!succeeded)
|
||||
{
|
||||
constexpr const char * DumpFailedMessage = "Failed to create the dump. Please file an issue with OpenRCT2 on GitHub and provide latest save, and provide information about what you did before the crash occurred.";
|
||||
constexpr const char* DumpFailedMessage
|
||||
= "Failed to create the dump. Please file an issue with OpenRCT2 on GitHub and provide latest save, and provide "
|
||||
"information about what you did before the crash occurred.";
|
||||
printf("%s\n", DumpFailedMessage);
|
||||
if (!gOpenRCT2SilentBreakpad)
|
||||
{
|
||||
|
@ -65,7 +68,14 @@ static bool OnCrash(const wchar_t * dumpPath,
|
|||
|
||||
// Try to rename the files
|
||||
wchar_t dumpFilePathNew[MAX_PATH];
|
||||
swprintf_s(dumpFilePathNew, sizeof(dumpFilePathNew), L"%s%s(%s_%s).dmp", dumpPath, miniDumpId, _wszCommitSha1Short, _wszArchitecture);
|
||||
swprintf_s(
|
||||
dumpFilePathNew,
|
||||
sizeof(dumpFilePathNew),
|
||||
L"%s%s(%s_%s).dmp",
|
||||
dumpPath,
|
||||
miniDumpId,
|
||||
_wszCommitSha1Short,
|
||||
_wszArchitecture);
|
||||
if (_wrename(dumpFilePath, dumpFilePathNew) == 0)
|
||||
{
|
||||
std::wcscpy(dumpFilePath, dumpFilePathNew);
|
||||
|
@ -79,7 +89,7 @@ static bool OnCrash(const wchar_t * dumpPath,
|
|||
wprintf(L"Commit: %s\n", _wszCommitSha1Short);
|
||||
|
||||
bool savedGameDumped = false;
|
||||
utf8 * saveFilePathUTF8 = widechar_to_utf8(saveFilePath);
|
||||
utf8* saveFilePathUTF8 = widechar_to_utf8(saveFilePath);
|
||||
try
|
||||
{
|
||||
auto exporter = std::make_unique<S6Exporter>();
|
||||
|
@ -87,7 +97,7 @@ static bool OnCrash(const wchar_t * dumpPath,
|
|||
exporter->SaveGame(saveFilePathUTF8);
|
||||
savedGameDumped = true;
|
||||
}
|
||||
catch (const std::exception &)
|
||||
catch (const std::exception&)
|
||||
{
|
||||
}
|
||||
free(saveFilePathUTF8);
|
||||
|
@ -97,13 +107,11 @@ static bool OnCrash(const wchar_t * dumpPath,
|
|||
return succeeded;
|
||||
}
|
||||
|
||||
constexpr const wchar_t * MessageFormat = L"A crash has occurred and a dump was created at\n%s.\n\nPlease file an issue with OpenRCT2 on GitHub, and provide the dump and saved game there.\n\nVersion: %s\nCommit: %s";
|
||||
constexpr const wchar_t* MessageFormat
|
||||
= L"A crash has occurred and a dump was created at\n%s.\n\nPlease file an issue with OpenRCT2 on GitHub, and provide "
|
||||
L"the dump and saved game there.\n\nVersion: %s\nCommit: %s";
|
||||
wchar_t message[MAX_PATH * 2];
|
||||
swprintf_s(message,
|
||||
MessageFormat,
|
||||
dumpFilePath,
|
||||
WSZ(OPENRCT2_VERSION),
|
||||
_wszCommitSha1Short);
|
||||
swprintf_s(message, MessageFormat, dumpFilePath, WSZ(OPENRCT2_VERSION), _wszCommitSha1Short);
|
||||
|
||||
// Cannot use platform_show_messagebox here, it tries to set parent window already dead.
|
||||
MessageBoxW(nullptr, message, WSZ(OPENRCT2_NAME), MB_OK | MB_ICONERROR);
|
||||
|
@ -119,8 +127,9 @@ static bool OnCrash(const wchar_t * dumpPath,
|
|||
{
|
||||
files[numFiles++] = ILCreateFromPathW(saveFilePath);
|
||||
}
|
||||
if (pidl != nullptr) {
|
||||
SHOpenFolderAndSelectItems(pidl, numFiles, (LPCITEMIDLIST *)files, 0);
|
||||
if (pidl != nullptr)
|
||||
{
|
||||
SHOpenFolderAndSelectItems(pidl, numFiles, (LPCITEMIDLIST*)files, 0);
|
||||
ILFree(pidl);
|
||||
for (uint32_t i = 0; i < numFiles; i++)
|
||||
{
|
||||
|
@ -139,7 +148,7 @@ static std::wstring GetDumpDirectory()
|
|||
char userDirectory[MAX_PATH];
|
||||
platform_get_user_directory(userDirectory, nullptr, sizeof(userDirectory));
|
||||
|
||||
wchar_t * userDirectoryW = utf8_to_widechar(userDirectory);
|
||||
wchar_t* userDirectoryW = utf8_to_widechar(userDirectory);
|
||||
auto result = std::wstring(userDirectoryW);
|
||||
free(userDirectoryW);
|
||||
|
||||
|
@ -147,7 +156,7 @@ static std::wstring GetDumpDirectory()
|
|||
}
|
||||
|
||||
// Using non-null pipe name here lets breakpad try setting OOP crash handling
|
||||
constexpr const wchar_t * PipeName = L"openrct2-bpad";
|
||||
constexpr const wchar_t* PipeName = L"openrct2-bpad";
|
||||
|
||||
#endif // USE_BREAKPAD
|
||||
|
||||
|
@ -156,16 +165,9 @@ CExceptionHandler crash_init()
|
|||
#ifdef USE_BREAKPAD
|
||||
// Path must exist and be RW!
|
||||
auto exHandler = new google_breakpad::ExceptionHandler(
|
||||
GetDumpDirectory(),
|
||||
0,
|
||||
OnCrash,
|
||||
0,
|
||||
google_breakpad::ExceptionHandler::HANDLER_ALL,
|
||||
MiniDumpWithDataSegs,
|
||||
PipeName,
|
||||
0);
|
||||
GetDumpDirectory(), 0, OnCrash, 0, google_breakpad::ExceptionHandler::HANDLER_ALL, MiniDumpWithDataSegs, PipeName, 0);
|
||||
return reinterpret_cast<CExceptionHandler>(exHandler);
|
||||
#else // USE_BREAKPAD
|
||||
#else // USE_BREAKPAD
|
||||
return nullptr;
|
||||
#endif // USE_BREAKPAD
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
#ifndef _OPENRCT2_CRASH_
|
||||
#define _OPENRCT2_CRASH_
|
||||
|
||||
using CExceptionHandler = void *;
|
||||
using CExceptionHandler = void*;
|
||||
|
||||
extern bool gOpenRCT2SilentBreakpad;
|
||||
CExceptionHandler crash_init();
|
||||
|
||||
#endif /* _OPENRCT2_CRASH_ */
|
||||
#endif /* _OPENRCT2_CRASH_ */
|
||||
|
|
|
@ -26,68 +26,81 @@
|
|||
#ifndef NO_TTF
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#endif // NO_TTF
|
||||
#include <fnmatch.h>
|
||||
#include <locale.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include "../config/Config.h"
|
||||
#include "../localisation/Language.h"
|
||||
#include "../localisation/StringIds.h"
|
||||
#include "../util/Util.h"
|
||||
#include "platform.h"
|
||||
|
||||
uint16_t platform_get_locale_language(){
|
||||
const char *langString = setlocale(LC_MESSAGES, "");
|
||||
if(langString != nullptr){
|
||||
#include <fnmatch.h>
|
||||
#include <locale.h>
|
||||
#include <pwd.h>
|
||||
|
||||
uint16_t platform_get_locale_language()
|
||||
{
|
||||
const char* langString = setlocale(LC_MESSAGES, "");
|
||||
if (langString != nullptr)
|
||||
{
|
||||
// The locale has the following form:
|
||||
// language[_territory[.codeset]][@modifier]
|
||||
// (see https://www.gnu.org/software/libc/manual/html_node/Locale-Names.html)
|
||||
// longest on my system is 29 with codeset and modifier, so 32 for the pattern should be more than enough
|
||||
char pattern[32];
|
||||
//strip the codeset and modifier part
|
||||
// strip the codeset and modifier part
|
||||
int32_t length = strlen(langString);
|
||||
{
|
||||
for(int32_t i = 0; i < length; ++i){
|
||||
if(langString[i] == '.' || langString[i] == '@'){
|
||||
for (int32_t i = 0; i < length; ++i)
|
||||
{
|
||||
if (langString[i] == '.' || langString[i] == '@')
|
||||
{
|
||||
length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} //end strip
|
||||
memcpy(pattern, langString, length); //copy all until first '.' or '@'
|
||||
} // end strip
|
||||
memcpy(pattern, langString, length); // copy all until first '.' or '@'
|
||||
pattern[length] = '\0';
|
||||
//find _ if present
|
||||
const char *strip = strchr(pattern, '_');
|
||||
if(strip != nullptr){
|
||||
// find _ if present
|
||||
const char* strip = strchr(pattern, '_');
|
||||
if (strip != nullptr)
|
||||
{
|
||||
// could also use '-', but '?' is more flexible. Maybe LanguagesDescriptors will change.
|
||||
// pattern is now "language?territory"
|
||||
pattern[strip - pattern] = '?';
|
||||
}
|
||||
|
||||
// Iterate through all available languages
|
||||
for(int32_t i = 1; i < LANGUAGE_COUNT; ++i){
|
||||
if(!fnmatch(pattern, LanguagesDescriptors[i].locale, 0)){
|
||||
for (int32_t i = 1; i < LANGUAGE_COUNT; ++i)
|
||||
{
|
||||
if (!fnmatch(pattern, LanguagesDescriptors[i].locale, 0))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
//special cases :(
|
||||
if(!fnmatch(pattern, "en_CA", 0)){
|
||||
// special cases :(
|
||||
if (!fnmatch(pattern, "en_CA", 0))
|
||||
{
|
||||
return LANGUAGE_ENGLISH_US;
|
||||
}
|
||||
else if (!fnmatch(pattern, "zh_CN", 0)){
|
||||
else if (!fnmatch(pattern, "zh_CN", 0))
|
||||
{
|
||||
return LANGUAGE_CHINESE_SIMPLIFIED;
|
||||
}
|
||||
else if (!fnmatch(pattern, "zh_TW", 0)){
|
||||
else if (!fnmatch(pattern, "zh_TW", 0))
|
||||
{
|
||||
return LANGUAGE_CHINESE_TRADITIONAL;
|
||||
}
|
||||
|
||||
//no exact match found trying only language part
|
||||
if(strip != nullptr){
|
||||
// no exact match found trying only language part
|
||||
if (strip != nullptr)
|
||||
{
|
||||
pattern[strip - pattern] = '*';
|
||||
pattern[strip - pattern +1] = '\0'; // pattern is now "language*"
|
||||
for(int32_t i = 1; i < LANGUAGE_COUNT; ++i){
|
||||
if(!fnmatch(pattern, LanguagesDescriptors[i].locale, 0)){
|
||||
pattern[strip - pattern + 1] = '\0'; // pattern is now "language*"
|
||||
for (int32_t i = 1; i < LANGUAGE_COUNT; ++i)
|
||||
{
|
||||
if (!fnmatch(pattern, LanguagesDescriptors[i].locale, 0))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -96,38 +109,43 @@ uint16_t platform_get_locale_language(){
|
|||
return LANGUAGE_ENGLISH_UK;
|
||||
}
|
||||
|
||||
uint8_t platform_get_locale_currency(){
|
||||
char *langstring = setlocale(LC_MONETARY, "");
|
||||
uint8_t platform_get_locale_currency()
|
||||
{
|
||||
char* langstring = setlocale(LC_MONETARY, "");
|
||||
|
||||
if (langstring == nullptr) {
|
||||
if (langstring == nullptr)
|
||||
{
|
||||
return platform_get_currency_value(NULL);
|
||||
}
|
||||
|
||||
struct lconv *lc = localeconv();
|
||||
struct lconv* lc = localeconv();
|
||||
|
||||
return platform_get_currency_value(lc->int_curr_symbol);
|
||||
}
|
||||
|
||||
uint8_t platform_get_locale_measurement_format(){
|
||||
// LC_MEASUREMENT is GNU specific.
|
||||
#ifdef LC_MEASUREMENT
|
||||
const char *langstring = setlocale(LC_MEASUREMENT, "");
|
||||
#else
|
||||
const char *langstring = setlocale(LC_ALL, "");
|
||||
#endif
|
||||
uint8_t platform_get_locale_measurement_format()
|
||||
{
|
||||
// LC_MEASUREMENT is GNU specific.
|
||||
#ifdef LC_MEASUREMENT
|
||||
const char* langstring = setlocale(LC_MEASUREMENT, "");
|
||||
#else
|
||||
const char* langstring = setlocale(LC_ALL, "");
|
||||
#endif
|
||||
|
||||
if(langstring != nullptr){
|
||||
//using https://en.wikipedia.org/wiki/Metrication#Chronology_and_status_of_conversion_by_country as reference
|
||||
if(!fnmatch("*_US*", langstring, 0) || !fnmatch("*_MM*", langstring, 0) || !fnmatch("*_LR*", langstring, 0)){
|
||||
if (langstring != nullptr)
|
||||
{
|
||||
// using https://en.wikipedia.org/wiki/Metrication#Chronology_and_status_of_conversion_by_country as reference
|
||||
if (!fnmatch("*_US*", langstring, 0) || !fnmatch("*_MM*", langstring, 0) || !fnmatch("*_LR*", langstring, 0))
|
||||
{
|
||||
return MEASUREMENT_FORMAT_IMPERIAL;
|
||||
}
|
||||
}
|
||||
return MEASUREMENT_FORMAT_METRIC;
|
||||
}
|
||||
|
||||
bool platform_get_steam_path(utf8 * outPath, size_t outSize)
|
||||
bool platform_get_steam_path(utf8* outPath, size_t outSize)
|
||||
{
|
||||
const char * steamRoot = getenv("STEAMROOT");
|
||||
const char* steamRoot = getenv("STEAMROOT");
|
||||
if (steamRoot != nullptr)
|
||||
{
|
||||
safe_strcpy(outPath, steamRoot, outSize);
|
||||
|
@ -136,7 +154,7 @@ bool platform_get_steam_path(utf8 * outPath, size_t outSize)
|
|||
}
|
||||
|
||||
char steamPath[1024] = { 0 };
|
||||
const char * localSharePath = getenv("XDG_DATA_HOME");
|
||||
const char* localSharePath = getenv("XDG_DATA_HOME");
|
||||
if (localSharePath != nullptr)
|
||||
{
|
||||
safe_strcpy(steamPath, localSharePath, sizeof(steamPath));
|
||||
|
@ -148,7 +166,7 @@ bool platform_get_steam_path(utf8 * outPath, size_t outSize)
|
|||
}
|
||||
}
|
||||
|
||||
const char * homeDir = getpwuid(getuid())->pw_dir;
|
||||
const char* homeDir = getpwuid(getuid())->pw_dir;
|
||||
if (homeDir != nullptr)
|
||||
{
|
||||
safe_strcpy(steamPath, homeDir, sizeof(steamPath));
|
||||
|
@ -172,7 +190,7 @@ bool platform_get_steam_path(utf8 * outPath, size_t outSize)
|
|||
}
|
||||
|
||||
#ifndef NO_TTF
|
||||
bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size)
|
||||
bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size)
|
||||
{
|
||||
assert(buffer != nullptr);
|
||||
assert(font != nullptr);
|
||||
|
@ -186,7 +204,7 @@ bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size)
|
|||
return false;
|
||||
}
|
||||
|
||||
FcPattern* pat = FcNameParse((const FcChar8*) font->font_name);
|
||||
FcPattern* pat = FcNameParse((const FcChar8*)font->font_name);
|
||||
|
||||
FcConfigSubstitute(config, pat, FcMatchPattern);
|
||||
FcDefaultSubstitute(pat);
|
||||
|
@ -205,8 +223,8 @@ bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size)
|
|||
// Western (sans-)serif font. We therefore ignore substitutions FontConfig provides,
|
||||
// and instead rely on exact matches on the fonts predefined for each font family.
|
||||
FcChar8* matched_font_face = nullptr;
|
||||
if (FcPatternGetString(match, FC_FULLNAME, 0, &matched_font_face) == FcResultMatch &&
|
||||
strcmp(font->font_name, (const char *) matched_font_face) != 0)
|
||||
if (FcPatternGetString(match, FC_FULLNAME, 0, &matched_font_face) == FcResultMatch
|
||||
&& strcmp(font->font_name, (const char*)matched_font_face) != 0)
|
||||
{
|
||||
log_verbose("FontConfig provided substitute font %s -- disregarding.", matched_font_face);
|
||||
is_substitute = true;
|
||||
|
@ -216,7 +234,7 @@ bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size)
|
|||
if (!is_substitute && FcPatternGetString(match, FC_FILE, 0, &filename) == FcResultMatch)
|
||||
{
|
||||
found = true;
|
||||
safe_strcpy(buffer, (utf8*) filename, size);
|
||||
safe_strcpy(buffer, (utf8*)filename, size);
|
||||
log_verbose("FontConfig provided font %s", filename);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,13 +19,13 @@ namespace Platform
|
|||
// Android builds currently only read from /sdcard/openrct2*
|
||||
switch (folder)
|
||||
{
|
||||
case SPECIAL_FOLDER::USER_CACHE:
|
||||
case SPECIAL_FOLDER::USER_CONFIG:
|
||||
case SPECIAL_FOLDER::USER_DATA:
|
||||
case SPECIAL_FOLDER::USER_HOME:
|
||||
return "/sdcard";
|
||||
default:
|
||||
return std::string();
|
||||
case SPECIAL_FOLDER::USER_CACHE:
|
||||
case SPECIAL_FOLDER::USER_CONFIG:
|
||||
case SPECIAL_FOLDER::USER_DATA:
|
||||
case SPECIAL_FOLDER::USER_HOME:
|
||||
return "/sdcard";
|
||||
default:
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,6 @@ namespace Platform
|
|||
Guard::Assert(false, "GetCurrentExecutablePath() not implemented for Android.");
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
} // namespace Platform
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,18 +13,18 @@
|
|||
#include <pwd.h>
|
||||
#if defined(__FreeBSD__)
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
#endif // __FreeBSD__
|
||||
#if defined(__linux__)
|
||||
// for PATH_MAX
|
||||
#include <linux/limits.h>
|
||||
#endif // __linux__
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../core/Path.hpp"
|
||||
#include "../core/Util.hpp"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "platform.h"
|
||||
#include "Platform2.h"
|
||||
#include "platform.h"
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
|
@ -32,9 +32,9 @@ namespace Platform
|
|||
{
|
||||
switch (folder)
|
||||
{
|
||||
case SPECIAL_FOLDER::USER_CACHE:
|
||||
case SPECIAL_FOLDER::USER_CONFIG:
|
||||
case SPECIAL_FOLDER::USER_DATA:
|
||||
case SPECIAL_FOLDER::USER_CACHE:
|
||||
case SPECIAL_FOLDER::USER_CONFIG:
|
||||
case SPECIAL_FOLDER::USER_DATA:
|
||||
{
|
||||
auto path = GetEnvironmentPath("XDG_CONFIG_HOME");
|
||||
if (path.empty())
|
||||
|
@ -44,17 +44,16 @@ namespace Platform
|
|||
}
|
||||
return path;
|
||||
}
|
||||
case SPECIAL_FOLDER::USER_HOME:
|
||||
return GetHomePath();
|
||||
default:
|
||||
return std::string();
|
||||
case SPECIAL_FOLDER::USER_HOME:
|
||||
return GetHomePath();
|
||||
default:
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetDocsPath()
|
||||
{
|
||||
static const utf8 * searchLocations[] =
|
||||
{
|
||||
static const utf8* searchLocations[] = {
|
||||
"./doc",
|
||||
"/usr/share/doc/openrct2",
|
||||
};
|
||||
|
@ -71,8 +70,7 @@ namespace Platform
|
|||
|
||||
static std::string FindInstallPath()
|
||||
{
|
||||
static const char * SearchLocations[] =
|
||||
{
|
||||
static const char* SearchLocations[] = {
|
||||
"../share/openrct2",
|
||||
#ifdef ORCT2_RESOURCE_DIR
|
||||
// defined in CMakeLists.txt
|
||||
|
@ -160,10 +158,10 @@ namespace Platform
|
|||
// If you are not using the port or package, you may have to change this line!
|
||||
strlcpy(exePath, "/usr/local/bin/", sizeof(exePath));
|
||||
#else
|
||||
#error "Platform does not support full path exe retrieval"
|
||||
#error "Platform does not support full path exe retrieval"
|
||||
#endif
|
||||
return exePath;
|
||||
}
|
||||
}
|
||||
} // namespace Platform
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,14 +9,15 @@
|
|||
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__)
|
||||
|
||||
#include <cstring>
|
||||
#include <pwd.h>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include "../core/String.hpp"
|
||||
#include "Platform2.h"
|
||||
#include "platform.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <pwd.h>
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
uint32_t GetTicks()
|
||||
|
@ -24,12 +25,12 @@ namespace Platform
|
|||
return platform_get_ticks();
|
||||
}
|
||||
|
||||
std::string GetEnvironmentVariable(const std::string &name)
|
||||
std::string GetEnvironmentVariable(const std::string& name)
|
||||
{
|
||||
return String::ToStd(getenv(name.c_str()));
|
||||
}
|
||||
|
||||
std::string GetEnvironmentPath(const char * name)
|
||||
std::string GetEnvironmentPath(const char* name)
|
||||
{
|
||||
auto value = getenv(name);
|
||||
if (value == nullptr)
|
||||
|
@ -90,14 +91,11 @@ namespace Platform
|
|||
if (!hasChecked)
|
||||
{
|
||||
auto term = GetEnvironmentVariable("TERM");
|
||||
isSupported =
|
||||
term != "cons25" &&
|
||||
term != "dumb" &&
|
||||
term != "emacs";
|
||||
isSupported = term != "cons25" && term != "dumb" && term != "emacs";
|
||||
hasChecked = true;
|
||||
}
|
||||
return isSupported;
|
||||
}
|
||||
}
|
||||
} // namespace Platform
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,22 +13,22 @@
|
|||
#include <windows.h>
|
||||
|
||||
// Then the rest
|
||||
#include <memory>
|
||||
#include <datetimeapi.h>
|
||||
#include <memory>
|
||||
#include <shlobj.h>
|
||||
#undef GetEnvironmentVariable
|
||||
|
||||
#if !defined(__MINGW32__) && ((NTDDI_VERSION >= NTDDI_VISTA) && !defined(_USING_V110_SDK71_) && !defined(_ATL_XP_TARGETING))
|
||||
#define __USE_SHGETKNOWNFOLDERPATH__
|
||||
#define __USE_GETDATEFORMATEX__
|
||||
#define __USE_SHGETKNOWNFOLDERPATH__
|
||||
#define __USE_GETDATEFORMATEX__
|
||||
#else
|
||||
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
||||
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
||||
#endif
|
||||
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../core/Path.hpp"
|
||||
#include "../core/String.hpp"
|
||||
#include "../core/Util.hpp"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "Platform2.h"
|
||||
#include "platform.h"
|
||||
|
||||
|
@ -46,7 +46,7 @@ namespace Platform
|
|||
return platform_get_ticks();
|
||||
}
|
||||
|
||||
std::string GetEnvironmentVariable(const std::string &name)
|
||||
std::string GetEnvironmentVariable(const std::string& name)
|
||||
{
|
||||
std::wstring result;
|
||||
auto wname = String::ToUtf16(name);
|
||||
|
@ -82,10 +82,10 @@ namespace Platform
|
|||
{
|
||||
switch (folder)
|
||||
{
|
||||
// We currently store everything under Documents/OpenRCT2
|
||||
case SPECIAL_FOLDER::USER_CACHE:
|
||||
case SPECIAL_FOLDER::USER_CONFIG:
|
||||
case SPECIAL_FOLDER::USER_DATA:
|
||||
// We currently store everything under Documents/OpenRCT2
|
||||
case SPECIAL_FOLDER::USER_CACHE:
|
||||
case SPECIAL_FOLDER::USER_CONFIG:
|
||||
case SPECIAL_FOLDER::USER_DATA:
|
||||
{
|
||||
#ifdef __USE_SHGETKNOWNFOLDERPATH__
|
||||
auto path = WIN32_GetKnownFolderPath(FOLDERID_Documents);
|
||||
|
@ -98,7 +98,7 @@ namespace Platform
|
|||
}
|
||||
return path;
|
||||
}
|
||||
case SPECIAL_FOLDER::USER_HOME:
|
||||
case SPECIAL_FOLDER::USER_HOME:
|
||||
{
|
||||
#ifdef __USE_SHGETKNOWNFOLDERPATH__
|
||||
auto path = WIN32_GetKnownFolderPath(FOLDERID_Profile);
|
||||
|
@ -115,8 +115,8 @@ namespace Platform
|
|||
}
|
||||
return path;
|
||||
}
|
||||
default:
|
||||
return std::string();
|
||||
default:
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ namespace Platform
|
|||
LONGLONG ll = Int32x32To64(timestamp, 10000000) + 116444736000000000;
|
||||
|
||||
FILETIME ft;
|
||||
ft.dwLowDateTime = (DWORD) ll;
|
||||
ft.dwLowDateTime = (DWORD)ll;
|
||||
ft.dwHighDateTime = ll >> 32;
|
||||
|
||||
SYSTEMTIME st;
|
||||
|
@ -199,7 +199,7 @@ namespace Platform
|
|||
auto hModule = GetModuleHandleA("ntdll.dll");
|
||||
if (hModule != nullptr)
|
||||
{
|
||||
using RtlGetVersionPtr = NTSTATUS(WINAPI *)(PRTL_OSVERSIONINFOW);
|
||||
using RtlGetVersionPtr = NTSTATUS(WINAPI*)(PRTL_OSVERSIONINFOW);
|
||||
auto fn = (RtlGetVersionPtr)GetProcAddress(hModule, "RtlGetVersion");
|
||||
if (fn != nullptr)
|
||||
{
|
||||
|
@ -207,11 +207,9 @@ namespace Platform
|
|||
rovi.dwOSVersionInfoSize = sizeof(rovi);
|
||||
if (fn(&rovi) == 0)
|
||||
{
|
||||
if (rovi.dwMajorVersion > major ||
|
||||
(rovi.dwMajorVersion == major &&
|
||||
(rovi.dwMinorVersion > minor ||
|
||||
(rovi.dwMinorVersion == minor &&
|
||||
rovi.dwBuildNumber >= build))))
|
||||
if (rovi.dwMajorVersion > major
|
||||
|| (rovi.dwMajorVersion == major
|
||||
&& (rovi.dwMinorVersion > minor || (rovi.dwMinorVersion == minor && rovi.dwBuildNumber >= build))))
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
|
@ -265,11 +263,11 @@ namespace Platform
|
|||
return isSupported;
|
||||
}
|
||||
|
||||
#ifdef __USE_SHGETKNOWNFOLDERPATH__
|
||||
#ifdef __USE_SHGETKNOWNFOLDERPATH__
|
||||
static std::string WIN32_GetKnownFolderPath(REFKNOWNFOLDERID rfid)
|
||||
{
|
||||
std::string path;
|
||||
wchar_t * wpath = nullptr;
|
||||
wchar_t* wpath = nullptr;
|
||||
if (SUCCEEDED(SHGetKnownFolderPath(rfid, KF_FLAG_CREATE, nullptr, &wpath)))
|
||||
{
|
||||
path = String::ToUtf8(std::wstring(wpath));
|
||||
|
@ -300,8 +298,7 @@ namespace Platform
|
|||
wExePathCapacity *= 2;
|
||||
wExePath = std::make_unique<wchar_t[]>(wExePathCapacity);
|
||||
size = GetModuleFileNameW(hModule, wExePath.get(), wExePathCapacity);
|
||||
}
|
||||
while (size >= wExePathCapacity);
|
||||
} while (size >= wExePathCapacity);
|
||||
return String::ToUtf8(wExePath.get());
|
||||
}
|
||||
} // namespace Platform
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
|
||||
#include "../core/Path.hpp"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../core/Path.hpp"
|
||||
#include "Platform2.h"
|
||||
|
||||
// undefine `interface` and `abstract`, because it's causing conflicts with Objective-C's keywords
|
||||
|
@ -27,17 +27,17 @@ namespace Platform
|
|||
// macOS stores everything in ~/Library/Application Support/OpenRCT2
|
||||
switch (folder)
|
||||
{
|
||||
case SPECIAL_FOLDER::USER_CACHE:
|
||||
case SPECIAL_FOLDER::USER_CONFIG:
|
||||
case SPECIAL_FOLDER::USER_DATA:
|
||||
case SPECIAL_FOLDER::USER_CACHE:
|
||||
case SPECIAL_FOLDER::USER_CONFIG:
|
||||
case SPECIAL_FOLDER::USER_DATA:
|
||||
{
|
||||
auto home = GetFolderPath(SPECIAL_FOLDER::USER_HOME);
|
||||
return Path::Combine(home, "Library/Application Support");
|
||||
}
|
||||
case SPECIAL_FOLDER::USER_HOME:
|
||||
return GetHomePath();
|
||||
default:
|
||||
return std::string();
|
||||
case SPECIAL_FOLDER::USER_HOME:
|
||||
return GetHomePath();
|
||||
default:
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,9 +48,8 @@ namespace Platform
|
|||
|
||||
static std::string GetBundlePath()
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
NSBundle * bundle = [NSBundle mainBundle];
|
||||
@autoreleasepool {
|
||||
NSBundle* bundle = [NSBundle mainBundle];
|
||||
if (bundle)
|
||||
{
|
||||
auto resources = bundle.resourcePath.UTF8String;
|
||||
|
@ -75,7 +74,7 @@ namespace Platform
|
|||
auto exePath = GetCurrentExecutablePath();
|
||||
auto exeDirectory = Path::GetDirectory(exePath);
|
||||
path = Path::Combine(exeDirectory, "data");
|
||||
NSString * nsPath = [NSString stringWithUTF8String:path.c_str()];
|
||||
NSString* nsPath = [NSString stringWithUTF8String:path.c_str()];
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:nsPath])
|
||||
{
|
||||
path = GetBundlePath();
|
||||
|
|
|
@ -9,9 +9,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
#include "../common.h"
|
||||
|
||||
enum class SPECIAL_FOLDER
|
||||
{
|
||||
|
@ -24,14 +25,14 @@ enum class SPECIAL_FOLDER
|
|||
namespace Platform
|
||||
{
|
||||
uint32_t GetTicks();
|
||||
std::string GetEnvironmentVariable(const std::string &name);
|
||||
std::string GetEnvironmentVariable(const std::string& name);
|
||||
std::string GetFolderPath(SPECIAL_FOLDER folder);
|
||||
std::string GetInstallPath();
|
||||
std::string GetDocsPath();
|
||||
std::string GetCurrentExecutablePath();
|
||||
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__)
|
||||
std::string GetEnvironmentPath(const char * name);
|
||||
std::string GetEnvironmentPath(const char* name);
|
||||
std::string GetHomePath();
|
||||
#endif
|
||||
|
||||
|
|
|
@ -16,8 +16,15 @@
|
|||
#include <fcntl.h>
|
||||
#include <fnmatch.h>
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#include <fts.h>
|
||||
#include <fts.h>
|
||||
#endif
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../config/Config.h"
|
||||
#include "../localisation/Date.h"
|
||||
#include "../localisation/Language.h"
|
||||
#include "../util/Util.h"
|
||||
#include "platform.h"
|
||||
|
||||
#include <libgen.h>
|
||||
#include <locale.h>
|
||||
#include <pwd.h>
|
||||
|
@ -27,12 +34,6 @@
|
|||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include "../config/Config.h"
|
||||
#include "../localisation/Date.h"
|
||||
#include "../localisation/Language.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../util/Util.h"
|
||||
#include "platform.h"
|
||||
// The name of the mutex used to prevent multiple instances of the game from running
|
||||
#define SINGLE_INSTANCE_MUTEX_NAME "openrct2.lock"
|
||||
|
||||
|
@ -40,11 +41,11 @@
|
|||
|
||||
static utf8 _userDataDirectoryPath[MAX_PATH] = { 0 };
|
||||
|
||||
void platform_get_date_utc(rct2_date *out_date)
|
||||
void platform_get_date_utc(rct2_date* out_date)
|
||||
{
|
||||
assert(out_date != nullptr);
|
||||
time_t rawtime;
|
||||
struct tm * timeinfo;
|
||||
struct tm* timeinfo;
|
||||
time(&rawtime);
|
||||
timeinfo = gmtime(&rawtime);
|
||||
out_date->day = timeinfo->tm_mday;
|
||||
|
@ -53,11 +54,11 @@ void platform_get_date_utc(rct2_date *out_date)
|
|||
out_date->day_of_week = timeinfo->tm_wday;
|
||||
}
|
||||
|
||||
void platform_get_time_utc(rct2_time *out_time)
|
||||
void platform_get_time_utc(rct2_time* out_time)
|
||||
{
|
||||
assert(out_time != nullptr);
|
||||
time_t rawtime;
|
||||
struct tm * timeinfo;
|
||||
struct tm* timeinfo;
|
||||
time(&rawtime);
|
||||
timeinfo = gmtime(&rawtime);
|
||||
out_time->second = timeinfo->tm_sec;
|
||||
|
@ -65,11 +66,11 @@ void platform_get_time_utc(rct2_time *out_time)
|
|||
out_time->hour = timeinfo->tm_hour;
|
||||
}
|
||||
|
||||
void platform_get_date_local(rct2_date *out_date)
|
||||
void platform_get_date_local(rct2_date* out_date)
|
||||
{
|
||||
assert(out_date != nullptr);
|
||||
time_t rawtime;
|
||||
struct tm * timeinfo;
|
||||
struct tm* timeinfo;
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
out_date->day = timeinfo->tm_mday;
|
||||
|
@ -78,11 +79,11 @@ void platform_get_date_local(rct2_date *out_date)
|
|||
out_date->day_of_week = timeinfo->tm_wday;
|
||||
}
|
||||
|
||||
void platform_get_time_local(rct2_time *out_time)
|
||||
void platform_get_time_local(rct2_time* out_time)
|
||||
{
|
||||
assert(out_time != nullptr);
|
||||
time_t rawtime;
|
||||
struct tm * timeinfo;
|
||||
struct tm* timeinfo;
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
out_time->second = timeinfo->tm_sec;
|
||||
|
@ -90,13 +91,14 @@ void platform_get_time_local(rct2_time *out_time)
|
|||
out_time->hour = timeinfo->tm_hour;
|
||||
}
|
||||
|
||||
static size_t platform_utf8_to_multibyte(const utf8 *path, char *buffer, size_t buffer_size)
|
||||
static size_t platform_utf8_to_multibyte(const utf8* path, char* buffer, size_t buffer_size)
|
||||
{
|
||||
wchar_t *wpath = utf8_to_widechar(path);
|
||||
wchar_t* wpath = utf8_to_widechar(path);
|
||||
setlocale(LC_CTYPE, "UTF-8");
|
||||
size_t len = wcstombs(NULL, wpath, 0);
|
||||
bool truncated = false;
|
||||
if (len > buffer_size - 1) {
|
||||
if (len > buffer_size - 1)
|
||||
{
|
||||
truncated = true;
|
||||
len = buffer_size - 1;
|
||||
}
|
||||
|
@ -108,7 +110,7 @@ static size_t platform_utf8_to_multibyte(const utf8 *path, char *buffer, size_t
|
|||
return len;
|
||||
}
|
||||
|
||||
bool platform_file_exists(const utf8 *path)
|
||||
bool platform_file_exists(const utf8* path)
|
||||
{
|
||||
char buffer[MAX_PATH];
|
||||
platform_utf8_to_multibyte(path, buffer, MAX_PATH);
|
||||
|
@ -117,7 +119,7 @@ bool platform_file_exists(const utf8 *path)
|
|||
return exists;
|
||||
}
|
||||
|
||||
bool platform_directory_exists(const utf8 *path)
|
||||
bool platform_directory_exists(const utf8* path)
|
||||
{
|
||||
char buffer[MAX_PATH];
|
||||
platform_utf8_to_multibyte(path, buffer, MAX_PATH);
|
||||
|
@ -131,7 +133,7 @@ bool platform_directory_exists(const utf8 *path)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool platform_original_game_data_exists(const utf8 *path)
|
||||
bool platform_original_game_data_exists(const utf8* path)
|
||||
{
|
||||
char buffer[MAX_PATH];
|
||||
platform_utf8_to_multibyte(path, buffer, MAX_PATH);
|
||||
|
@ -151,21 +153,25 @@ static mode_t openrct2_getumask()
|
|||
return 0777 & ~mask; // Keep in mind 0777 is octal
|
||||
}
|
||||
|
||||
bool platform_ensure_directory_exists(const utf8 *path)
|
||||
bool platform_ensure_directory_exists(const utf8* path)
|
||||
{
|
||||
mode_t mask = openrct2_getumask();
|
||||
char buffer[MAX_PATH];
|
||||
platform_utf8_to_multibyte(path, buffer, MAX_PATH);
|
||||
|
||||
log_verbose("Create directory: %s", buffer);
|
||||
for (char *p = buffer + 1; *p != '\0'; p++) {
|
||||
if (*p == '/') {
|
||||
for (char* p = buffer + 1; *p != '\0'; p++)
|
||||
{
|
||||
if (*p == '/')
|
||||
{
|
||||
// Temporarily truncate
|
||||
*p = '\0';
|
||||
|
||||
log_verbose("mkdir(%s)", buffer);
|
||||
if (mkdir(buffer, mask) != 0) {
|
||||
if (errno != EEXIST) {
|
||||
if (mkdir(buffer, mask) != 0)
|
||||
{
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -176,8 +182,10 @@ bool platform_ensure_directory_exists(const utf8 *path)
|
|||
}
|
||||
|
||||
log_verbose("mkdir(%s)", buffer);
|
||||
if (mkdir(buffer, mask) != 0) {
|
||||
if (errno != EEXIST) {
|
||||
if (mkdir(buffer, mask) != 0)
|
||||
{
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -185,26 +193,28 @@ bool platform_ensure_directory_exists(const utf8 *path)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool platform_directory_delete(const utf8 *path)
|
||||
bool platform_directory_delete(const utf8* path)
|
||||
{
|
||||
#ifdef _FTS_H
|
||||
log_verbose("Recursively deleting directory %s", path);
|
||||
|
||||
FTS *ftsp;
|
||||
FTS* ftsp;
|
||||
FTSENT *p, *chp;
|
||||
|
||||
// fts_open only accepts non const paths, so we have to take a copy
|
||||
char* ourPath = _strdup(path);
|
||||
|
||||
utf8* const patharray[2] = {ourPath, NULL};
|
||||
if ((ftsp = fts_open(patharray, FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR, NULL)) == nullptr) {
|
||||
utf8* const patharray[2] = { ourPath, NULL };
|
||||
if ((ftsp = fts_open(patharray, FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR, NULL)) == nullptr)
|
||||
{
|
||||
log_error("fts_open returned NULL");
|
||||
free(ourPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
chp = fts_children(ftsp, 0);
|
||||
if (chp == nullptr) {
|
||||
if (chp == nullptr)
|
||||
{
|
||||
log_verbose("No files to traverse, deleting directory %s", path);
|
||||
if (remove(path) != 0)
|
||||
{
|
||||
|
@ -214,13 +224,16 @@ bool platform_directory_delete(const utf8 *path)
|
|||
return true; // No files to traverse
|
||||
}
|
||||
|
||||
while ((p = fts_read(ftsp)) != nullptr) {
|
||||
switch (p->fts_info) {
|
||||
while ((p = fts_read(ftsp)) != nullptr)
|
||||
{
|
||||
switch (p->fts_info)
|
||||
{
|
||||
case FTS_DP: // Directory postorder, which means
|
||||
// the directory is empty
|
||||
|
||||
case FTS_F: // File
|
||||
if(remove(p->fts_path)) {
|
||||
case FTS_F: // File
|
||||
if (remove(p->fts_path))
|
||||
{
|
||||
log_error("Could not remove %s", p->fts_path);
|
||||
fts_close(ftsp);
|
||||
free(ourPath);
|
||||
|
@ -244,7 +257,7 @@ bool platform_directory_delete(const utf8 *path)
|
|||
return true;
|
||||
}
|
||||
|
||||
utf8 * platform_get_absolute_path(const utf8 * relative_path, const utf8 * base_path)
|
||||
utf8* platform_get_absolute_path(const utf8* relative_path, const utf8* base_path)
|
||||
{
|
||||
utf8 path[MAX_PATH];
|
||||
|
||||
|
@ -256,10 +269,9 @@ utf8 * platform_get_absolute_path(const utf8 * relative_path, const utf8 * base_
|
|||
{
|
||||
safe_strcpy(path, base_path, MAX_PATH);
|
||||
}
|
||||
return realpath(path,NULL);
|
||||
return realpath(path, NULL);
|
||||
}
|
||||
|
||||
|
||||
bool platform_lock_single_instance()
|
||||
{
|
||||
char pidFilePath[MAX_PATH];
|
||||
|
@ -273,11 +285,12 @@ bool platform_lock_single_instance()
|
|||
// This is intentional.
|
||||
int32_t pidFile = open(pidFilePath, O_CREAT | O_RDWR, 0666);
|
||||
|
||||
if (pidFile == -1) {
|
||||
if (pidFile == -1)
|
||||
{
|
||||
log_warning("Cannot open lock file for writing.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
struct flock lock;
|
||||
|
||||
lock.l_start = 0;
|
||||
|
@ -285,9 +298,10 @@ bool platform_lock_single_instance()
|
|||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
|
||||
if (fcntl(pidFile, F_SETLK, &lock) == -1)
|
||||
if (fcntl(pidFile, F_SETLK, &lock) == -1)
|
||||
{
|
||||
if (errno == EWOULDBLOCK) {
|
||||
if (errno == EWOULDBLOCK)
|
||||
{
|
||||
log_warning("Another OpenRCT2 session has been found running.");
|
||||
return false;
|
||||
}
|
||||
|
@ -297,26 +311,32 @@ bool platform_lock_single_instance()
|
|||
return true;
|
||||
}
|
||||
|
||||
int32_t platform_get_drives() {
|
||||
int32_t platform_get_drives()
|
||||
{
|
||||
// POSIX systems do not know drives. Return 0.
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool platform_file_copy(const utf8 *srcPath, const utf8 *dstPath, bool overwrite)
|
||||
bool platform_file_copy(const utf8* srcPath, const utf8* dstPath, bool overwrite)
|
||||
{
|
||||
log_verbose("Copying %s to %s", srcPath, dstPath);
|
||||
|
||||
FILE *dstFile;
|
||||
FILE* dstFile;
|
||||
|
||||
if (overwrite) {
|
||||
if (overwrite)
|
||||
{
|
||||
dstFile = fopen(dstPath, "wb");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Portability note: check your libc's support for "wbx"
|
||||
dstFile = fopen(dstPath, "wbx");
|
||||
}
|
||||
|
||||
if (dstFile == nullptr) {
|
||||
if (errno == EEXIST) {
|
||||
if (dstFile == nullptr)
|
||||
{
|
||||
if (errno == EEXIST)
|
||||
{
|
||||
log_warning("platform_file_copy: Not overwriting %s, because overwrite flag == false", dstPath);
|
||||
return false;
|
||||
}
|
||||
|
@ -326,8 +346,9 @@ bool platform_file_copy(const utf8 *srcPath, const utf8 *dstPath, bool overwrite
|
|||
}
|
||||
|
||||
// Open both files and check whether they are opened correctly
|
||||
FILE *srcFile = fopen(srcPath, "rb");
|
||||
if (srcFile == nullptr) {
|
||||
FILE* srcFile = fopen(srcPath, "rb");
|
||||
if (srcFile == nullptr)
|
||||
{
|
||||
fclose(dstFile);
|
||||
log_error("Could not open source file %s for copying", srcPath);
|
||||
return false;
|
||||
|
@ -337,8 +358,9 @@ bool platform_file_copy(const utf8 *srcPath, const utf8 *dstPath, bool overwrite
|
|||
size_t file_offset = 0;
|
||||
|
||||
// Copy file in FILE_BUFFER_SIZE-d chunks
|
||||
char* buffer = (char*) malloc(FILE_BUFFER_SIZE);
|
||||
while ((amount_read = fread(buffer, FILE_BUFFER_SIZE, 1, srcFile))) {
|
||||
char* buffer = (char*)malloc(FILE_BUFFER_SIZE);
|
||||
while ((amount_read = fread(buffer, FILE_BUFFER_SIZE, 1, srcFile)))
|
||||
{
|
||||
fwrite(buffer, amount_read, 1, dstFile);
|
||||
file_offset += amount_read;
|
||||
}
|
||||
|
@ -356,38 +378,40 @@ bool platform_file_copy(const utf8 *srcPath, const utf8 *dstPath, bool overwrite
|
|||
return true;
|
||||
}
|
||||
|
||||
bool platform_file_move(const utf8 *srcPath, const utf8 *dstPath)
|
||||
bool platform_file_move(const utf8* srcPath, const utf8* dstPath)
|
||||
{
|
||||
return rename(srcPath, dstPath) == 0;
|
||||
}
|
||||
|
||||
bool platform_file_delete(const utf8 *path)
|
||||
bool platform_file_delete(const utf8* path)
|
||||
{
|
||||
int32_t ret = unlink(path);
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
time_t platform_file_get_modified_time(const utf8* path){
|
||||
time_t platform_file_get_modified_time(const utf8* path)
|
||||
{
|
||||
struct stat buf;
|
||||
if (stat(path, &buf) == 0) {
|
||||
if (stat(path, &buf) == 0)
|
||||
{
|
||||
return buf.st_mtime;
|
||||
}
|
||||
return 100;
|
||||
}
|
||||
|
||||
uint8_t platform_get_locale_temperature_format(){
|
||||
uint8_t platform_get_locale_temperature_format()
|
||||
{
|
||||
// LC_MEASUREMENT is GNU specific.
|
||||
#ifdef LC_MEASUREMENT
|
||||
const char *langstring = setlocale(LC_MEASUREMENT, "");
|
||||
const char* langstring = setlocale(LC_MEASUREMENT, "");
|
||||
#else
|
||||
const char *langstring = setlocale(LC_ALL, "");
|
||||
const char* langstring = setlocale(LC_ALL, "");
|
||||
#endif
|
||||
|
||||
if(langstring != nullptr){
|
||||
if (!fnmatch("*_US*", langstring, 0) ||
|
||||
!fnmatch("*_BS*", langstring, 0) ||
|
||||
!fnmatch("*_BZ*", langstring, 0) ||
|
||||
!fnmatch("*_PW*", langstring, 0))
|
||||
if (langstring != nullptr)
|
||||
{
|
||||
if (!fnmatch("*_US*", langstring, 0) || !fnmatch("*_BS*", langstring, 0) || !fnmatch("*_BZ*", langstring, 0)
|
||||
|| !fnmatch("*_PW*", langstring, 0))
|
||||
{
|
||||
return TEMPERATURE_FORMAT_F;
|
||||
}
|
||||
|
@ -414,12 +438,16 @@ datetime64 platform_get_datetime_now_utc()
|
|||
return utcNow;
|
||||
}
|
||||
|
||||
utf8* platform_get_username() {
|
||||
utf8* platform_get_username()
|
||||
{
|
||||
struct passwd* pw = getpwuid(getuid());
|
||||
|
||||
if (pw) {
|
||||
if (pw)
|
||||
{
|
||||
return pw->pw_name;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -427,9 +455,9 @@ utf8* platform_get_username() {
|
|||
bool platform_process_is_elevated()
|
||||
{
|
||||
#ifndef __EMSCRIPTEN__
|
||||
return (geteuid() == 0);
|
||||
return (geteuid() == 0);
|
||||
#else
|
||||
return false;
|
||||
return false;
|
||||
#endif // __EMSCRIPTEN__
|
||||
}
|
||||
|
||||
|
|
|
@ -10,65 +10,69 @@
|
|||
#include "../common.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "../Context.h"
|
||||
#include "../Game.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../config/Config.h"
|
||||
#include "../drawing/Drawing.h"
|
||||
#include "../drawing/LightFX.h"
|
||||
#include "../Game.h"
|
||||
#include "../localisation/Currency.h"
|
||||
#include "../localisation/Localisation.h"
|
||||
#include "../util/Util.h"
|
||||
#include "../world/Climate.h"
|
||||
#include "platform.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <mach/mach_time.h>
|
||||
#include <AvailabilityMacros.h>
|
||||
#ifndef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
||||
#error Missing __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ define
|
||||
#endif
|
||||
#include <AvailabilityMacros.h>
|
||||
#include <mach/mach_time.h>
|
||||
#ifndef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
||||
#error Missing __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ define
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200)
|
||||
static mach_timebase_info_data_t _mach_base_info = {};
|
||||
static mach_timebase_info_data_t _mach_base_info = {};
|
||||
#endif
|
||||
|
||||
#if !((defined (_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700) || (defined(__APPLE__) && defined(__MACH__)))
|
||||
char * strndup(const char * src, size_t size)
|
||||
#if !( \
|
||||
(defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700) \
|
||||
|| (defined(__APPLE__) && defined(__MACH__)))
|
||||
char* strndup(const char* src, size_t size)
|
||||
{
|
||||
size_t len = strnlen(src, size);
|
||||
char * dst = (char *)malloc(len + 1);
|
||||
char* dst = (char*)malloc(len + 1);
|
||||
|
||||
if (dst == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
dst = (char *)memcpy(dst, src, len);
|
||||
dst = (char*)memcpy(dst, src, len);
|
||||
dst[len] = '\0';
|
||||
return dst;
|
||||
}
|
||||
#endif // !((defined (_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700) || (defined(__APPLE__) && defined(__MACH__)))
|
||||
#endif // !((defined (_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700) ||
|
||||
// (defined(__APPLE__) && defined(__MACH__)))
|
||||
|
||||
#ifdef _WIN32
|
||||
static uint32_t _frequency = 0;
|
||||
static uint32_t _frequency = 0;
|
||||
static LARGE_INTEGER _entryTimestamp;
|
||||
#endif
|
||||
|
||||
using update_palette_func = void (*)(const uint8_t *, int32_t, int32_t);
|
||||
using update_palette_func = void (*)(const uint8_t*, int32_t, int32_t);
|
||||
|
||||
rct_palette_entry gPalette[256];
|
||||
|
||||
void platform_update_palette(const uint8_t * colours, int32_t start_index, int32_t num_colours)
|
||||
void platform_update_palette(const uint8_t* colours, int32_t start_index, int32_t num_colours)
|
||||
{
|
||||
colours += start_index * 4;
|
||||
|
||||
|
@ -95,18 +99,18 @@ void platform_update_palette(const uint8_t * colours, int32_t start_index, int32
|
|||
}
|
||||
}
|
||||
|
||||
gPalette[i].red = r;
|
||||
gPalette[i].red = r;
|
||||
gPalette[i].green = g;
|
||||
gPalette[i].blue = b;
|
||||
gPalette[i].blue = b;
|
||||
gPalette[i].alpha = 0;
|
||||
colours += 4;
|
||||
}
|
||||
|
||||
// Fix #1749 and #6535: rainbow path, donut shop and pause button contain black spots that should be white.
|
||||
gPalette[255].alpha = 0;
|
||||
gPalette[255].red = 255;
|
||||
gPalette[255].red = 255;
|
||||
gPalette[255].green = 255;
|
||||
gPalette[255].blue = 255;
|
||||
gPalette[255].blue = 255;
|
||||
|
||||
if (!gOpenRCT2Headless)
|
||||
{
|
||||
|
@ -181,7 +185,7 @@ void platform_sleep(uint32_t ms)
|
|||
#endif
|
||||
}
|
||||
|
||||
uint8_t platform_get_currency_value(const char * currCode)
|
||||
uint8_t platform_get_currency_value(const char* currCode)
|
||||
{
|
||||
if (currCode == nullptr || strlen(currCode) < 3)
|
||||
{
|
||||
|
|
|
@ -19,26 +19,28 @@
|
|||
#include <windows.h>
|
||||
|
||||
// Then the rest
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../Version.h"
|
||||
#include "../config/Config.h"
|
||||
#include "../core/Util.hpp"
|
||||
#include "../localisation/Date.h"
|
||||
#include "../localisation/Language.h"
|
||||
#include "../rct2/RCT2.h"
|
||||
#include "../util/Util.h"
|
||||
#include "platform.h"
|
||||
|
||||
#include <lmcons.h>
|
||||
#include <psapi.h>
|
||||
#include <shlobj.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "../config/Config.h"
|
||||
#include "../core/Util.hpp"
|
||||
#include "../localisation/Date.h"
|
||||
#include "../localisation/Language.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../rct2/RCT2.h"
|
||||
#include "../util/Util.h"
|
||||
#include "../Version.h"
|
||||
#include "platform.h"
|
||||
|
||||
// Native resource IDs
|
||||
#include "../../../resources/resource.h"
|
||||
|
||||
// Enable visual styles
|
||||
#pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
#pragma comment( \
|
||||
linker, \
|
||||
"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
|
||||
// The name of the mutex used to prevent multiple instances of the game from running
|
||||
#define SINGLE_INSTANCE_MUTEX_NAME "RollerCoaster Tycoon 2_GSKMUTEX"
|
||||
|
@ -49,13 +51,14 @@ static HMODULE _dllModule = nullptr;
|
|||
|
||||
static HMODULE plaform_get_dll_module()
|
||||
{
|
||||
if (_dllModule == nullptr) {
|
||||
if (_dllModule == nullptr)
|
||||
{
|
||||
_dllModule = GetModuleHandle(NULL);
|
||||
}
|
||||
return _dllModule;
|
||||
}
|
||||
|
||||
void platform_get_date_local(rct2_date *out_date)
|
||||
void platform_get_date_local(rct2_date* out_date)
|
||||
{
|
||||
assert(out_date != nullptr);
|
||||
SYSTEMTIME systime;
|
||||
|
@ -67,7 +70,7 @@ void platform_get_date_local(rct2_date *out_date)
|
|||
out_date->day_of_week = systime.wDayOfWeek;
|
||||
}
|
||||
|
||||
void platform_get_time_local(rct2_time *out_time)
|
||||
void platform_get_time_local(rct2_time* out_time)
|
||||
{
|
||||
assert(out_time != nullptr);
|
||||
SYSTEMTIME systime;
|
||||
|
@ -77,24 +80,24 @@ void platform_get_time_local(rct2_time *out_time)
|
|||
out_time->second = systime.wSecond;
|
||||
}
|
||||
|
||||
bool platform_file_exists(const utf8 *path)
|
||||
bool platform_file_exists(const utf8* path)
|
||||
{
|
||||
wchar_t *wPath = utf8_to_widechar(path);
|
||||
wchar_t* wPath = utf8_to_widechar(path);
|
||||
DWORD result = GetFileAttributesW(wPath);
|
||||
DWORD error = GetLastError();
|
||||
free(wPath);
|
||||
return !(result == INVALID_FILE_ATTRIBUTES && (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND));
|
||||
}
|
||||
|
||||
bool platform_directory_exists(const utf8 *path)
|
||||
bool platform_directory_exists(const utf8* path)
|
||||
{
|
||||
wchar_t *wPath = utf8_to_widechar(path);
|
||||
wchar_t* wPath = utf8_to_widechar(path);
|
||||
DWORD dwAttrib = GetFileAttributesW(wPath);
|
||||
free(wPath);
|
||||
return dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
|
||||
}
|
||||
|
||||
bool platform_original_game_data_exists(const utf8 *path)
|
||||
bool platform_original_game_data_exists(const utf8* path)
|
||||
{
|
||||
utf8 checkPath[MAX_PATH];
|
||||
safe_strcpy(checkPath, path, MAX_PATH);
|
||||
|
@ -103,22 +106,22 @@ bool platform_original_game_data_exists(const utf8 *path)
|
|||
return platform_file_exists(checkPath);
|
||||
}
|
||||
|
||||
bool platform_ensure_directory_exists(const utf8 *path)
|
||||
bool platform_ensure_directory_exists(const utf8* path)
|
||||
{
|
||||
if (platform_directory_exists(path))
|
||||
return 1;
|
||||
|
||||
wchar_t *wPath = utf8_to_widechar(path);
|
||||
wchar_t* wPath = utf8_to_widechar(path);
|
||||
BOOL success = CreateDirectoryW(wPath, NULL);
|
||||
free(wPath);
|
||||
return success == TRUE;
|
||||
}
|
||||
|
||||
bool platform_directory_delete(const utf8 *path)
|
||||
bool platform_directory_delete(const utf8* path)
|
||||
{
|
||||
wchar_t pszFrom[MAX_PATH];
|
||||
|
||||
wchar_t *wPath = utf8_to_widechar(path);
|
||||
wchar_t* wPath = utf8_to_widechar(path);
|
||||
wcsncpy(pszFrom, wPath, MAX_PATH);
|
||||
|
||||
// Needs to be double-null terminated for some weird reason
|
||||
|
@ -126,15 +129,15 @@ bool platform_directory_delete(const utf8 *path)
|
|||
free(wPath);
|
||||
|
||||
SHFILEOPSTRUCTW fileop;
|
||||
fileop.hwnd = nullptr; // no status display
|
||||
fileop.wFunc = FO_DELETE; // delete operation
|
||||
fileop.pFrom = pszFrom; // source file name as double null terminated string
|
||||
fileop.pTo = nullptr; // no destination needed
|
||||
fileop.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; // do not prompt the user
|
||||
fileop.hwnd = nullptr; // no status display
|
||||
fileop.wFunc = FO_DELETE; // delete operation
|
||||
fileop.pFrom = pszFrom; // source file name as double null terminated string
|
||||
fileop.pTo = nullptr; // no destination needed
|
||||
fileop.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; // do not prompt the user
|
||||
|
||||
fileop.fAnyOperationsAborted = FALSE;
|
||||
fileop.lpszProgressTitle = nullptr;
|
||||
fileop.hNameMappings = nullptr;
|
||||
fileop.lpszProgressTitle = nullptr;
|
||||
fileop.hNameMappings = nullptr;
|
||||
|
||||
int32_t ret = SHFileOperationW(&fileop);
|
||||
return (ret == 0);
|
||||
|
@ -146,14 +149,17 @@ bool platform_lock_single_instance()
|
|||
|
||||
// Check if operating system mutex exists
|
||||
mutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, SINGLE_INSTANCE_MUTEX_NAME);
|
||||
if (mutex == nullptr) {
|
||||
if (mutex == nullptr)
|
||||
{
|
||||
// Create new mutex
|
||||
status = CreateMutex(NULL, FALSE, SINGLE_INSTANCE_MUTEX_NAME);
|
||||
if (status == nullptr)
|
||||
log_error("unable to create mutex\n");
|
||||
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Already running
|
||||
CloseHandle(mutex);
|
||||
return false;
|
||||
|
@ -165,37 +171,37 @@ int32_t platform_get_drives()
|
|||
return GetLogicalDrives();
|
||||
}
|
||||
|
||||
bool platform_file_copy(const utf8 *srcPath, const utf8 *dstPath, bool overwrite)
|
||||
bool platform_file_copy(const utf8* srcPath, const utf8* dstPath, bool overwrite)
|
||||
{
|
||||
wchar_t *wSrcPath = utf8_to_widechar(srcPath);
|
||||
wchar_t *wDstPath = utf8_to_widechar(dstPath);
|
||||
wchar_t* wSrcPath = utf8_to_widechar(srcPath);
|
||||
wchar_t* wDstPath = utf8_to_widechar(dstPath);
|
||||
BOOL success = CopyFileW(wSrcPath, wDstPath, overwrite ? FALSE : TRUE);
|
||||
free(wSrcPath);
|
||||
free(wDstPath);
|
||||
return success == TRUE;
|
||||
}
|
||||
|
||||
bool platform_file_move(const utf8 *srcPath, const utf8 *dstPath)
|
||||
bool platform_file_move(const utf8* srcPath, const utf8* dstPath)
|
||||
{
|
||||
wchar_t *wSrcPath = utf8_to_widechar(srcPath);
|
||||
wchar_t *wDstPath = utf8_to_widechar(dstPath);
|
||||
wchar_t* wSrcPath = utf8_to_widechar(srcPath);
|
||||
wchar_t* wDstPath = utf8_to_widechar(dstPath);
|
||||
BOOL success = MoveFileW(wSrcPath, wDstPath);
|
||||
free(wSrcPath);
|
||||
free(wDstPath);
|
||||
return success == TRUE;
|
||||
}
|
||||
|
||||
bool platform_file_delete(const utf8 *path)
|
||||
bool platform_file_delete(const utf8* path)
|
||||
{
|
||||
wchar_t *wPath = utf8_to_widechar(path);
|
||||
wchar_t* wPath = utf8_to_widechar(path);
|
||||
BOOL success = DeleteFileW(wPath);
|
||||
free(wPath);
|
||||
return success == TRUE;
|
||||
}
|
||||
|
||||
bool platform_get_steam_path(utf8 * outPath, size_t outSize)
|
||||
bool platform_get_steam_path(utf8* outPath, size_t outSize)
|
||||
{
|
||||
wchar_t * wSteamPath;
|
||||
wchar_t* wSteamPath;
|
||||
HKEY hKey;
|
||||
DWORD type, size;
|
||||
LRESULT result;
|
||||
|
@ -214,7 +220,7 @@ bool platform_get_steam_path(utf8 * outPath, size_t outSize)
|
|||
result = RegQueryValueExW(hKey, L"SteamPath", 0, &type, (LPBYTE)wSteamPath, &size);
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
utf8 * utf8SteamPath = widechar_to_utf8(wSteamPath);
|
||||
utf8* utf8SteamPath = widechar_to_utf8(wSteamPath);
|
||||
safe_strcpy(outPath, utf8SteamPath, outSize);
|
||||
safe_strcat_path(outPath, "steamapps\\common", outSize);
|
||||
free(utf8SteamPath);
|
||||
|
@ -233,50 +239,61 @@ uint16_t platform_get_locale_language()
|
|||
{
|
||||
CHAR langCode[4];
|
||||
|
||||
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
|
||||
LOCALE_SABBREVLANGNAME,
|
||||
(LPSTR)&langCode,
|
||||
sizeof(langCode)) == 0){
|
||||
if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVLANGNAME, (LPSTR)&langCode, sizeof(langCode)) == 0)
|
||||
{
|
||||
return LANGUAGE_UNDEFINED;
|
||||
}
|
||||
|
||||
if (strcmp(langCode, "ENG") == 0){
|
||||
if (strcmp(langCode, "ENG") == 0)
|
||||
{
|
||||
return LANGUAGE_ENGLISH_UK;
|
||||
}
|
||||
else if (strcmp(langCode, "ENU") == 0){
|
||||
else if (strcmp(langCode, "ENU") == 0)
|
||||
{
|
||||
return LANGUAGE_ENGLISH_US;
|
||||
}
|
||||
else if (strcmp(langCode, "DEU") == 0){
|
||||
else if (strcmp(langCode, "DEU") == 0)
|
||||
{
|
||||
return LANGUAGE_GERMAN;
|
||||
}
|
||||
else if (strcmp(langCode, "NLD") == 0){
|
||||
else if (strcmp(langCode, "NLD") == 0)
|
||||
{
|
||||
return LANGUAGE_DUTCH;
|
||||
}
|
||||
else if (strcmp(langCode, "FRA") == 0){
|
||||
else if (strcmp(langCode, "FRA") == 0)
|
||||
{
|
||||
return LANGUAGE_FRENCH;
|
||||
}
|
||||
else if (strcmp(langCode, "HUN") == 0){
|
||||
else if (strcmp(langCode, "HUN") == 0)
|
||||
{
|
||||
return LANGUAGE_HUNGARIAN;
|
||||
}
|
||||
else if (strcmp(langCode, "PLK") == 0){
|
||||
else if (strcmp(langCode, "PLK") == 0)
|
||||
{
|
||||
return LANGUAGE_POLISH;
|
||||
}
|
||||
else if (strcmp(langCode, "ESP") == 0){
|
||||
else if (strcmp(langCode, "ESP") == 0)
|
||||
{
|
||||
return LANGUAGE_SPANISH;
|
||||
}
|
||||
else if (strcmp(langCode, "SVE") == 0){
|
||||
else if (strcmp(langCode, "SVE") == 0)
|
||||
{
|
||||
return LANGUAGE_SWEDISH;
|
||||
}
|
||||
else if (strcmp(langCode, "ITA") == 0){
|
||||
else if (strcmp(langCode, "ITA") == 0)
|
||||
{
|
||||
return LANGUAGE_ITALIAN;
|
||||
}
|
||||
else if (strcmp(langCode, "POR") == 0){
|
||||
else if (strcmp(langCode, "POR") == 0)
|
||||
{
|
||||
return LANGUAGE_PORTUGUESE_BR;
|
||||
}
|
||||
else if (strcmp(langCode, "FIN") == 0){
|
||||
else if (strcmp(langCode, "FIN") == 0)
|
||||
{
|
||||
return LANGUAGE_FINNISH;
|
||||
}
|
||||
else if (strcmp(langCode, "NOR") == 0){
|
||||
else if (strcmp(langCode, "NOR") == 0)
|
||||
{
|
||||
return LANGUAGE_NORWEGIAN;
|
||||
}
|
||||
else if (strcmp(langCode, "DAN") == 0)
|
||||
|
@ -290,16 +307,19 @@ time_t platform_file_get_modified_time(const utf8* path)
|
|||
{
|
||||
WIN32_FILE_ATTRIBUTE_DATA data;
|
||||
|
||||
wchar_t *wPath = utf8_to_widechar(path);
|
||||
wchar_t* wPath = utf8_to_widechar(path);
|
||||
BOOL result = GetFileAttributesExW(wPath, GetFileExInfoStandard, &data);
|
||||
free(wPath);
|
||||
|
||||
if (result) {
|
||||
if (result)
|
||||
{
|
||||
ULARGE_INTEGER ull;
|
||||
ull.LowPart = data.ftLastWriteTime.dwLowDateTime;
|
||||
ull.HighPart = data.ftLastWriteTime.dwHighDateTime;
|
||||
return ull.QuadPart / 10000000ULL - 11644473600ULL;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -307,11 +327,8 @@ time_t platform_file_get_modified_time(const utf8* path)
|
|||
uint8_t platform_get_locale_currency()
|
||||
{
|
||||
CHAR currCode[4];
|
||||
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
|
||||
LOCALE_SINTLSYMBOL,
|
||||
(LPSTR)&currCode,
|
||||
sizeof(currCode)) == 0
|
||||
) {
|
||||
if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SINTLSYMBOL, (LPSTR)&currCode, sizeof(currCode)) == 0)
|
||||
{
|
||||
return platform_get_currency_value(NULL);
|
||||
}
|
||||
|
||||
|
@ -321,20 +338,20 @@ uint8_t platform_get_locale_currency()
|
|||
uint8_t platform_get_locale_measurement_format()
|
||||
{
|
||||
UINT measurement_system;
|
||||
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
|
||||
LOCALE_IMEASURE | LOCALE_RETURN_NUMBER,
|
||||
(LPSTR)&measurement_system,
|
||||
sizeof(measurement_system)) == 0
|
||||
) {
|
||||
if (GetLocaleInfo(
|
||||
LOCALE_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER, (LPSTR)&measurement_system, sizeof(measurement_system))
|
||||
== 0)
|
||||
{
|
||||
return MEASUREMENT_FORMAT_METRIC;
|
||||
}
|
||||
|
||||
switch (measurement_system) {
|
||||
case 1:
|
||||
return MEASUREMENT_FORMAT_IMPERIAL;
|
||||
case 0:
|
||||
default:
|
||||
return MEASUREMENT_FORMAT_METRIC;
|
||||
switch (measurement_system)
|
||||
{
|
||||
case 1:
|
||||
return MEASUREMENT_FORMAT_IMPERIAL;
|
||||
case 0:
|
||||
default:
|
||||
return MEASUREMENT_FORMAT_METRIC;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,16 +361,13 @@ uint8_t platform_get_locale_temperature_format()
|
|||
|
||||
// GetLocaleInfo will set fahrenheit to 1 if the locale on this computer
|
||||
// uses the United States measurement system or 0 otherwise.
|
||||
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
|
||||
LOCALE_IMEASURE | LOCALE_RETURN_NUMBER,
|
||||
(LPSTR)&fahrenheit,
|
||||
sizeof(fahrenheit)) == 0
|
||||
) {
|
||||
if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER, (LPSTR)&fahrenheit, sizeof(fahrenheit)) == 0)
|
||||
{
|
||||
// Assume celsius by default if function call fails
|
||||
return TEMPERATURE_FORMAT_C;
|
||||
}
|
||||
|
||||
if(fahrenheit)
|
||||
if (fahrenheit)
|
||||
return TEMPERATURE_FORMAT_F;
|
||||
else
|
||||
return TEMPERATURE_FORMAT_C;
|
||||
|
@ -376,7 +390,15 @@ uint8_t platform_get_locale_date_format()
|
|||
//
|
||||
wchar_t first[sizeof(dateFormat)];
|
||||
wchar_t second[sizeof(dateFormat)];
|
||||
if (swscanf_s(dateFormat, L"%l[dyM]%*l[^dyM]%l[dyM]%*l[^dyM]%*l[dyM]", first, (uint32_t)Util::CountOf(first), second, (uint32_t)Util::CountOf(second)) != 2) {
|
||||
if (swscanf_s(
|
||||
dateFormat,
|
||||
L"%l[dyM]%*l[^dyM]%l[dyM]%*l[^dyM]%*l[dyM]",
|
||||
first,
|
||||
(uint32_t)Util::CountOf(first),
|
||||
second,
|
||||
(uint32_t)Util::CountOf(second))
|
||||
!= 2)
|
||||
{
|
||||
return DATE_FORMAT_DAY_MONTH_YEAR;
|
||||
}
|
||||
|
||||
|
@ -390,10 +412,12 @@ uint8_t platform_get_locale_date_format()
|
|||
}
|
||||
else if (wcsncmp(L"y", first, 1) == 0)
|
||||
{
|
||||
if (wcsncmp(L"d", second, 1) == 0) {
|
||||
if (wcsncmp(L"d", second, 1) == 0)
|
||||
{
|
||||
return DATE_FORMAT_YEAR_DAY_MONTH;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
// Closest possible option
|
||||
return DATE_FORMAT_YEAR_MONTH_DAY;
|
||||
}
|
||||
|
@ -404,14 +428,14 @@ uint8_t platform_get_locale_date_format()
|
|||
}
|
||||
|
||||
#ifndef NO_TTF
|
||||
bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size)
|
||||
bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size)
|
||||
{
|
||||
#if !defined(__MINGW32__) && ((NTDDI_VERSION >= NTDDI_VISTA) && !defined(_USING_V110_SDK71_) && !defined(_ATL_XP_TARGETING))
|
||||
wchar_t *fontFolder;
|
||||
wchar_t* fontFolder;
|
||||
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Fonts, 0, NULL, &fontFolder)))
|
||||
{
|
||||
// Convert wchar to utf8, then copy the font folder path to the buffer.
|
||||
utf8 *outPathTemp = widechar_to_utf8(fontFolder);
|
||||
utf8* outPathTemp = widechar_to_utf8(fontFolder);
|
||||
safe_strcpy(buffer, outPathTemp, size);
|
||||
free(outPathTemp);
|
||||
|
||||
|
@ -434,13 +458,13 @@ bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size)
|
|||
}
|
||||
#endif // NO_TTF
|
||||
|
||||
utf8 * platform_get_absolute_path(const utf8 * relativePath, const utf8 * basePath)
|
||||
utf8* platform_get_absolute_path(const utf8* relativePath, const utf8* basePath)
|
||||
{
|
||||
utf8 path[MAX_PATH];
|
||||
safe_strcpy(path, basePath, sizeof(path));
|
||||
safe_strcat_path(path, relativePath, sizeof(path));
|
||||
|
||||
wchar_t * pathW = utf8_to_widechar(path);
|
||||
wchar_t* pathW = utf8_to_widechar(path);
|
||||
wchar_t fullPathW[MAX_PATH];
|
||||
DWORD fullPathLen = GetFullPathNameW(pathW, (DWORD)Util::CountOf(fullPathW), fullPathW, NULL);
|
||||
|
||||
|
@ -472,7 +496,8 @@ utf8* platform_get_username()
|
|||
static char username[UNLEN + 1];
|
||||
|
||||
DWORD usernameLength = UNLEN + 1;
|
||||
if (!GetUserName(username, &usernameLength)) {
|
||||
if (!GetUserName(username, &usernameLength))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -483,14 +508,17 @@ bool platform_process_is_elevated()
|
|||
{
|
||||
BOOL isElevated = FALSE;
|
||||
HANDLE hToken = nullptr;
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
|
||||
{
|
||||
TOKEN_ELEVATION Elevation;
|
||||
DWORD tokenSize = sizeof(TOKEN_ELEVATION);
|
||||
if (GetTokenInformation(hToken, TokenElevation, &Elevation, sizeof(Elevation), &tokenSize)) {
|
||||
if (GetTokenInformation(hToken, TokenElevation, &Elevation, sizeof(Elevation), &tokenSize))
|
||||
{
|
||||
isElevated = Elevation.TokenIsElevated;
|
||||
}
|
||||
}
|
||||
if (hToken) {
|
||||
if (hToken)
|
||||
{
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
return isElevated;
|
||||
|
@ -500,27 +528,23 @@ bool platform_process_is_elevated()
|
|||
// File association setup
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define SOFTWARE_CLASSES L"Software\\Classes"
|
||||
#define MUI_CACHE L"Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache"
|
||||
#define SOFTWARE_CLASSES L"Software\\Classes"
|
||||
#define MUI_CACHE L"Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache"
|
||||
|
||||
static void get_progIdName(wchar_t *dst, const utf8 *extension)
|
||||
static void get_progIdName(wchar_t* dst, const utf8* extension)
|
||||
{
|
||||
utf8 progIdName[128];
|
||||
safe_strcpy(progIdName, OPENRCT2_NAME, sizeof(progIdName));
|
||||
safe_strcat(progIdName, extension, sizeof(progIdName));
|
||||
|
||||
wchar_t *progIdNameW = utf8_to_widechar(progIdName);
|
||||
wchar_t* progIdNameW = utf8_to_widechar(progIdName);
|
||||
lstrcpyW(dst, progIdNameW);
|
||||
free(progIdNameW);
|
||||
}
|
||||
|
||||
static bool windows_setup_file_association(
|
||||
const utf8 * extension,
|
||||
const utf8 * fileTypeText,
|
||||
const utf8 * commandText,
|
||||
const utf8 * commandArgs,
|
||||
const uint32_t iconIndex
|
||||
) {
|
||||
const utf8* extension, const utf8* fileTypeText, const utf8* commandText, const utf8* commandArgs, const uint32_t iconIndex)
|
||||
{
|
||||
wchar_t exePathW[MAX_PATH];
|
||||
wchar_t dllPathW[MAX_PATH];
|
||||
|
||||
|
@ -529,10 +553,10 @@ static bool windows_setup_file_association(
|
|||
GetModuleFileNameW(NULL, exePathW, sizeof(exePathW));
|
||||
GetModuleFileNameW(plaform_get_dll_module(), dllPathW, sizeof(dllPathW));
|
||||
|
||||
wchar_t *extensionW = utf8_to_widechar(extension);
|
||||
wchar_t *fileTypeTextW = utf8_to_widechar(fileTypeText);
|
||||
wchar_t *commandTextW = utf8_to_widechar(commandText);
|
||||
wchar_t *commandArgsW = utf8_to_widechar(commandArgs);
|
||||
wchar_t* extensionW = utf8_to_widechar(extension);
|
||||
wchar_t* fileTypeTextW = utf8_to_widechar(fileTypeText);
|
||||
wchar_t* commandTextW = utf8_to_widechar(commandText);
|
||||
wchar_t* commandArgsW = utf8_to_widechar(commandArgs);
|
||||
|
||||
wchar_t progIdNameW[128];
|
||||
get_progIdName(progIdNameW, extension);
|
||||
|
@ -542,38 +566,45 @@ static bool windows_setup_file_association(
|
|||
HKEY hRootKey = nullptr;
|
||||
|
||||
// [HKEY_CURRENT_USER\Software\Classes]
|
||||
if (RegOpenKeyW(HKEY_CURRENT_USER, SOFTWARE_CLASSES, &hRootKey) != ERROR_SUCCESS) {
|
||||
if (RegOpenKeyW(HKEY_CURRENT_USER, SOFTWARE_CLASSES, &hRootKey) != ERROR_SUCCESS)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// [hRootKey\.ext]
|
||||
if (RegSetValueW(hRootKey, extensionW, REG_SZ, progIdNameW, 0) != ERROR_SUCCESS) {
|
||||
if (RegSetValueW(hRootKey, extensionW, REG_SZ, progIdNameW, 0) != ERROR_SUCCESS)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (RegCreateKeyW(hRootKey, progIdNameW, &hKey) != ERROR_SUCCESS) {
|
||||
if (RegCreateKeyW(hRootKey, progIdNameW, &hKey) != ERROR_SUCCESS)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// [hRootKey\OpenRCT2.ext]
|
||||
if (RegSetValueW(hKey, NULL, REG_SZ, fileTypeTextW, 0) != ERROR_SUCCESS) {
|
||||
if (RegSetValueW(hKey, NULL, REG_SZ, fileTypeTextW, 0) != ERROR_SUCCESS)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
// [hRootKey\OpenRCT2.ext\DefaultIcon]
|
||||
wchar_t szIconW[MAX_PATH];
|
||||
printResult = swprintf_s(szIconW, MAX_PATH, L"\"%s\",%d", dllPathW, iconIndex);
|
||||
assert(printResult >= 0);
|
||||
if (RegSetValueW(hKey, L"DefaultIcon", REG_SZ, szIconW, 0) != ERROR_SUCCESS) {
|
||||
if (RegSetValueW(hKey, L"DefaultIcon", REG_SZ, szIconW, 0) != ERROR_SUCCESS)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// [hRootKey\OpenRCT2.sv6\shell]
|
||||
if (RegSetValueW(hKey, L"shell", REG_SZ, L"open", 0) != ERROR_SUCCESS) {
|
||||
if (RegSetValueW(hKey, L"shell", REG_SZ, L"open", 0) != ERROR_SUCCESS)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// [hRootKey\OpenRCT2.sv6\shell\open]
|
||||
if (RegSetValueW(hKey, L"shell\\open", REG_SZ, commandTextW, 0) != ERROR_SUCCESS) {
|
||||
if (RegSetValueW(hKey, L"shell\\open", REG_SZ, commandTextW, 0) != ERROR_SUCCESS)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -581,7 +612,8 @@ static bool windows_setup_file_association(
|
|||
wchar_t szCommandW[MAX_PATH];
|
||||
printResult = swprintf_s(szCommandW, MAX_PATH, L"\"%s\" %s", exePathW, commandArgsW);
|
||||
assert(printResult >= 0);
|
||||
if (RegSetValueW(hKey, L"shell\\open\\command", REG_SZ, szCommandW, 0) != ERROR_SUCCESS) {
|
||||
if (RegSetValueW(hKey, L"shell\\open\\command", REG_SZ, szCommandW, 0) != ERROR_SUCCESS)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -596,11 +628,12 @@ fail:
|
|||
return result;
|
||||
}
|
||||
|
||||
static void windows_remove_file_association(const utf8 * extension)
|
||||
static void windows_remove_file_association(const utf8* extension)
|
||||
{
|
||||
// [HKEY_CURRENT_USER\Software\Classes]
|
||||
HKEY hRootKey;
|
||||
if (RegOpenKeyW(HKEY_CURRENT_USER, SOFTWARE_CLASSES, &hRootKey) == ERROR_SUCCESS) {
|
||||
if (RegOpenKeyW(HKEY_CURRENT_USER, SOFTWARE_CLASSES, &hRootKey) == ERROR_SUCCESS)
|
||||
{
|
||||
// [hRootKey\.ext]
|
||||
RegDeleteTreeA(hRootKey, extension);
|
||||
|
||||
|
@ -616,10 +649,10 @@ static void windows_remove_file_association(const utf8 * extension)
|
|||
void platform_setup_file_associations()
|
||||
{
|
||||
// Setup file extensions
|
||||
windows_setup_file_association(".sc4", "RCT1 Scenario (.sc4)", "Play", "\"%1\"", 0);
|
||||
windows_setup_file_association(".sc6", "RCT2 Scenario (.sc6)", "Play", "\"%1\"", 0);
|
||||
windows_setup_file_association(".sv4", "RCT1 Saved Game (.sc4)", "Play", "\"%1\"", 0);
|
||||
windows_setup_file_association(".sv6", "RCT2 Saved Game (.sv6)", "Play", "\"%1\"", 0);
|
||||
windows_setup_file_association(".sc4", "RCT1 Scenario (.sc4)", "Play", "\"%1\"", 0);
|
||||
windows_setup_file_association(".sc6", "RCT2 Scenario (.sc6)", "Play", "\"%1\"", 0);
|
||||
windows_setup_file_association(".sv4", "RCT1 Saved Game (.sc4)", "Play", "\"%1\"", 0);
|
||||
windows_setup_file_association(".sv6", "RCT2 Saved Game (.sv6)", "Play", "\"%1\"", 0);
|
||||
windows_setup_file_association(".td4", "RCT1 Track Design (.td4)", "Install", "\"%1\"", 0);
|
||||
windows_setup_file_association(".td6", "RCT2 Track Design (.td6)", "Install", "\"%1\"", 0);
|
||||
|
||||
|
@ -653,23 +686,29 @@ bool platform_setup_uri_protocol()
|
|||
|
||||
// [HKEY_CURRENT_USER\Software\Classes]
|
||||
HKEY hRootKey;
|
||||
if (RegOpenKeyW(HKEY_CURRENT_USER, SOFTWARE_CLASSES, &hRootKey) == ERROR_SUCCESS) {
|
||||
if (RegOpenKeyW(HKEY_CURRENT_USER, SOFTWARE_CLASSES, &hRootKey) == ERROR_SUCCESS)
|
||||
{
|
||||
// [hRootKey\openrct2]
|
||||
HKEY hClassKey;
|
||||
if (RegCreateKeyA(hRootKey, "openrct2", &hClassKey) == ERROR_SUCCESS) {
|
||||
if (RegSetValueA(hClassKey, NULL, REG_SZ, "URL:openrct2", 0) == ERROR_SUCCESS) {
|
||||
if (RegSetKeyValueA(hClassKey, NULL, "URL Protocol", REG_SZ, "", 0) == ERROR_SUCCESS) {
|
||||
if (RegCreateKeyA(hRootKey, "openrct2", &hClassKey) == ERROR_SUCCESS)
|
||||
{
|
||||
if (RegSetValueA(hClassKey, NULL, REG_SZ, "URL:openrct2", 0) == ERROR_SUCCESS)
|
||||
{
|
||||
if (RegSetKeyValueA(hClassKey, NULL, "URL Protocol", REG_SZ, "", 0) == ERROR_SUCCESS)
|
||||
{
|
||||
// [hRootKey\openrct2\shell\open\command]
|
||||
wchar_t exePath[MAX_PATH];
|
||||
GetModuleFileNameW(NULL, exePath, MAX_PATH);
|
||||
|
||||
wchar_t buffer[512];
|
||||
swprintf_s(buffer, sizeof(buffer), L"\"%s\" handle-uri \"%%1\"", exePath);
|
||||
if (RegSetValueW(hClassKey, L"shell\\open\\command", REG_SZ, buffer, 0) == ERROR_SUCCESS) {
|
||||
if (RegSetValueW(hClassKey, L"shell\\open\\command", REG_SZ, buffer, 0) == ERROR_SUCCESS)
|
||||
{
|
||||
// Not compulsory, but gives the application a nicer name
|
||||
// [HKEY_CURRENT_USER\SOFTWARE\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache]
|
||||
HKEY hMuiCacheKey;
|
||||
if (RegCreateKeyW(hRootKey, MUI_CACHE, &hMuiCacheKey) == ERROR_SUCCESS) {
|
||||
if (RegCreateKeyW(hRootKey, MUI_CACHE, &hMuiCacheKey) == ERROR_SUCCESS)
|
||||
{
|
||||
swprintf_s(buffer, sizeof(buffer), L"%s.FriendlyAppName", exePath);
|
||||
// mingw-w64 used to define RegSetKeyValueW's signature incorrectly
|
||||
// You need at least mingw-w64 5.0 including this commit:
|
||||
|
|
|
@ -26,76 +26,86 @@
|
|||
void macos_disallow_automatic_window_tabbing()
|
||||
{
|
||||
@autoreleasepool {
|
||||
if ([NSWindow respondsToSelector:@selector(setAllowsAutomaticWindowTabbing:)]) {
|
||||
if ([NSWindow respondsToSelector:@selector(setAllowsAutomaticWindowTabbing:)])
|
||||
{
|
||||
[NSWindow setAllowsAutomaticWindowTabbing:NO];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
utf8* macos_str_decomp_to_precomp(utf8 *input)
|
||||
utf8* macos_str_decomp_to_precomp(utf8* input)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
if (input == NULL) {
|
||||
@autoreleasepool {
|
||||
if (input == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NSString *inputDecomp = [NSString stringWithUTF8String:input];
|
||||
NSString* inputDecomp = [NSString stringWithUTF8String:input];
|
||||
return strdup([inputDecomp.precomposedStringWithCanonicalMapping cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_TTF
|
||||
bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size)
|
||||
bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
CTFontDescriptorRef fontRef = CTFontDescriptorCreateWithNameAndSize((CFStringRef)[NSString stringWithUTF8String:font->font_name], 0.0);
|
||||
@autoreleasepool {
|
||||
CTFontDescriptorRef fontRef
|
||||
= CTFontDescriptorCreateWithNameAndSize((CFStringRef)[NSString stringWithUTF8String:font->font_name], 0.0);
|
||||
CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(fontRef, kCTFontURLAttribute);
|
||||
if (url) {
|
||||
NSString *fontPath = [NSString stringWithString:[(NSURL *)CFBridgingRelease(url) path]];
|
||||
if (url)
|
||||
{
|
||||
NSString* fontPath = [NSString stringWithString:[(NSURL*)CFBridgingRelease(url) path]];
|
||||
safe_strcpy(buffer, fontPath.UTF8String, size);
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // NO_TTF
|
||||
|
||||
bool platform_has_matching_language(NSString *preferredLocale, uint16_t* languageIdentifier)
|
||||
bool platform_has_matching_language(NSString* preferredLocale, uint16_t* languageIdentifier)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
if ([preferredLocale isEqualToString:@"en"] || [preferredLocale isEqualToString:@"en-CA"]) {
|
||||
@autoreleasepool {
|
||||
if ([preferredLocale isEqualToString:@"en"] || [preferredLocale isEqualToString:@"en-CA"])
|
||||
{
|
||||
*languageIdentifier = LANGUAGE_ENGLISH_US;
|
||||
return YES;
|
||||
}
|
||||
|
||||
if ([preferredLocale isEqualToString:@"zh-CN"]) {
|
||||
if ([preferredLocale isEqualToString:@"zh-CN"])
|
||||
{
|
||||
*languageIdentifier = LANGUAGE_CHINESE_SIMPLIFIED;
|
||||
return YES;
|
||||
}
|
||||
|
||||
if ([preferredLocale isEqualToString:@"zh-TW"]) {
|
||||
if ([preferredLocale isEqualToString:@"zh-TW"])
|
||||
{
|
||||
*languageIdentifier = LANGUAGE_CHINESE_TRADITIONAL;
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Find an exact match (language and region)
|
||||
for (int i = 1; i < LANGUAGE_COUNT; i++) {
|
||||
if([preferredLocale isEqualToString:[NSString stringWithUTF8String:LanguagesDescriptors[i].locale]]) {
|
||||
for (int i = 1; i < LANGUAGE_COUNT; i++)
|
||||
{
|
||||
if ([preferredLocale isEqualToString:[NSString stringWithUTF8String:LanguagesDescriptors[i].locale]])
|
||||
{
|
||||
*languageIdentifier = i;
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Only check for a matching language
|
||||
NSString *languageCode = [[preferredLocale componentsSeparatedByString:@"-"] firstObject];
|
||||
for (int i = 1; i < LANGUAGE_COUNT; i++) {
|
||||
NSString *optionLanguageCode = [[[NSString stringWithUTF8String:LanguagesDescriptors[i].locale] componentsSeparatedByString:@"-"] firstObject];
|
||||
if([languageCode isEqualToString:optionLanguageCode]) {
|
||||
NSString* languageCode = [[preferredLocale componentsSeparatedByString:@"-"] firstObject];
|
||||
for (int i = 1; i < LANGUAGE_COUNT; i++)
|
||||
{
|
||||
NSString* optionLanguageCode =
|
||||
[[[NSString stringWithUTF8String:LanguagesDescriptors[i].locale] componentsSeparatedByString:@"-"] firstObject];
|
||||
if ([languageCode isEqualToString:optionLanguageCode])
|
||||
{
|
||||
*languageIdentifier = i;
|
||||
return YES;
|
||||
}
|
||||
|
@ -107,12 +117,13 @@ bool platform_has_matching_language(NSString *preferredLocale, uint16_t* languag
|
|||
|
||||
uint16_t platform_get_locale_language()
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
NSArray<NSString*> *preferredLanguages = [NSLocale preferredLanguages];
|
||||
for (NSString *preferredLanguage in preferredLanguages) {
|
||||
@autoreleasepool {
|
||||
NSArray<NSString*>* preferredLanguages = [NSLocale preferredLanguages];
|
||||
for (NSString* preferredLanguage in preferredLanguages)
|
||||
{
|
||||
uint16_t languageIdentifier;
|
||||
if (platform_has_matching_language(preferredLanguage, &languageIdentifier)) {
|
||||
if (platform_has_matching_language(preferredLanguage, &languageIdentifier))
|
||||
{
|
||||
return languageIdentifier;
|
||||
}
|
||||
}
|
||||
|
@ -124,20 +135,19 @@ uint16_t platform_get_locale_language()
|
|||
|
||||
uint8_t platform_get_locale_currency()
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
NSString *currencyCode = [[NSLocale currentLocale] objectForKey:NSLocaleCurrencyCode];
|
||||
@autoreleasepool {
|
||||
NSString* currencyCode = [[NSLocale currentLocale] objectForKey:NSLocaleCurrencyCode];
|
||||
return platform_get_currency_value(currencyCode.UTF8String);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t platform_get_locale_measurement_format()
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
NSNumber *metricSystem = [[NSLocale currentLocale] objectForKey:NSLocaleUsesMetricSystem];
|
||||
@autoreleasepool {
|
||||
NSNumber* metricSystem = [[NSLocale currentLocale] objectForKey:NSLocaleUsesMetricSystem];
|
||||
|
||||
if (metricSystem.boolValue) {
|
||||
if (metricSystem.boolValue)
|
||||
{
|
||||
return MEASUREMENT_FORMAT_METRIC;
|
||||
}
|
||||
|
||||
|
@ -145,16 +155,16 @@ uint8_t platform_get_locale_measurement_format()
|
|||
}
|
||||
}
|
||||
|
||||
void platform_get_changelog_path(utf8 *outPath, size_t outSize)
|
||||
void platform_get_changelog_path(utf8* outPath, size_t outSize)
|
||||
{
|
||||
platform_get_openrct_data_path(outPath, outSize);
|
||||
safe_strcat_path(outPath, "changelog.txt", outSize);
|
||||
}
|
||||
|
||||
bool platform_get_steam_path(utf8 * outPath, size_t outSize)
|
||||
bool platform_get_steam_path(utf8* outPath, size_t outSize)
|
||||
{
|
||||
char steamPath[1024] = { 0 };
|
||||
const char * homeDir = getpwuid(getuid())->pw_dir;
|
||||
const char* homeDir = getpwuid(getuid())->pw_dir;
|
||||
if (homeDir != NULL)
|
||||
{
|
||||
safe_strcpy(steamPath, homeDir, sizeof(steamPath));
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
#ifndef _PLATFORM_H_
|
||||
#define _PLATFORM_H_
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
#include "../common.h"
|
||||
|
||||
struct TTFFontDescriptor;
|
||||
struct rct2_install_info;
|
||||
|
@ -31,24 +32,28 @@ struct rct2_install_info;
|
|||
#define PLATFORM_NEWLINE "\n"
|
||||
#endif
|
||||
|
||||
struct resolution_t {
|
||||
struct resolution_t
|
||||
{
|
||||
int32_t width, height;
|
||||
};
|
||||
|
||||
struct file_info {
|
||||
const char *path;
|
||||
struct file_info
|
||||
{
|
||||
const char* path;
|
||||
uint64_t size;
|
||||
uint64_t last_modified;
|
||||
};
|
||||
|
||||
struct rct2_date {
|
||||
struct rct2_date
|
||||
{
|
||||
uint8_t day;
|
||||
uint8_t month;
|
||||
int16_t year;
|
||||
uint8_t day_of_week;
|
||||
};
|
||||
|
||||
struct rct2_time {
|
||||
struct rct2_time
|
||||
{
|
||||
uint8_t hour;
|
||||
uint8_t minute;
|
||||
uint8_t second;
|
||||
|
@ -60,62 +65,64 @@ enum FILEDIALOG_TYPE
|
|||
FD_SAVE
|
||||
};
|
||||
|
||||
struct file_dialog_desc {
|
||||
struct file_dialog_desc
|
||||
{
|
||||
uint8_t type;
|
||||
const utf8 *title;
|
||||
const utf8 *initial_directory;
|
||||
const utf8 *default_filename;
|
||||
struct {
|
||||
const utf8 *name; // E.g. "Image Files"
|
||||
const utf8 *pattern; // E.g. "*.png;*.jpg;*.gif"
|
||||
const utf8* title;
|
||||
const utf8* initial_directory;
|
||||
const utf8* default_filename;
|
||||
struct
|
||||
{
|
||||
const utf8* name; // E.g. "Image Files"
|
||||
const utf8* pattern; // E.g. "*.png;*.jpg;*.gif"
|
||||
} filters[8];
|
||||
};
|
||||
|
||||
// Platform shared definitions
|
||||
void platform_update_palette(const uint8_t *colours, int32_t start_index, int32_t num_colours);
|
||||
void platform_update_palette(const uint8_t* colours, int32_t start_index, int32_t num_colours);
|
||||
void platform_toggle_windowed_mode();
|
||||
void platform_refresh_video(bool recreate_window);
|
||||
void platform_get_date_utc(rct2_date *out_date);
|
||||
void platform_get_time_utc(rct2_time *out_time);
|
||||
void platform_get_date_local(rct2_date *out_date);
|
||||
void platform_get_time_local(rct2_time *out_time);
|
||||
void platform_get_date_utc(rct2_date* out_date);
|
||||
void platform_get_time_utc(rct2_time* out_time);
|
||||
void platform_get_date_local(rct2_date* out_date);
|
||||
void platform_get_time_local(rct2_time* out_time);
|
||||
|
||||
// Platform specific definitions
|
||||
bool platform_file_exists(const utf8 *path);
|
||||
bool platform_directory_exists(const utf8 *path);
|
||||
bool platform_original_game_data_exists(const utf8 *path);
|
||||
bool platform_file_exists(const utf8* path);
|
||||
bool platform_directory_exists(const utf8* path);
|
||||
bool platform_original_game_data_exists(const utf8* path);
|
||||
time_t platform_file_get_modified_time(const utf8* path);
|
||||
bool platform_ensure_directory_exists(const utf8 *path);
|
||||
bool platform_directory_delete(const utf8 *path);
|
||||
utf8 * platform_get_absolute_path(const utf8 * relative_path, const utf8 * base_path);
|
||||
bool platform_ensure_directory_exists(const utf8* path);
|
||||
bool platform_directory_delete(const utf8* path);
|
||||
utf8* platform_get_absolute_path(const utf8* relative_path, const utf8* base_path);
|
||||
bool platform_lock_single_instance();
|
||||
bool platform_place_string_on_clipboard(utf8* target);
|
||||
|
||||
// Returns the bitmask of the GetLogicalDrives function for windows, 0 for other systems
|
||||
int32_t platform_get_drives();
|
||||
|
||||
bool platform_file_copy(const utf8 *srcPath, const utf8 *dstPath, bool overwrite);
|
||||
bool platform_file_move(const utf8 *srcPath, const utf8 *dstPath);
|
||||
bool platform_file_delete(const utf8 *path);
|
||||
bool platform_file_copy(const utf8* srcPath, const utf8* dstPath, bool overwrite);
|
||||
bool platform_file_move(const utf8* srcPath, const utf8* dstPath);
|
||||
bool platform_file_delete(const utf8* path);
|
||||
uint32_t platform_get_ticks();
|
||||
void platform_sleep(uint32_t ms);
|
||||
void platform_get_openrct_data_path(utf8 *outPath, size_t outSize);
|
||||
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory, size_t outSize);
|
||||
void platform_get_openrct_data_path(utf8* outPath, size_t outSize);
|
||||
void platform_get_user_directory(utf8* outPath, const utf8* subDirectory, size_t outSize);
|
||||
utf8* platform_get_username();
|
||||
bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc, size_t outSize);
|
||||
utf8 *platform_open_directory_browser(const utf8 *title);
|
||||
bool platform_open_common_file_dialog(utf8* outFilename, file_dialog_desc* desc, size_t outSize);
|
||||
utf8* platform_open_directory_browser(const utf8* title);
|
||||
uint8_t platform_get_locale_currency();
|
||||
uint8_t platform_get_currency_value(const char *currencyCode);
|
||||
uint8_t platform_get_currency_value(const char* currencyCode);
|
||||
uint16_t platform_get_locale_language();
|
||||
uint8_t platform_get_locale_measurement_format();
|
||||
uint8_t platform_get_locale_temperature_format();
|
||||
uint8_t platform_get_locale_date_format();
|
||||
bool platform_process_is_elevated();
|
||||
bool platform_get_steam_path(utf8 * outPath, size_t outSize);
|
||||
bool platform_get_steam_path(utf8* outPath, size_t outSize);
|
||||
std::string platform_get_rct2_steam_dir();
|
||||
|
||||
#ifndef NO_TTF
|
||||
bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size);
|
||||
bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size);
|
||||
#endif // NO_TTF
|
||||
|
||||
datetime64 platform_get_datetime_now_utc();
|
||||
|
@ -127,28 +134,28 @@ void core_init();
|
|||
|
||||
// Windows specific definitions
|
||||
#ifdef _WIN32
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#undef CreateDirectory
|
||||
#undef CreateWindow
|
||||
#undef GetMessage
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#undef CreateDirectory
|
||||
#undef CreateWindow
|
||||
#undef GetMessage
|
||||
|
||||
void platform_setup_file_associations();
|
||||
void platform_remove_file_associations();
|
||||
bool platform_setup_uri_protocol();
|
||||
// This function cannot be marked as 'static', even though it may seem to be,
|
||||
// as it requires external linkage, which 'static' prevents
|
||||
__declspec(dllexport) int32_t StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int32_t nCmdShow);
|
||||
void platform_setup_file_associations();
|
||||
void platform_remove_file_associations();
|
||||
bool platform_setup_uri_protocol();
|
||||
// This function cannot be marked as 'static', even though it may seem to be,
|
||||
// as it requires external linkage, which 'static' prevents
|
||||
__declspec(dllexport) int32_t StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int32_t nCmdShow);
|
||||
#endif // _WIN32
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
void macos_disallow_automatic_window_tabbing();
|
||||
utf8* macos_str_decomp_to_precomp(utf8 *input);
|
||||
void macos_disallow_automatic_window_tabbing();
|
||||
utf8* macos_str_decomp_to_precomp(utf8* input);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue