1 /** 2 * OS-specific paths. 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <vladimir@thecybershadow.net> 12 */ 13 14 module ae.sys.paths; 15 16 import std.path; 17 18 version (Windows) 19 { 20 import core.stdc.wctype; 21 22 import std.exception; 23 import std.file; 24 import std.utf; 25 26 import ae.sys.windows.imports; 27 mixin(importWin32!q{shlobj}); 28 mixin(importWin32!q{objidl}); 29 mixin(importWin32!q{windef}); 30 mixin(importWin32!q{winbase}); 31 32 string getExecutableName() 33 { 34 auto path = new char[MAX_PATH]; 35 path.length = enforce(GetModuleFileNameA(null, path.ptr, cast(uint)path.length)); 36 return baseName(assumeUnique(path)); 37 } 38 39 private string getShellPath(int csidl) 40 { 41 LPITEMIDLIST pidl; 42 SHGetSpecialFolderLocation(null, csidl, &pidl); 43 scope(exit) 44 { 45 IMalloc aMalloc; 46 SHGetMalloc(&aMalloc); 47 aMalloc.Free(pidl); 48 } 49 50 auto path = new wchar[MAX_PATH]; 51 if (!SHGetPathFromIDListW(pidl, path.ptr)) 52 return null; 53 path.length = wcslen(path.ptr); 54 55 return toUTF8(path); 56 } 57 58 private string getAppDir(string appName, int csidl) 59 { 60 string dir = getShellPath(csidl) ~ `\` ~ (appName ? appName : getExecutableName()); 61 if (!exists(dir)) 62 mkdir(dir); 63 return dir; 64 } 65 66 string getLocalAppProfile (string appName = null) { return getAppDir(appName, CSIDL_LOCAL_APPDATA); } 67 string getRoamingAppProfile(string appName = null) { return getAppDir(appName, CSIDL_APPDATA); } 68 } 69 else // POSIX 70 { 71 import std.string; 72 import std.ascii; 73 import std.file; 74 75 alias toLower = std.ascii.toLower; 76 77 string getExecutableName() 78 { 79 // TODO: is this valid with OS X app bundles? 80 return baseName(readLink("/proc/self/exe")); 81 } 82 83 private string getPosixAppName(string appName) 84 { 85 string s = appName ? appName : getExecutableName(); 86 string s2; 87 foreach (c; s) 88 if (isAlphaNum(c)) 89 s2 ~= toLower(c); 90 else 91 if (!s2.endsWith('-')) 92 s2 ~= '-'; 93 return s2; 94 } 95 96 string getAppProfile(string appName = null) 97 { 98 string path = expandTilde("~/." ~ getPosixAppName(appName)); 99 if (!exists(path)) 100 mkdir(path); 101 return path; 102 } 103 104 alias getAppProfile getLocalAppProfile; 105 alias getAppProfile getRoamingAppProfile; 106 }