PageRenderTime 25ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/boxvivid/uppsrc/Core/App.cpp

http://boxvivid.googlecode.com/
C++ | 573 lines | 503 code | 70 blank | 0 comment | 88 complexity | c391c66c7adf33980945092a74b43155 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-2-Clause, BSD-3-Clause, LGPL-3.0
  1. #include "Core.h"
  2. #ifdef PLATFORM_WIN32
  3. #define Ptr Ptr_
  4. #define byte byte_
  5. #define CY win32_CY_
  6. #include <shellapi.h>
  7. #include <wincon.h>
  8. #include <shlobj.h>
  9. #undef Ptr
  10. #undef byte
  11. #undef CY
  12. #endif
  13. NAMESPACE_UPP
  14. #ifdef PLATFORM_WIN32
  15. String GetEnv(const char *id)
  16. {
  17. return WString(_wgetenv(WString(id))).ToString();
  18. }
  19. String GetExeFilePath()
  20. {
  21. return GetModuleFileName();
  22. }
  23. String GetHomeDirectory() {
  24. return GetEnv("HOMEDRIVE") + GetEnv("HOMEPATH");
  25. }
  26. #endif
  27. #ifdef PLATFORM_POSIX
  28. String GetEnv(const char *id)
  29. {
  30. return FromSystemCharset(getenv(id));
  31. }
  32. char Argv0__[_MAX_PATH + 1];
  33. static void sSetArgv0__(const char *title)
  34. {
  35. strcpy(Argv0__, title);
  36. }
  37. extern char Argv0__[];
  38. const char *procexepath_() {
  39. static char h[_MAX_PATH + 1];
  40. ONCELOCK {
  41. char link[100];
  42. #ifdef PLATFORM_BSD
  43. sprintf(link, "/proc/%d/file", getpid());
  44. #else
  45. sprintf(link, "/proc/%d/exe", getpid());
  46. #endif
  47. int ret = readlink(link, h, _MAX_PATH);
  48. if(ret > 0 && ret < _MAX_PATH)
  49. h[ret] = '\0';
  50. else
  51. *h = '\0';
  52. }
  53. return h;
  54. }
  55. String GetExeFilePath()
  56. {
  57. static String exepath;
  58. ONCELOCK {
  59. const char *exe = procexepath_();
  60. if(*exe)
  61. exepath = exe;
  62. else {
  63. String x = Argv0__;
  64. if(IsFullPath(x) && FileExists(x))
  65. exepath = x;
  66. else {
  67. exepath = GetHomeDirFile("upp");
  68. Vector<String> p = Split(FromSystemCharset(Environment().Get("PATH")), ':');
  69. if(x.Find('/') >= 0)
  70. p.Add(GetCurrentDirectory());
  71. for(int i = 0; i < p.GetCount(); i++) {
  72. String ep = NormalizePath(AppendFileName(p[i], x));
  73. if(FileExists(ep))
  74. exepath = ep;
  75. }
  76. }
  77. }
  78. }
  79. return exepath;
  80. }
  81. #endif
  82. String GetExeDirFile(const char *filename)
  83. {
  84. return AppendFileName(GetFileFolder(GetExeFilePath()), filename);
  85. }
  86. String GetExeTitle()
  87. {
  88. return GetFileTitle(GetExeFilePath());
  89. }
  90. #ifdef PLATFORM_POSIX
  91. static StaticCriticalSection sHlock;
  92. String& sHomeDir() {
  93. static String s;
  94. return s;
  95. }
  96. String GetHomeDirectory() {
  97. String r;
  98. INTERLOCKED_(sHlock) {
  99. String& s = sHomeDir();
  100. if(s.IsEmpty()) {
  101. s = Nvl(GetEnv("HOME"), "/root");
  102. }
  103. r = s;
  104. }
  105. return r;
  106. }
  107. void SetHomeDirectory(const char *dir)
  108. {
  109. INTERLOCKED_(sHlock) {
  110. sHomeDir() = dir;
  111. }
  112. }
  113. #endif//PLATFORM_POSIX
  114. String GetHomeDirFile(const char *fp) {
  115. return AppendFileName(GetHomeDirectory(), fp);
  116. }
  117. static bool sHomecfg;
  118. void UseHomeDirectoryConfig(bool b)
  119. {
  120. sHomecfg = b;
  121. }
  122. String ConfigFile(const char *file) {
  123. #if defined(PLATFORM_WIN32)
  124. if(sHomecfg) {
  125. String p = GetHomeDirFile(GetExeTitle());
  126. ONCELOCK
  127. RealizeDirectory(p);
  128. return AppendFileName(p, file);
  129. }
  130. return GetExeDirFile(file);
  131. #elif defined(PLATFORM_POSIX)
  132. String p = GetHomeDirFile(".upp/" + GetExeTitle());
  133. ONCELOCK
  134. RealizeDirectory(p);
  135. return AppendFileName(p, file);
  136. #else
  137. #error ConfigFile not implemented for this platform, comment this line to get input string back
  138. return file;
  139. #endif//PLATFORM
  140. }
  141. String ConfigFile() {
  142. return ConfigFile(GetExeTitle() + ".cfg");
  143. }
  144. GLOBAL_VAR(Vector<WString>, coreCmdLine__)
  145. const Vector<String>& CommandLine()
  146. {
  147. Vector<String> *ptr;
  148. INTERLOCKED {
  149. static ArrayMap< byte, Vector<String> > charset_cmd;
  150. byte cs = GetDefaultCharset();
  151. int f = charset_cmd.Find(cs);
  152. if(f >= 0)
  153. ptr = &charset_cmd[f];
  154. else {
  155. ptr = &charset_cmd.Add(cs);
  156. const Vector<WString>& src = coreCmdLine__();
  157. for(int i = 0; i < src.GetCount(); i++)
  158. ptr->Add(src[i].ToString());
  159. }
  160. }
  161. return *ptr;
  162. }
  163. VectorMap<WString, WString>& EnvMap()
  164. {
  165. static VectorMap<WString, WString> x;
  166. return x;
  167. }
  168. const VectorMap<String, String>& Environment()
  169. {
  170. VectorMap<String, String> *ptr;
  171. INTERLOCKED {
  172. static ArrayMap< byte, VectorMap<String, String> > charset_env;
  173. byte cs = GetDefaultCharset();
  174. int f = charset_env.Find(cs);
  175. if(f >= 0)
  176. ptr = &charset_env[f];
  177. else {
  178. ptr = &charset_env.Add(cs);
  179. const VectorMap<WString, WString>& env_map = EnvMap();
  180. for(int i = 0; i < env_map.GetCount(); i++)
  181. ptr->Add(env_map.GetKey(i).ToString(), env_map[i].ToString());
  182. }
  183. }
  184. return *ptr;
  185. }
  186. static int exitcode;
  187. static bool sMainRunning;
  188. void SetExitCode(int code) { exitcode = code; }
  189. int GetExitCode() { return exitcode; }
  190. bool IsMainRunning()
  191. {
  192. return sMainRunning;
  193. }
  194. void LoadLangFiles(const char *dir)
  195. {
  196. FindFile ff(AppendFileName(dir, "*.tr"));
  197. while(ff) {
  198. LoadLngFile(AppendFileName(dir, ff.GetName()));
  199. ff.Next();
  200. }
  201. }
  202. void CommonInit()
  203. {
  204. #ifdef PLATFORM_WIN32
  205. LoadLangFiles(GetFileFolder(GetExeFilePath()));
  206. #else
  207. LoadLangFiles(GetHomeDirectory());
  208. #endif
  209. Vector<WString>& cmd = coreCmdLine__();
  210. static WString exp_cmd = "--export-tr";
  211. static WString brk_cmd = "--memory-breakpoint__";
  212. for(int i = 0; i < cmd.GetCount();) {
  213. if(cmd[i] == exp_cmd) {
  214. {
  215. i++;
  216. int lang = 0;
  217. byte charset = CHARSET_UTF8;
  218. String fn = "all";
  219. if(i < cmd.GetCount())
  220. if(cmd[i].GetLength() != 4 && cmd[i].GetLength() != 5)
  221. lang = 0;
  222. else {
  223. lang = LNGFromText(cmd[i].ToString());
  224. fn = cmd[i].ToString();
  225. int c = cmd[i][4];
  226. if(c >= '0' && c <= '8')
  227. charset = c - '0' + CHARSET_WIN1250;
  228. if(c >= 'A' && c <= 'J')
  229. charset = c - 'A' + CHARSET_ISO8859_1;
  230. }
  231. fn << ".tr";
  232. #ifdef PLATFORM_WIN32
  233. FileOut out(GetExeDirFile(fn));
  234. #else
  235. FileOut out(GetHomeDirFile(fn));
  236. #endif
  237. if(lang)
  238. SaveLngFile(out, SetLNGCharset(lang, charset));
  239. else {
  240. Index<int> l = GetLngSet();
  241. for(int i = 0; i < l.GetCount(); i++)
  242. SaveLngFile(out, SetLNGCharset(l[i], charset));
  243. }
  244. }
  245. exit(0);
  246. }
  247. #if defined(_DEBUG) && defined(UPP_HEAP)
  248. if(cmd[i] == brk_cmd && i + 1 < cmd.GetCount()) {
  249. MemoryBreakpoint(atoi(cmd[i + 1].ToString()));
  250. cmd.Remove(i, 2);
  251. }
  252. else
  253. i++;
  254. #else
  255. i++;
  256. #endif
  257. }
  258. sMainRunning = true;
  259. }
  260. #ifdef PLATFORM_POSIX
  261. void s_ill_handler(int)
  262. {
  263. Panic("Illegal instruction!");
  264. }
  265. void s_segv_handler(int)
  266. {
  267. Panic("Invalid memory access!");
  268. }
  269. void s_fpe_handler(int)
  270. {
  271. Panic("Invalid arithmetic operation!");
  272. }
  273. void AppInit__(int argc, const char **argv, const char **envptr)
  274. {
  275. SetLanguage(LNG_ENGLISH);
  276. sSetArgv0__(argv[0]);
  277. for(const char *var; (var = *envptr) != 0; envptr++)
  278. {
  279. const char *b = var;
  280. while(*var && *var != '=')
  281. var++;
  282. String varname(b, var);
  283. if(*var == '=')
  284. var++;
  285. EnvMap().Add(varname.ToWString(), String(var).ToWString());
  286. }
  287. Vector<WString>& cmd = coreCmdLine__();
  288. for(int i = 1; i < argc; i++)
  289. cmd.Add(FromSystemCharset(argv[i]).ToWString());
  290. CommonInit();
  291. signal(SIGILL, s_ill_handler);
  292. signal(SIGSEGV, s_segv_handler);
  293. signal(SIGBUS, s_segv_handler);
  294. signal(SIGFPE, s_fpe_handler);
  295. }
  296. #endif
  297. #if defined(PLATFORM_WIN32)
  298. void AppInitEnvironment__()
  299. {
  300. #ifndef PLATFORM_WINCE
  301. wchar *env = GetEnvironmentStringsW();
  302. for(wchar *ptr = env; *ptr; ptr++)
  303. {
  304. const wchar *b = ptr;
  305. if(*ptr)
  306. ptr++;
  307. while(*ptr && *ptr != '=')
  308. ptr++;
  309. WString varname(b, ptr);
  310. if(*ptr)
  311. ptr++;
  312. b = ptr;
  313. while(*ptr)
  314. ptr++;
  315. EnvMap().GetAdd(ToUpper(varname)) = WString(b, ptr);
  316. }
  317. FreeEnvironmentStringsW(env);
  318. #endif
  319. CommonInit();
  320. }
  321. void AppInit__(int argc, const char **argv)
  322. {
  323. SetLanguage(LNG_ENGLISH);
  324. Vector<WString>& cmd = coreCmdLine__();
  325. for(int i = 1; i < argc; i++)
  326. cmd.Add(argv[i]);
  327. AppInitEnvironment__();
  328. }
  329. #endif
  330. void AppExit__()
  331. {
  332. sMainRunning = false;
  333. #ifdef PLATFORM_POSIX
  334. MemoryIgnoreLeaksBegin(); // Qt leaks on app exit...
  335. #endif
  336. }
  337. void LaunchWebBrowser(const String& url)
  338. {
  339. #if defined(PLATFORM_WIN32) && !defined(PLATFORM_WINCE)
  340. ShellExecute(NULL, "open", url, NULL, ".", SW_SHOWDEFAULT);
  341. #endif
  342. #ifdef PLATFORM_POSIX
  343. const char * browser[] = {
  344. "htmlview", "xdg-open", "x-www-browser", "firefox", "konqueror", "opera", "epiphany", "galeon", "netscape"
  345. };
  346. for(int i = 0; i < __countof(browser); i++)
  347. if(system("which " + String(browser[i])) == 0) {
  348. system(String(browser[i]) + " " + url + " &");
  349. break;
  350. }
  351. #endif
  352. }
  353. String GetDataFile(const char *filename)
  354. {
  355. String s = GetEnv("UPP_MAIN__");
  356. return s.GetCount() ? AppendFileName(s, filename) : GetExeDirFile(filename);
  357. }
  358. String GetComputerName()
  359. {
  360. char temp[256];
  361. *temp = 0;
  362. #if defined(PLATFORM_WIN32)
  363. dword w = 255;
  364. ::GetComputerNameA(temp, &w);
  365. #else
  366. gethostname(temp, sizeof(temp));
  367. #endif
  368. return FromSystemCharset(temp);
  369. }
  370. String GetUserName()
  371. {
  372. char temp[256];
  373. *temp = 0;
  374. #if defined(PLATFORM_WIN32)
  375. dword w = 255;
  376. ::GetUserNameA(temp, &w);
  377. return FromSystemCharset(temp);
  378. #else
  379. return Nvl(GetEnv("USER"), "boot");
  380. #endif
  381. }
  382. String GetDesktopManager()
  383. {
  384. #if defined(PLATFORM_WIN32) && !defined(PLATFORM_WINCE)
  385. return "windows";
  386. #endif
  387. #ifdef PLATFORM_POSIX
  388. if(GetEnv("GNOME_DESKTOP_SESSION_ID").GetCount())
  389. return "gnome";
  390. if(GetEnv("KDE_FULL_SESSION").GetCount() || GetEnv("KDEDIR").GetCount())
  391. return "kde";
  392. return GetEnv("DESKTOP_SESSION");
  393. #endif
  394. }
  395. #if defined(PLATFORM_WIN32)
  396. String GetShellFolder(int clsid)
  397. {
  398. wchar path[MAX_PATH];
  399. if(SHGetFolderPathW(NULL, clsid, NULL, /*SHGFP_TYPE_CURRENT*/0, path) == S_OK)
  400. return FromUnicodeBuffer(path);
  401. return Null;
  402. }
  403. String GetDesktopFolder() { return GetShellFolder(CSIDL_DESKTOP); }
  404. String GetProgramsFolder() { return GetShellFolder(CSIDL_PROGRAM_FILES); }
  405. String GetAppDataFolder() { return GetShellFolder(CSIDL_APPDATA);}
  406. String GetMusicFolder() { return GetShellFolder(CSIDL_MYMUSIC);}
  407. String GetPicturesFolder() { return GetShellFolder(CSIDL_MYPICTURES);}
  408. String GetVideoFolder() { return GetShellFolder(CSIDL_MYVIDEO);}
  409. String GetDocumentsFolder() { return GetShellFolder(/*CSIDL_MYDOCUMENTS*/0x0005);}
  410. String GetTemplatesFolder() { return GetShellFolder(CSIDL_TEMPLATES);}
  411. #define MY_DEFINE_KNOWN_FOLDER(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
  412. static const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
  413. MY_DEFINE_KNOWN_FOLDER(MY_FOLDERID_Downloads, 0x374de290, 0x123f, 0x4565, 0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b);
  414. String GetDownloadFolder()
  415. {
  416. static HRESULT (STDAPICALLTYPE * SHGetKnownFolderPath)(const void *rfid, DWORD dwFlags, HANDLE hToken, PWSTR *ppszPath);
  417. ONCELOCK {
  418. DllFn(SHGetKnownFolderPath, "shell32.dll", "SHGetKnownFolderPath");
  419. }
  420. if(SHGetKnownFolderPath) {
  421. PWSTR path = NULL;
  422. if(SHGetKnownFolderPath(&MY_FOLDERID_Downloads, 0, NULL, &path) == S_OK && path) {
  423. String s = FromUnicodeBuffer(path, wstrlen(path));
  424. CoTaskMemFree(path);
  425. return s;
  426. }
  427. }
  428. return Null;
  429. };
  430. #endif
  431. #ifdef PLATFORM_POSIX
  432. String GetPathXdg(String xdgConfigHome, String xdgConfigDirs)
  433. {
  434. String ret = "";
  435. if (FileExists(ret = AppendFileName(xdgConfigHome, "user-dirs.dirs"))) ;
  436. else if (FileExists(ret = AppendFileName(xdgConfigDirs, "user-dirs.defaults"))) ;
  437. else if (FileExists(ret = AppendFileName(xdgConfigDirs, "user-dirs.dirs"))) ;
  438. return ret;
  439. }
  440. String GetPathDataXdg(String fileConfig, const char *folder)
  441. {
  442. TextSettings settings;
  443. settings.Load(fileConfig);
  444. String v = settings.Get(folder);
  445. if(*v == '\"')
  446. v = v.Mid(1);
  447. if(*v.Last() == '\"')
  448. v.Trim(v.GetCount() - 1);
  449. String r;
  450. const char *s = v;
  451. while(*s) {
  452. if(*s == '$') {
  453. CParser p(s + 1);
  454. p.NoSkipSpaces();
  455. p.Spaces();
  456. if(p.IsId()) {
  457. String id = p.ReadId();
  458. r.Cat(GetEnv(id));
  459. s = p.GetPtr();
  460. }
  461. else {
  462. r.Cat('$');
  463. s++;
  464. }
  465. }
  466. else
  467. r.Cat(*s++);
  468. }
  469. return r;
  470. }
  471. String GetShellFolder(const char *local, const char *users)
  472. {
  473. String xdgConfigHome = GetEnv("XDG_CONFIG_HOME");
  474. if (xdgConfigHome == "") // By default
  475. xdgConfigHome = AppendFileName(GetHomeDirectory(), ".config");
  476. String xdgConfigDirs = GetEnv("XDG_CONFIG_DIRS");
  477. if (xdgConfigDirs == "") // By default
  478. xdgConfigDirs = "/etc/xdg";
  479. String xdgFileConfigData = GetPathXdg(xdgConfigHome, xdgConfigDirs);
  480. String ret = GetPathDataXdg(xdgFileConfigData, local);
  481. if (ret == "" && *users != '\0')
  482. return GetPathDataXdg(xdgFileConfigData, users);
  483. else
  484. return ret;
  485. }
  486. String GetDesktopFolder()
  487. {
  488. String ret = GetShellFolder("XDG_DESKTOP_DIR", "DESKTOP");
  489. if (ret.IsEmpty())
  490. return AppendFileName(GetHomeDirectory(), "Desktop");
  491. else
  492. return ret;
  493. }
  494. String GetProgramsFolder() { return String("/usr/bin"); }
  495. String GetAppDataFolder() { return GetHomeDirectory(); }
  496. String GetMusicFolder() { return GetShellFolder("XDG_MUSIC_DIR", "MUSIC"); }
  497. String GetPicturesFolder() { return GetShellFolder("XDG_PICTURES_DIR", "PICTURES"); }
  498. String GetVideoFolder() { return GetShellFolder("XDG_VIDEOS_DIR", "VIDEOS"); }
  499. String GetDocumentsFolder() { return GetShellFolder("XDG_DOCUMENTS_DIR", "DOCUMENTS"); }
  500. String GetTemplatesFolder() { return GetShellFolder("XDG_TEMPLATES_DIR", "XDG_TEMPLATES_DIR"); }
  501. String GetDownloadFolder() { return GetShellFolder("XDG_DOWNLOAD_DIR", "XDG_DOWNLOAD_DIR"); }
  502. #endif
  503. END_UPP_NAMESPACE