ref: e646d6d829d50983ec2cba8e230a0b95341f6752
parent: a41d051499b5be820f4eb2a96efb8019bd1fcd53
author: Iliyas Jorio <iliyas@jor.io>
date: Thu Jul 30 17:37:20 EDT 2020
Linux support for prefs
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.16)
project(Candy_Crisis)
-set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD 17)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
find_package(SDL2 REQUIRED)
--- a/src/prefs.cpp
+++ b/src/prefs.cpp
@@ -4,6 +4,9 @@
#if __APPLE__
#include <Cocoa/Cocoa.h>
+#else
+#include <filesystem>
+#include <fstream>
#endif
#include <stdio.h>
@@ -41,9 +44,51 @@
{ PREF_NAME("BestCombo"), &best, sizeof(best ) }
};
+#if !__APPLE__ && !_WIN32
+static std::fstream GetPrefsStream(std::ios::openmode openmode)
+{
+ std::filesystem::path path;
+ const char *home = getenv("XDG_CONFIG_HOME");
+ if (home) {
+ path = std::filesystem::path(home);
+ } else {
+ home = getenv("HOME");
+ if (!home) {
+ throw std::exception();
+ }
+ path = std::filesystem::path(home) / ".config";
+ }
+ path = path.lexically_normal();
+ bool exists = std::filesystem::exists(path);
+
+ if (!exists) {
+ if (openmode == std::ios::out)
+ std::filesystem::create_directories(path);
+ else
+ throw std::exception();
+ } else if (!std::filesystem::is_directory(path)) {
+ throw;
+ }
+ path /= "CandyCrisis.prefs";
+
+ if (openmode == std::ios::in && !std::filesystem::is_regular_file(path))
+ throw std::exception();
+ return std::fstream(path, std::ios::binary | openmode);
+}
+#endif
+
void LoadPrefs()
{
+#if !__APPLE__ && !_WIN32
+ std::fstream stream;
+ try {
+ stream = GetPrefsStream(std::ios::in);
+ } catch (...) {
+ return;
+ }
+#endif
+
for (Preference& pref: prefList)
{
#if __APPLE__
@@ -52,8 +97,7 @@
{
memcpy(pref.valuePtr, [data bytes], pref.valueLength);
}
- #endif
- #if _WIN32
+ #elif _WIN32
HKEY hKey;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\\CandyCrisis"), 0, KEY_QUERY_VALUE, &hKey))
{
@@ -69,6 +113,28 @@
RegCloseKey(hKey);
}
+ #else
+ stream.seekg(0, std::ios::beg);
+ while (!stream.eof()) {
+ int keyLength;
+ char key[256];
+ unsigned int contentsLength;
+
+ keyLength = stream.get();
+ if (stream.eof()) break;
+ stream.read(key, keyLength);
+ key[keyLength] = '\0';
+ stream.read((char*)&contentsLength, sizeof(contentsLength));
+
+ if (!strncmp(key, pref.keyName, strlen(pref.keyName))) {
+ if (contentsLength != pref.valueLength)
+ break;
+ stream.read((char*) pref.valuePtr, pref.valueLength);
+ break;
+ } else {
+ stream.seekg(contentsLength, std::ios::cur);
+ }
+ }
#endif
}
}
@@ -76,6 +142,15 @@
void SavePrefs()
{
+#if !__APPLE__ && !_WIN32
+ std::fstream stream;
+ try {
+ stream = GetPrefsStream(std::ios::out);
+ } catch (...) {
+ return;
+ }
+#endif
+
for (Preference& pref: prefList)
{
#if __APPLE__
@@ -82,8 +157,7 @@
[[NSUserDefaults standardUserDefaults]
setObject:[NSData dataWithBytes:pref.valuePtr length:pref.valueLength]
forKey:pref.keyName];
- #endif
- #if _WIN32
+ #elif _WIN32
HKEY hKey;
if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\\CandyCrisis"), 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL))
{
@@ -90,6 +164,11 @@
RegSetValueEx(hKey, pref.keyName, 0, REG_BINARY, reinterpret_cast<BYTE*>(pref.valuePtr), pref.valueLength);
RegCloseKey(hKey);
}
+ #else
+ stream.put(strlen(pref.keyName));
+ stream.write(pref.keyName, strlen(pref.keyName));
+ stream.write((const char*)&pref.valueLength, sizeof(pref.valueLength));
+ stream.write((const char*)pref.valuePtr, pref.valueLength);
#endif
}