diff --git a/src/common/console/c_enginecmds.cpp b/src/common/console/c_enginecmds.cpp index 0af6f3b56a5..4ce05c8169a 100644 --- a/src/common/console/c_enginecmds.cpp +++ b/src/common/console/c_enginecmds.cpp @@ -52,6 +52,10 @@ #include "version.h" #include "findfile.h" #include "md5.h" +#include "i_specialpaths.h" + +void I_OpenShellFolder(const char*); +void I_OpenShellFile(const char*); extern FILE* Logfile; @@ -336,3 +340,19 @@ CCMD(printlocalized) } } + +UNSAFE_CCMD(opensaves) +{ + I_OpenShellFolder(M_GetSavegamesPath().GetChars()); +} + +UNSAFE_CCMD(openscreenshots) +{ + I_OpenShellFolder(M_GetScreenshotsPath().GetChars()); +} + +UNSAFE_CCMD(openconfig) +{ + I_OpenShellFile(M_GetConfigPath(false).GetChars()); +} + diff --git a/src/common/platform/posix/cocoa/i_system.mm b/src/common/platform/posix/cocoa/i_system.mm index 76a38cbcf73..02cad154ab3 100644 --- a/src/common/platform/posix/cocoa/i_system.mm +++ b/src/common/platform/posix/cocoa/i_system.mm @@ -170,3 +170,18 @@ unsigned int I_MakeRNGSeed() { return static_cast(arc4random()); } + +void I_OpenShellFolder(const char* folder) +{ + std::string x = (std::string)"open " + (std::string)folder; + Printf("Opening folder: %s\n", folder); + std::system(x.c_str()); +} + +void I_OpenShellFile(const char* file) +{ + std::string x = (std::string)"open " + (std::string)file; + x.erase(x.find_last_of('/'), std::string::npos); + Printf("Opening folder to file: %s\n", file); + std::system(x.c_str()); +} diff --git a/src/common/platform/posix/sdl/i_system.cpp b/src/common/platform/posix/sdl/i_system.cpp index a63b15a9f2a..3dd43e98d80 100644 --- a/src/common/platform/posix/sdl/i_system.cpp +++ b/src/common/platform/posix/sdl/i_system.cpp @@ -431,3 +431,19 @@ unsigned int I_MakeRNGSeed() } return seed; } + +void I_OpenShellFolder(const char* folder) +{ + std::string x = (std::string)"xdg-open " + (std::string)folder; + Printf("Opening folder: %s\n", folder); + std::system(x.c_str()); +} + +void I_OpenShellFile(const char* file) +{ + std::string x = (std::string)"xdg-open " + (std::string)file; + x.erase(x.find_last_of('/'), std::string::npos); + Printf("Opening folder to file: %s\n", file); + std::system(x.c_str()); +} + diff --git a/src/common/platform/win32/i_specialpaths.cpp b/src/common/platform/win32/i_specialpaths.cpp index bbd3c4976ba..777d4fc63ac 100644 --- a/src/common/platform/win32/i_specialpaths.cpp +++ b/src/common/platform/win32/i_specialpaths.cpp @@ -283,7 +283,7 @@ FString M_GetScreenshotsPath() if (!UseKnownFolders()) { - path << progdir << "/Screenshots/"; + path << progdir << "Screenshots/"; } else if (GetKnownFolder(-1, MyFOLDERID_Screenshots, true, path)) { diff --git a/src/common/platform/win32/i_system.cpp b/src/common/platform/win32/i_system.cpp index 5459b7458c7..554bdddbcaa 100644 --- a/src/common/platform/win32/i_system.cpp +++ b/src/common/platform/win32/i_system.cpp @@ -6,6 +6,7 @@ ** Copyright 1998-2009 Randy Heit ** Copyright (C) 2007-2012 Skulltag Development Team ** Copyright (C) 2007-2016 Zandronum Development Team +** Copyright (C) 2017-2022 GZDoom Development Team ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -49,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +64,8 @@ #include #include +#include + #include "hardware.h" #include "printf.h" @@ -955,3 +959,51 @@ void I_SetThreadNumaNode(std::thread &thread, int numaNode) SetThreadAffinityMask(handle, (DWORD_PTR)numaNodes[numaNode].affinityMask); } } + +std::wstring ToUtf16(const std::string& str) +{ + if (str.empty()) return {}; + int needed = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0); + if (needed == 0) + throw std::runtime_error("MultiByteToWideChar failed"); + std::wstring result; + result.resize(needed); + needed = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), &result[0], (int)result.size()); + if (needed == 0) + throw std::runtime_error("MultiByteToWideChar failed"); + return result; +} + +/* // not currently used, but here for reference if it is needed +std::string FromUtf16(const std::wstring& str) +{ + if (str.empty()) return {}; + int needed = WideCharToMultiByte(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0, nullptr, nullptr); + if (needed == 0) + throw std::runtime_error("WideCharToMultiByte failed"); + std::string result; + result.resize(needed); + needed = WideCharToMultiByte(CP_UTF8, 0, str.data(), (int)str.size(), &result[0], (int)result.size(), nullptr, nullptr); + if (needed == 0) + throw std::runtime_error("WideCharToMultiByte failed"); + return result; +} +*/ + +void I_OpenShellFolder(const char* folder) +{ + std::string x = folder; + for (auto& c : x) { if (c == '/') c = '\\'; } + Printf("Opening folder: %s\n", x.c_str()); + ShellExecuteW(NULL, L"open", L"explorer.exe", ToUtf16(x).c_str(), NULL, SW_SHOWNORMAL); +} + +void I_OpenShellFile(const char* file) +{ + std::string x = (std::string)"/select," + (std::string)file; + for (auto& c : x) { if (c == '/') c = '\\'; } + x[0] = '/'; + Printf("Opening folder to file: %s\n", x.c_str()); + ShellExecuteW(NULL, L"open", L"explorer.exe", ToUtf16(x).c_str(), NULL, SW_SHOWNORMAL); +} +