mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
894 lines
No EOL
18 KiB
C++
894 lines
No EOL
18 KiB
C++
#include "Core.h"
|
|
|
|
#ifdef PLATFORM_MACOS
|
|
#include <mach-o/dyld.h>
|
|
#endif
|
|
|
|
#ifdef PLATFORM_WIN32
|
|
#define Ptr Ptr_
|
|
#define byte byte_
|
|
#define CY win32_CY_
|
|
|
|
#include <shellapi.h>
|
|
#include <wincon.h>
|
|
|
|
#ifdef COMPILER_MINGW
|
|
#undef CY
|
|
#endif
|
|
|
|
#include <shlobj.h>
|
|
|
|
#undef Ptr
|
|
#undef byte
|
|
#undef CY
|
|
#endif
|
|
|
|
namespace Upp {
|
|
|
|
static StaticMutex sHlock;
|
|
|
|
static char sHomeDir[_MAX_PATH + 1];
|
|
static char Argv0__[_MAX_PATH + 1];
|
|
|
|
void (*CrashHook)();
|
|
|
|
void InstallCrashHook(void (*h)())
|
|
{
|
|
CrashHook = h;
|
|
}
|
|
|
|
void SetHomeDirectory(const char *dir)
|
|
{
|
|
INTERLOCKED_(sHlock) {
|
|
strcpy(sHomeDir, dir);
|
|
}
|
|
}
|
|
|
|
String GetHomeDirectory() {
|
|
String r;
|
|
INTERLOCKED_(sHlock) {
|
|
if(!*sHomeDir)
|
|
strcpy(sHomeDir,
|
|
#ifdef PLATFORM_WIN32
|
|
GetEnv("HOMEDRIVE") + GetEnv("HOMEPATH")
|
|
#else
|
|
Nvl(GetEnv("HOME"), "/root")
|
|
#endif
|
|
);
|
|
r = sHomeDir;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
|
|
|
|
#ifdef PLATFORM_WIN32
|
|
|
|
String GetEnv(const char *id)
|
|
{
|
|
return WString(_wgetenv(ToSystemCharsetW(id))).ToString();
|
|
}
|
|
|
|
bool SetEnv(const char *name, const char *value)
|
|
{
|
|
String env;
|
|
env << name << "=" << value;
|
|
auto wenv = ToUtf16(env);
|
|
wenv.Add(wchar_t(0));
|
|
return _wputenv(wenv.begin()) == 0;
|
|
}
|
|
|
|
String GetExeFilePath()
|
|
{
|
|
return GetModuleFileName();
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef PLATFORM_POSIX
|
|
|
|
String GetEnv(const char *id)
|
|
{
|
|
return FromSystemCharset(getenv(id));
|
|
}
|
|
|
|
bool SetEnv(const char *name, const char *value)
|
|
{
|
|
return setenv(name, value, 1) == 0;
|
|
}
|
|
|
|
static void sSetArgv0__(const char *title)
|
|
{
|
|
strcpy(Argv0__, title);
|
|
}
|
|
|
|
const char *procexepath_() {
|
|
static char h[_MAX_PATH + 1];
|
|
ONCELOCK {
|
|
char link[1024];
|
|
#ifdef PLATFORM_MACOS
|
|
uint32_t sz = 1024;
|
|
if(_NSGetExecutablePath(link, &sz))
|
|
*link = 0;
|
|
#elif defined(PLATFORM_BSD)
|
|
sprintf(link, "/proc/%d/file", getpid());
|
|
#else
|
|
sprintf(link, "/proc/%d/exe", getpid());
|
|
#endif
|
|
FindFile ff(link);
|
|
if(ff) {
|
|
if(ff.IsSymLink()) {
|
|
int ret = readlink(link, h, _MAX_PATH);
|
|
if(ret > 0 && ret < _MAX_PATH)
|
|
h[ret] = '\0';
|
|
else
|
|
*h = '\0';
|
|
}
|
|
else
|
|
strcpy(h, link);
|
|
}
|
|
}
|
|
return h;
|
|
}
|
|
|
|
String GetExeFilePath()
|
|
{
|
|
static char exepath[_MAX_PATH + 1];
|
|
ONCELOCK {
|
|
const char *exe = procexepath_();
|
|
if(*exe)
|
|
strcpy(exepath, exe);
|
|
else {
|
|
String x = Argv0__;
|
|
if(IsFullPath(x) && FileExists(x))
|
|
strcpy(exepath, x);
|
|
else {
|
|
strcpy(exepath, GetHomeDirFile("upp"));
|
|
Vector<String> p = Split(FromSystemCharset(Environment().Get("PATH")), ':');
|
|
if(x.Find('/') >= 0)
|
|
p.Add(GetCurrentDirectory());
|
|
for(int i = 0; i < p.GetCount(); i++) {
|
|
String ep = NormalizePath(AppendFileName(p[i], x));
|
|
if(FileExists(ep))
|
|
strcpy(exepath, ep);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return exepath;
|
|
}
|
|
|
|
#endif
|
|
|
|
String GetExeDirFile(const char *filename)
|
|
{
|
|
return AppendFileName(GetFileFolder(GetExeFilePath()), filename);
|
|
}
|
|
|
|
String GetExeFolder()
|
|
{
|
|
return GetFileFolder(GetExeFilePath());
|
|
}
|
|
|
|
String GetExeTitle()
|
|
{
|
|
return GetFileTitle(GetExeFilePath());
|
|
}
|
|
|
|
#ifdef PLATFORM_COCOA
|
|
String GetAppFolder()
|
|
{
|
|
String p = GetExeFolder();
|
|
return p.TrimEnd("/Contents/MacOS") && GetFileExt(p) == ".app" ? p : String();
|
|
}
|
|
#endif
|
|
|
|
void SyncLogPath__();
|
|
|
|
static char sAppName[256];
|
|
|
|
String GetAppName()
|
|
{
|
|
return Nvl(String(sAppName), GetExeTitle());
|
|
}
|
|
|
|
void SetAppName(const String& name)
|
|
{
|
|
strcpy(sAppName, name);
|
|
SyncLogPath__();
|
|
}
|
|
|
|
static char sConfigGroup[256] = "u++";
|
|
|
|
void SetConfigGroup(const char *group)
|
|
{
|
|
strcpy(sConfigGroup, group);
|
|
SyncLogPath__();
|
|
}
|
|
|
|
String GetConfigGroup()
|
|
{
|
|
return sConfigGroup;
|
|
}
|
|
|
|
String GetTempDirectory()
|
|
{
|
|
return GetTempPath();
|
|
}
|
|
|
|
String TempFile(const char *filename)
|
|
{
|
|
return AppendFileName(GetTempDirectory(), filename);
|
|
}
|
|
|
|
String GetHomeDirFile(const char *fp) {
|
|
return AppendFileName(GetHomeDirectory(), fp);
|
|
}
|
|
|
|
static bool sHomecfg;
|
|
|
|
void UseHomeDirectoryConfig(bool b)
|
|
{
|
|
sHomecfg = b;
|
|
}
|
|
|
|
static char sConfigFolder[_MAX_PATH + 1];
|
|
|
|
void SetConfigDirectory(const String& s)
|
|
{
|
|
strcpy(sConfigFolder, s);
|
|
SyncLogPath__();
|
|
}
|
|
|
|
static char sConfigName[_MAX_PATH + 1];
|
|
|
|
void SetConfigName(const String& s)
|
|
{
|
|
strcpy(sConfigName, s);
|
|
SyncLogPath__();
|
|
}
|
|
|
|
void CopyFolder(const char *dst, const char *src)
|
|
{
|
|
RealizeDirectory(dst);
|
|
FindFile ff(String(src) + "/*.*");
|
|
while(ff) {
|
|
String s = AppendFileName(src, ff.GetName());
|
|
String d = AppendFileName(dst, ff.GetName());
|
|
if(ff.IsFile()) {
|
|
FileIn in(s);
|
|
FileOut out(d);
|
|
CopyStream(out, in);
|
|
}
|
|
else
|
|
if(ff.IsFolder() && *ff.GetName() != '.')
|
|
CopyFolder(d, s);
|
|
ff.Next();
|
|
}
|
|
}
|
|
|
|
#ifdef PLATFORM_POSIX
|
|
|
|
String GetUserConfigDir(const String& exe, bool *sandboxed)
|
|
{
|
|
String cfgdir;
|
|
String h = GetExeFolder();
|
|
if(!sHomecfg)
|
|
while(h.GetCount() > 1 && DirectoryExists(h)) {
|
|
String pp = AppendFileName(h, ".config");
|
|
FindFile ff(pp);
|
|
if(ff && ff.IsFolder() && ff.CanWrite()) {
|
|
cfgdir = pp;
|
|
break;
|
|
}
|
|
h = GetFileFolder(h);
|
|
}
|
|
if(IsNull(cfgdir)) {
|
|
if(sandboxed)
|
|
*sandboxed = false;
|
|
cfgdir = GetEnv("XDG_CONFIG_HOME");
|
|
}
|
|
if(IsNull(cfgdir) || !DirectoryExists(cfgdir))
|
|
cfgdir = GetHomeDirFile(".config");
|
|
|
|
return cfgdir;
|
|
}
|
|
|
|
String GetUserConfigDir(bool *sandboxed)
|
|
{
|
|
return GetUserConfigDir(GetExeFolder(), sandboxed);
|
|
}
|
|
|
|
#endif
|
|
|
|
String ConfigFile(const char *file) {
|
|
if(*sConfigFolder)
|
|
return AppendFileName(sConfigFolder, file);
|
|
String name = *sConfigName ? sConfigName : GetAppName();
|
|
#if defined(PLATFORM_WIN32)
|
|
if(sHomecfg) {
|
|
String p = GetHomeDirFile(name);
|
|
ONCELOCK
|
|
RealizeDirectory(p);
|
|
return AppendFileName(p, file);
|
|
}
|
|
return GetExeDirFile(file);
|
|
#elif defined(PLATFORM_POSIX)
|
|
static char cfgd[_MAX_PATH + 1];
|
|
static bool sandboxed = true;
|
|
ONCELOCK {
|
|
String cfgdir = GetUserConfigDir(&sandboxed);
|
|
if(*sConfigGroup)
|
|
cfgdir = AppendFileName(cfgdir, GetConfigGroup());
|
|
strcpy(cfgd, cfgdir);
|
|
}
|
|
String pp = AppendFileName(cfgd, name);
|
|
bool exists = DirectoryExists(pp);
|
|
RealizeDirectory(pp);
|
|
if(!exists && !sandboxed) { // migrate config files from the old path
|
|
String old = GetHomeDirFile(".upp/" + GetExeTitle());
|
|
if(DirectoryExists(old))
|
|
CopyFolder(pp, old);
|
|
}
|
|
return AppendFileName(pp, file);
|
|
#else
|
|
NEVER();
|
|
return GetExeDirFile(file);
|
|
#endif//PLATFORM
|
|
}
|
|
|
|
String GetConfigFolder()
|
|
{
|
|
return GetFileFolder(ConfigFile("x"));
|
|
}
|
|
|
|
String ConfigFile() {
|
|
return ConfigFile(GetAppName() + ".cfg");
|
|
}
|
|
|
|
String argv0;
|
|
|
|
Vector<WString>& coreCmdLine__()
|
|
{
|
|
static Vector<WString> h;
|
|
return h;
|
|
}
|
|
|
|
static Mutex sCmdMutex;
|
|
static Vector<String> sCmd;
|
|
|
|
const Vector<String>& CommandLine()
|
|
{
|
|
Mutex::Lock __(sCmdMutex);
|
|
ONCELOCK {
|
|
for(WString s : coreCmdLine__())
|
|
sCmd.Add(s.ToString());
|
|
}
|
|
return sCmd;
|
|
}
|
|
|
|
void CommandLineRemove(int i, int count)
|
|
{
|
|
CommandLine();
|
|
sCmd.Remove(i, count);
|
|
}
|
|
|
|
String GetArgv0()
|
|
{
|
|
return Argv0__;
|
|
}
|
|
|
|
VectorMap<WString, WString>& EnvMap()
|
|
{
|
|
static VectorMap<WString, WString> x;
|
|
return x;
|
|
}
|
|
|
|
const VectorMap<String, String>& Environment()
|
|
{
|
|
VectorMap<String, String> *ptr;
|
|
INTERLOCKED {
|
|
static ArrayMap< byte, VectorMap<String, String> > charset_env;
|
|
byte cs = GetDefaultCharset();
|
|
int f = charset_env.Find(cs);
|
|
if(f >= 0)
|
|
ptr = &charset_env[f];
|
|
else {
|
|
ptr = &charset_env.Add(cs);
|
|
const VectorMap<WString, WString>& env_map = EnvMap();
|
|
for(int i = 0; i < env_map.GetCount(); i++)
|
|
ptr->Add(env_map.GetKey(i).ToString(), env_map[i].ToString());
|
|
}
|
|
}
|
|
return *ptr;
|
|
}
|
|
|
|
static int exitcode;
|
|
static bool sMainRunning;
|
|
|
|
void SetExitCode(int code) { exitcode = code; }
|
|
int GetExitCode() { return exitcode; }
|
|
|
|
bool IsMainRunning()
|
|
{
|
|
return sMainRunning;
|
|
}
|
|
|
|
void LoadLangFiles(const char *dir)
|
|
{
|
|
FindFile ff(AppendFileName(dir, "*.tr"));
|
|
while(ff) {
|
|
LoadLngFile(AppendFileName(dir, ff.GetName()));
|
|
ff.Next();
|
|
}
|
|
}
|
|
|
|
void CommonInit()
|
|
{
|
|
#ifdef PLATFORM_WIN32
|
|
LoadLangFiles(GetFileFolder(GetExeFilePath()));
|
|
#else
|
|
LoadLangFiles(GetHomeDirectory());
|
|
#endif
|
|
|
|
Vector<WString>& cmd = coreCmdLine__();
|
|
static WString exp_cmd = "--export-tr";
|
|
static WString brk_cmd = "--memory-breakpoint__";
|
|
|
|
for(int i = 0; i < cmd.GetCount();) {
|
|
if(cmd[i] == exp_cmd) {
|
|
{
|
|
i++;
|
|
int lang = 0;
|
|
int lang2 = 0;
|
|
byte charset = CHARSET_UTF8;
|
|
String fn = "all";
|
|
if(i < cmd.GetCount())
|
|
if(cmd[i].GetLength() == 4 || cmd[i].GetLength() == 5) {
|
|
lang = LNGFromText(cmd[i].ToString());
|
|
fn = cmd[i].ToString();
|
|
int c = cmd[i][4];
|
|
if(c >= '0' && c <= '8')
|
|
charset = c - '0' + CHARSET_WIN1250;
|
|
if(c >= 'A' && c <= 'J')
|
|
charset = c - 'A' + CHARSET_ISO8859_1;
|
|
}
|
|
fn << ".tr";
|
|
if(++i < cmd.GetCount() && (cmd[i].GetLength() == 4 || cmd[i].GetLength() == 5))
|
|
lang2 = LNGFromText(cmd[i].ToString());
|
|
#ifdef PLATFORM_WIN32
|
|
FileOut out(GetExeDirFile(fn));
|
|
#else
|
|
FileOut out(GetHomeDirFile(fn));
|
|
#endif
|
|
if(lang) {
|
|
if(lang2)
|
|
SaveLngFile(out, SetLNGCharset(lang, charset), SetLNGCharset(lang2, charset));
|
|
else
|
|
SaveLngFile(out, SetLNGCharset(lang, charset));
|
|
}
|
|
else {
|
|
Index<int> l = GetLngSet();
|
|
for(int i = 0; i < l.GetCount(); i++)
|
|
SaveLngFile(out, SetLNGCharset(l[i], charset));
|
|
}
|
|
}
|
|
exit(0);
|
|
}
|
|
#if defined(_DEBUG) && defined(UPP_HEAP)
|
|
if(cmd[i] == brk_cmd && i + 1 < cmd.GetCount()) {
|
|
MemoryBreakpoint(atoi(cmd[i + 1].ToString()));
|
|
cmd.Remove(i, 2);
|
|
}
|
|
else
|
|
i++;
|
|
#else
|
|
i++;
|
|
#endif
|
|
}
|
|
sMainRunning = true;
|
|
}
|
|
|
|
void Exit(int code)
|
|
{
|
|
SetExitCode(code);
|
|
throw ExitExc();
|
|
}
|
|
|
|
void MemorySetMainBegin__();
|
|
void MemorySetMainEnd__();
|
|
|
|
void AppExecute__(void (*app)())
|
|
{
|
|
try {
|
|
MemorySetMainBegin__();
|
|
(*app)();
|
|
MemorySetMainEnd__();
|
|
}
|
|
catch(ExitExc) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
#ifdef PLATFORM_POSIX
|
|
|
|
void s_ill_handler(int)
|
|
{
|
|
CrashHook();
|
|
Panic("Illegal instruction!");
|
|
}
|
|
|
|
void s_segv_handler(int)
|
|
{
|
|
CrashHook();
|
|
Panic("Invalid memory access!");
|
|
}
|
|
|
|
void s_fpe_handler(int)
|
|
{
|
|
CrashHook();
|
|
Panic("Invalid arithmetic operation!");
|
|
}
|
|
|
|
void AppInit__(int argc, const char **argv, const char **envptr)
|
|
{
|
|
SetLanguage(LNG_ENGLISH);
|
|
sSetArgv0__(argv[0]);
|
|
for(const char *var; (var = *envptr) != 0; envptr++)
|
|
{
|
|
const char *b = var;
|
|
while(*var && *var != '=')
|
|
var++;
|
|
String varname(b, var);
|
|
if(*var == '=')
|
|
var++;
|
|
EnvMap().Add(varname.ToWString(), String(var).ToWString());
|
|
}
|
|
Vector<WString>& cmd = coreCmdLine__();
|
|
for(int i = 1; i < argc; i++)
|
|
cmd.Add(FromSystemCharset(argv[i]).ToWString());
|
|
CommonInit();
|
|
signal(SIGILL, s_ill_handler);
|
|
signal(SIGSEGV, s_segv_handler);
|
|
signal(SIGBUS, s_segv_handler);
|
|
signal(SIGFPE, s_fpe_handler);
|
|
}
|
|
#endif
|
|
|
|
#if defined(PLATFORM_WIN32)
|
|
|
|
#ifdef _DEBUG
|
|
static BOOL WINAPI s_consoleCtrlHandler(DWORD signal) {
|
|
if(signal == CTRL_C_EVENT) {
|
|
extern bool NoMemoryLeaksCheck;
|
|
NoMemoryLeaksCheck = true;
|
|
}
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
void AppInitEnvironment__()
|
|
{
|
|
SetLanguage(LNG_('E', 'N', 'U', 'S'));
|
|
int nArgs;
|
|
LPWSTR *szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
|
|
if(szArglist) {
|
|
strcpy(Argv0__, FromSystemCharsetW(szArglist[0]));
|
|
for(int i = 1; i < nArgs; i++)
|
|
coreCmdLine__().Add(FromSystemCharsetW(szArglist[i]).ToWString());
|
|
LocalFree(szArglist);
|
|
}
|
|
|
|
WCHAR *env = GetEnvironmentStringsW();
|
|
for(WCHAR *ptr = env; *ptr; ptr++)
|
|
{
|
|
const WCHAR *b = ptr;
|
|
if(*ptr)
|
|
ptr++;
|
|
while(*ptr && *ptr != '=')
|
|
ptr++;
|
|
WString varname = ToUtf32(b, int(ptr - b));
|
|
if(*ptr)
|
|
ptr++;
|
|
b = ptr;
|
|
while(*ptr)
|
|
ptr++;
|
|
EnvMap().GetAdd(ToUpper(varname)) = ToUtf32(b, int(ptr - b));
|
|
}
|
|
FreeEnvironmentStringsW(env);
|
|
|
|
CommonInit();
|
|
}
|
|
|
|
void AppInit__(int argc, const char **argv)
|
|
{
|
|
AppInitEnvironment__();
|
|
|
|
#ifdef _DEBUG
|
|
SetConsoleCtrlHandler(s_consoleCtrlHandler, TRUE);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
void AppExit__()
|
|
{
|
|
Thread::ShutdownThreads();
|
|
sMainRunning = false;
|
|
#ifdef PLATFORM_POSIX
|
|
MemoryIgnoreLeaksBegin(); // Qt leaks on app exit...
|
|
#endif
|
|
}
|
|
|
|
#ifdef flagTURTLE // Turtle web backend
|
|
|
|
void Turtle_PutLink(const String& link);
|
|
|
|
void LaunchWebBrowser(const String& url)
|
|
{
|
|
Turtle_PutLink(url);
|
|
}
|
|
|
|
#else
|
|
|
|
#if defined(PLATFORM_WIN32) && !defined(PLATFORM_WINCE)
|
|
static auxthread_t auxthread__ sShellExecuteOpen(void *str)
|
|
{
|
|
ShellExecuteW(NULL, L"open", (WCHAR *)str, NULL, L".", SW_SHOWDEFAULT);
|
|
free(str);
|
|
return 0;
|
|
}
|
|
|
|
void LaunchWebBrowser(const String& url)
|
|
{
|
|
Vector<WCHAR> wurl = ToSystemCharsetW(url);
|
|
if ((int64)(ShellExecuteW(NULL, L"open", wurl, NULL, L".", SW_SHOWDEFAULT)) <= 32) {
|
|
int l = sizeof(wchar) * wurl.GetCount() + 1;
|
|
char *curl = (char *)malloc(l);
|
|
memcpy(curl, wurl, l);
|
|
StartAuxThread(sShellExecuteOpen, curl);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef PLATFORM_POSIX
|
|
void LaunchWebBrowser(const String& url)
|
|
{
|
|
#ifdef PLATFORM_MACOS
|
|
String u = url;
|
|
u.Replace("$", "\\$");
|
|
IGNORE_RESULT(system("open " + u));
|
|
#else
|
|
const char * browser[] = {
|
|
"htmlview", "xdg-open", "x-www-browser", "firefox", "konqueror", "opera", "epiphany", "galeon", "netscape"
|
|
};
|
|
for(int i = 0; i < __countof(browser); i++)
|
|
if(system("which " + String(browser[i])) == 0) {
|
|
String u = url;
|
|
u.Replace("'", "'\\''");
|
|
IGNORE_RESULT(
|
|
system(String(browser[i]) + " '" + u + "' &")
|
|
);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|
|
String sDataPath;
|
|
|
|
void SetDataPath(const char *path)
|
|
{
|
|
sDataPath = path;
|
|
}
|
|
|
|
String GetDataFile(const char *filename)
|
|
{
|
|
if(sDataPath.GetCount())
|
|
return AppendFileName(sDataPath, filename);
|
|
String s = GetEnv("UPP_MAIN__");
|
|
return s.GetCount() ? AppendFileName(s, filename) : GetExeDirFile(filename);
|
|
}
|
|
|
|
String LoadDataFile(const char *filename)
|
|
{
|
|
return LoadFile(GetDataFile(filename));
|
|
}
|
|
|
|
String GetComputerName()
|
|
{
|
|
#if defined(PLATFORM_WIN32)
|
|
WCHAR temp[256];
|
|
*temp = 0;
|
|
dword w = 255;
|
|
::GetComputerNameW(temp, &w);
|
|
#else
|
|
char temp[256];
|
|
gethostname(temp, sizeof(temp));
|
|
#endif
|
|
return temp;
|
|
}
|
|
|
|
String GetUserName()
|
|
{
|
|
#if defined(PLATFORM_WIN32)
|
|
WCHAR temp[256];
|
|
*temp = 0;
|
|
dword w = 255;
|
|
::GetUserNameW(temp, &w);
|
|
return temp;
|
|
#else
|
|
return Nvl(GetEnv("USER"), "root");
|
|
#endif
|
|
}
|
|
|
|
String GetDesktopManager()
|
|
{
|
|
#if defined(PLATFORM_WIN32) && !defined(PLATFORM_WINCE)
|
|
return "windows";
|
|
#endif
|
|
#ifdef PLATFORM_POSIX
|
|
if(GetEnv("GNOME_DESKTOP_SESSION_ID").GetCount())
|
|
return "gnome";
|
|
if(GetEnv("KDE_FULL_SESSION").GetCount() || GetEnv("KDEDIR").GetCount())
|
|
return "kde";
|
|
return GetEnv("DESKTOP_SESSION");
|
|
#endif
|
|
}
|
|
|
|
#if defined(PLATFORM_WIN32)
|
|
|
|
String GetShellFolder(int clsid)
|
|
{
|
|
WCHAR path[MAX_PATH];
|
|
if(SHGetFolderPathW(NULL, clsid, NULL, /*SHGFP_TYPE_CURRENT*/0, path) == S_OK)
|
|
return FromSystemCharsetW(path);
|
|
return Null;
|
|
}
|
|
|
|
String GetDesktopFolder() { return GetShellFolder(CSIDL_DESKTOP); }
|
|
String GetProgramsFolder() { return GetShellFolder(CSIDL_PROGRAM_FILES); }
|
|
String GetProgramsFolderX86() { return GetShellFolder(0x2a); }
|
|
String GetAppDataFolder() { return GetShellFolder(CSIDL_APPDATA);}
|
|
String GetMusicFolder() { return GetShellFolder(CSIDL_MYMUSIC);}
|
|
String GetPicturesFolder() { return GetShellFolder(CSIDL_MYPICTURES);}
|
|
String GetVideoFolder() { return GetShellFolder(CSIDL_MYVIDEO);}
|
|
String GetDocumentsFolder() { return GetShellFolder(/*CSIDL_MYDOCUMENTS*/0x0005);}
|
|
String GetTemplatesFolder() { return GetShellFolder(CSIDL_TEMPLATES);}
|
|
String GetProgramDataFolder() { return GetShellFolder(CSIDL_COMMON_APPDATA); }
|
|
|
|
#define MY_DEFINE_KNOWN_FOLDER(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
|
static const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
|
|
|
|
MY_DEFINE_KNOWN_FOLDER(MY_FOLDERID_Downloads, 0x374de290, 0x123f, 0x4565, 0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b);
|
|
|
|
String GetDownloadFolder()
|
|
{
|
|
static HRESULT (STDAPICALLTYPE * SHGetKnownFolderPath)(const void *rfid, DWORD dwFlags, HANDLE hToken, PWSTR *ppszPath);
|
|
ONCELOCK {
|
|
DllFn(SHGetKnownFolderPath, "shell32.dll", "SHGetKnownFolderPath");
|
|
}
|
|
if(SHGetKnownFolderPath) {
|
|
PWSTR path = NULL;
|
|
if(SHGetKnownFolderPath(&MY_FOLDERID_Downloads, 0, NULL, &path) == S_OK && path) {
|
|
String s = FromSystemCharsetW(path);
|
|
CoTaskMemFree(path);
|
|
return s;
|
|
}
|
|
}
|
|
return Null;
|
|
};
|
|
#endif
|
|
|
|
#ifdef PLATFORM_POSIX
|
|
|
|
String GetPathXdg(String xdgConfigHome, String xdgConfigDirs)
|
|
{
|
|
String ret;
|
|
if(FileExists(ret = AppendFileName(xdgConfigHome, "user-dirs.dirs")))
|
|
return ret;
|
|
if(FileExists(ret = AppendFileName(xdgConfigDirs, "user-dirs.defaults")))
|
|
return ret;
|
|
if(FileExists(ret = AppendFileName(xdgConfigDirs, "user-dirs.dirs")))
|
|
return ret;
|
|
return Null;
|
|
}
|
|
|
|
String GetPathDataXdg(String fileConfig, const char *folder)
|
|
{
|
|
TextSettings settings;
|
|
settings.Load(fileConfig);
|
|
String v = settings.Get(folder);
|
|
if(*v == '\"')
|
|
v = v.Mid(1);
|
|
if(*v.Last() == '\"')
|
|
v.Trim(v.GetCount() - 1);
|
|
String r;
|
|
const char *s = v;
|
|
while(*s) {
|
|
if(*s == '$') {
|
|
CParser p(s + 1);
|
|
p.NoSkipSpaces();
|
|
p.Spaces();
|
|
if(p.IsId()) {
|
|
String id = p.ReadId();
|
|
r.Cat(GetEnv(id));
|
|
s = p.GetPtr();
|
|
}
|
|
else {
|
|
r.Cat('$');
|
|
s++;
|
|
}
|
|
}
|
|
else
|
|
r.Cat(*s++);
|
|
}
|
|
return r;
|
|
}
|
|
|
|
String GetShellFolder(const char *local, const char *users)
|
|
{
|
|
String xdgConfigHome = GetEnv("XDG_CONFIG_HOME");
|
|
if (xdgConfigHome == "") // By default
|
|
xdgConfigHome = AppendFileName(GetHomeDirectory(), ".config");
|
|
String xdgConfigDirs = GetEnv("XDG_CONFIG_DIRS");
|
|
if (xdgConfigDirs == "") // By default
|
|
xdgConfigDirs = "/etc/xdg";
|
|
String xdgFileConfigData = GetPathXdg(xdgConfigHome, xdgConfigDirs);
|
|
String ret = GetPathDataXdg(xdgFileConfigData, local);
|
|
if (ret == "" && *users != '\0')
|
|
return GetPathDataXdg(xdgFileConfigData, users);
|
|
else
|
|
return ret;
|
|
}
|
|
|
|
String GetProgramsFolder() { return String("/usr/bin"); }
|
|
String GetAppDataFolder() { return GetHomeDirectory(); }
|
|
#ifndef PLATFORM_MACOS // in MacOS, we need objective-c and AppKit to get these, we do not want to do that in Core
|
|
String GetDesktopFolder()
|
|
{
|
|
String ret = GetShellFolder("XDG_DESKTOP_DIR", "DESKTOP");
|
|
if (ret.IsEmpty())
|
|
return AppendFileName(GetHomeDirectory(), "Desktop");
|
|
else
|
|
return ret;
|
|
}
|
|
|
|
String GetMusicFolder() { return GetShellFolder("XDG_MUSIC_DIR", "MUSIC"); }
|
|
String GetPicturesFolder() { return GetShellFolder("XDG_PICTURES_DIR", "PICTURES"); }
|
|
String GetVideoFolder() { return GetShellFolder("XDG_VIDEOS_DIR", "VIDEOS"); }
|
|
String GetDocumentsFolder() { return GetShellFolder("XDG_DOCUMENTS_DIR", "DOCUMENTS"); }
|
|
String GetTemplatesFolder() { return GetShellFolder("XDG_TEMPLATES_DIR", "XDG_TEMPLATES_DIR"); }
|
|
String GetDownloadFolder() { return GetShellFolder("XDG_DOWNLOAD_DIR", "XDG_DOWNLOAD_DIR"); }
|
|
#endif
|
|
String GetProgramDataFolder() { return String("/var/opt"); }
|
|
|
|
#endif
|
|
|
|
bool IsUserAdmin()
|
|
{
|
|
#ifdef PLATFORM_POSIX
|
|
return geteuid() == 0;
|
|
#elif PLATFORM_WIN32
|
|
BOOL isAdmin = FALSE;
|
|
PSID pAdminGroup = nullptr;
|
|
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
|
if(AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&pAdminGroup)) {
|
|
CheckTokenMembership(nullptr, pAdminGroup, &isAdmin);
|
|
FreeSid(pAdminGroup);
|
|
}
|
|
return isAdmin;
|
|
#else
|
|
// Unsupported platform. (Assume no elevation.)
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
} |