GUITools.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. //---------------------------------------------------------------------------
  2. #define NO_WIN32_LEAN_AND_MEAN
  3. #include <vcl.h>
  4. #pragma hdrstop
  5. #include <shlobj.h>
  6. #include <Common.h>
  7. #include "GUITools.h"
  8. #include "GUIConfiguration.h"
  9. #include <TextsCore.h>
  10. #include <CoreMain.h>
  11. #include <SessionData.h>
  12. //---------------------------------------------------------------------------
  13. #pragma package(smart_init)
  14. //---------------------------------------------------------------------------
  15. bool __fastcall FindFile(AnsiString & Path)
  16. {
  17. bool Result = FileExists(Path);
  18. if (!Result)
  19. {
  20. int Len = GetEnvironmentVariable("PATH", NULL, 0);
  21. if (Len > 0)
  22. {
  23. AnsiString Paths;
  24. Paths.SetLength(Len - 1);
  25. GetEnvironmentVariable("PATH", Paths.c_str(), Len);
  26. AnsiString NewPath = FileSearch(ExtractFileName(Path), Paths);
  27. Result = !NewPath.IsEmpty();
  28. if (Result)
  29. {
  30. Path = NewPath;
  31. }
  32. }
  33. }
  34. return Result;
  35. }
  36. //---------------------------------------------------------------------------
  37. bool __fastcall FileExistsEx(AnsiString Path)
  38. {
  39. return FindFile(Path);
  40. }
  41. //---------------------------------------------------------------------------
  42. void __fastcall OpenSessionInPutty(const AnsiString PuttyPath,
  43. TSessionData * SessionData, AnsiString Password)
  44. {
  45. AnsiString Program, Params, Dir;
  46. SplitCommand(PuttyPath, Program, Params, Dir);
  47. Program = ExpandEnvironmentVariables(Program);
  48. if (FindFile(Program))
  49. {
  50. AnsiString SessionName;
  51. TRegistryStorage * Storage = NULL;
  52. TSessionData * ExportData = NULL;
  53. TRegistryStorage * SourceStorage = NULL;
  54. try
  55. {
  56. Storage = new TRegistryStorage(Configuration->PuttySessionsKey);
  57. Storage->AccessMode = smReadWrite;
  58. // make it compatible with putty
  59. Storage->MungeStringValues = false;
  60. if (Storage->OpenRootKey(true))
  61. {
  62. if (Storage->KeyExists(SessionData->StorageKey))
  63. {
  64. SessionName = SessionData->SessionName;
  65. }
  66. else
  67. {
  68. SourceStorage = new TRegistryStorage(Configuration->PuttySessionsKey);
  69. SourceStorage->MungeStringValues = false;
  70. if (SourceStorage->OpenSubKey(StoredSessions->DefaultSettings->Name, false) &&
  71. Storage->OpenSubKey(GUIConfiguration->PuttySession, true))
  72. {
  73. Storage->Copy(SourceStorage);
  74. Storage->CloseSubKey();
  75. }
  76. ExportData = new TSessionData("");
  77. ExportData->Assign(SessionData);
  78. ExportData->Modified = true;
  79. ExportData->Name = GUIConfiguration->PuttySession;
  80. ExportData->Password = "";
  81. if (SessionData->FSProtocol == fsFTP)
  82. {
  83. if (GUIConfiguration->TelnetForFtpInPutty)
  84. {
  85. ExportData->Protocol = ptTelnet;
  86. ExportData->PortNumber = 23;
  87. // PuTTY does not allow -pw for telnet
  88. Password = "";
  89. }
  90. else
  91. {
  92. ExportData->Protocol = ptSSH;
  93. ExportData->PortNumber = 22;
  94. }
  95. }
  96. ExportData->Save(Storage, true);
  97. SessionName = GUIConfiguration->PuttySession;
  98. }
  99. }
  100. }
  101. __finally
  102. {
  103. delete Storage;
  104. delete ExportData;
  105. delete SourceStorage;
  106. }
  107. if (!Params.IsEmpty())
  108. {
  109. Params += " ";
  110. }
  111. if (!Password.IsEmpty())
  112. {
  113. Params += FORMAT("-pw \"%s\" ", (Password));
  114. }
  115. Params += FORMAT("-load \"%s\"", (SessionName));
  116. if (!ExecuteShell(Program, Params))
  117. {
  118. throw Exception(FMTLOAD(EXECUTE_APP_ERROR, (Program)));
  119. }
  120. }
  121. else
  122. {
  123. throw Exception(FMTLOAD(FILE_NOT_FOUND, (Program)));
  124. }
  125. }
  126. //---------------------------------------------------------------------------
  127. bool __fastcall ExecuteShell(const AnsiString Path, const AnsiString Params)
  128. {
  129. return ((int)ShellExecute(NULL, "open", (char*)Path.data(),
  130. (char*)Params.data(), NULL, SW_SHOWNORMAL) > 32);
  131. }
  132. //---------------------------------------------------------------------------
  133. bool __fastcall ExecuteShell(const AnsiString Path, const AnsiString Params,
  134. HANDLE & Handle)
  135. {
  136. bool Result;
  137. TShellExecuteInfo ExecuteInfo;
  138. memset(&ExecuteInfo, 0, sizeof(ExecuteInfo));
  139. ExecuteInfo.cbSize = sizeof(ExecuteInfo);
  140. ExecuteInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
  141. ExecuteInfo.hwnd = Application->Handle;
  142. ExecuteInfo.lpFile = (char*)Path.data();
  143. ExecuteInfo.lpParameters = (char*)Params.data();
  144. ExecuteInfo.nShow = SW_SHOW;
  145. Result = (ShellExecuteEx(&ExecuteInfo) != 0);
  146. if (Result)
  147. {
  148. Handle = ExecuteInfo.hProcess;
  149. }
  150. return Result;
  151. }
  152. //---------------------------------------------------------------------------
  153. bool __fastcall ExecuteShellAndWait(HWND Handle, const AnsiString Path,
  154. const AnsiString Params, TProcessMessagesEvent ProcessMessages)
  155. {
  156. bool Result;
  157. TShellExecuteInfo ExecuteInfo;
  158. memset(&ExecuteInfo, 0, sizeof(ExecuteInfo));
  159. ExecuteInfo.cbSize = sizeof(ExecuteInfo);
  160. ExecuteInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
  161. ExecuteInfo.hwnd = Handle;
  162. ExecuteInfo.lpFile = (char*)Path.data();
  163. ExecuteInfo.lpParameters = (char*)Params.data();
  164. ExecuteInfo.nShow = SW_SHOW;
  165. Result = (ShellExecuteEx(&ExecuteInfo) != 0);
  166. if (Result)
  167. {
  168. if (ProcessMessages != NULL)
  169. {
  170. unsigned long WaitResult;
  171. do
  172. {
  173. WaitResult = WaitForSingleObject(ExecuteInfo.hProcess, 200);
  174. if (WaitResult == WAIT_FAILED)
  175. {
  176. throw Exception(LoadStr(DOCUMENT_WAIT_ERROR));
  177. }
  178. ProcessMessages();
  179. }
  180. while (WaitResult == WAIT_TIMEOUT);
  181. }
  182. else
  183. {
  184. WaitForSingleObject(ExecuteInfo.hProcess, INFINITE);
  185. }
  186. }
  187. return Result;
  188. }
  189. //---------------------------------------------------------------------------
  190. bool __fastcall ExecuteShellAndWait(HWND Handle, const AnsiString Command,
  191. TProcessMessagesEvent ProcessMessages)
  192. {
  193. AnsiString Program, Params, Dir;
  194. SplitCommand(Command, Program, Params, Dir);
  195. return ExecuteShellAndWait(Handle, Program, Params, ProcessMessages);
  196. }
  197. //---------------------------------------------------------------------------
  198. bool __fastcall SpecialFolderLocation(int PathID, AnsiString & Path)
  199. {
  200. LPITEMIDLIST Pidl;
  201. char Buf[256];
  202. if (SHGetSpecialFolderLocation(NULL, PathID, &Pidl) == NO_ERROR &&
  203. SHGetPathFromIDList(Pidl, Buf))
  204. {
  205. Path = AnsiString(Buf);
  206. return true;
  207. }
  208. return false;
  209. }
  210. //---------------------------------------------------------------------------
  211. AnsiString __fastcall ItemsFormatString(const AnsiString SingleItemFormat,
  212. const AnsiString MultiItemsFormat, int Count, const AnsiString FirstItem)
  213. {
  214. AnsiString Result;
  215. if (Count == 1)
  216. {
  217. Result = FORMAT(SingleItemFormat, (FirstItem));
  218. }
  219. else
  220. {
  221. Result = FORMAT(MultiItemsFormat, (Count));
  222. }
  223. return Result;
  224. }
  225. //---------------------------------------------------------------------------
  226. AnsiString __fastcall ItemsFormatString(const AnsiString SingleItemFormat,
  227. const AnsiString MultiItemsFormat, TStrings * Items)
  228. {
  229. return ItemsFormatString(SingleItemFormat, MultiItemsFormat,
  230. Items->Count, (Items->Count > 0 ? Items->Strings[0] : AnsiString()));
  231. }
  232. //---------------------------------------------------------------------------
  233. AnsiString __fastcall FileNameFormatString(const AnsiString SingleFileFormat,
  234. const AnsiString MultiFilesFormat, TStrings * Files, bool Remote)
  235. {
  236. assert(Files != NULL);
  237. AnsiString Item;
  238. if (Files->Count > 0)
  239. {
  240. Item = Remote ? UnixExtractFileName(Files->Strings[0]) :
  241. ExtractFileName(Files->Strings[0]);
  242. }
  243. return ItemsFormatString(SingleFileFormat, MultiFilesFormat,
  244. Files->Count, Item);
  245. }
  246. //---------------------------------------------------------------------
  247. AnsiString __fastcall FormatBytes(__int64 Bytes, bool UseOrders)
  248. {
  249. AnsiString Result;
  250. if (!UseOrders || (Bytes < __int64(100*1024)))
  251. {
  252. Result = FormatFloat("#,##0 \"B\"", Bytes);
  253. }
  254. else if (Bytes < __int64(100*1024*1024))
  255. {
  256. Result = FormatFloat("#,##0 \"KiB\"", Bytes / 1024);
  257. }
  258. else
  259. {
  260. Result = FormatFloat("#,##0 \"MiB\"", Bytes / (1024*1024));
  261. }
  262. return Result;
  263. }
  264. //---------------------------------------------------------------------------
  265. AnsiString __fastcall UniqTempDir(const AnsiString BaseDir, const AnsiString Identity,
  266. bool Mask)
  267. {
  268. AnsiString TempDir;
  269. do
  270. {
  271. TempDir = BaseDir.IsEmpty() ? SystemTemporaryDirectory() : BaseDir;
  272. TempDir = IncludeTrailingBackslash(TempDir) + Identity;
  273. if (Mask)
  274. {
  275. TempDir += "?????";
  276. }
  277. else
  278. {
  279. TempDir += IncludeTrailingBackslash(FormatDateTime("nnzzz", Now()));
  280. };
  281. }
  282. while (!Mask && DirectoryExists(TempDir));
  283. return TempDir;
  284. }
  285. //---------------------------------------------------------------------------
  286. bool __fastcall DeleteDirectory(const AnsiString DirName)
  287. {
  288. TSearchRec sr;
  289. bool retval = true;
  290. if (FindFirst(DirName + "\\*", faAnyFile, sr) == 0) // VCL Function
  291. {
  292. if (FLAGSET(sr.Attr, faDirectory))
  293. {
  294. if (sr.Name != "." && sr.Name != "..")
  295. retval = DeleteDirectory(DirName + "\\" + sr.Name);
  296. }
  297. else
  298. {
  299. retval = DeleteFile(DirName + "\\" + sr.Name);
  300. }
  301. if (retval)
  302. {
  303. while (FindNext(sr) == 0)
  304. { // VCL Function
  305. if (FLAGSET(sr.Attr, faDirectory))
  306. {
  307. if (sr.Name != "." && sr.Name != "..")
  308. retval = DeleteDirectory(DirName + "\\" + sr.Name);
  309. }
  310. else
  311. {
  312. retval = DeleteFile(DirName + "\\" + sr.Name);
  313. }
  314. if (!retval) break;
  315. }
  316. }
  317. }
  318. FindClose(sr);
  319. if (retval) retval = RemoveDir(DirName); // VCL function
  320. return retval;
  321. }
  322. //---------------------------------------------------------------------------
  323. AnsiString __fastcall FormatDateTimeSpan(const AnsiString TimeFormat, TDateTime DateTime)
  324. {
  325. AnsiString Result;
  326. if (int(DateTime) > 0)
  327. {
  328. Result = IntToStr(int(DateTime)) + ", ";
  329. }
  330. // days are decremented, because when there are to many of them,
  331. // "integer overflow" error occurs
  332. Result += FormatDateTime(TimeFormat, DateTime - int(DateTime));
  333. return Result;
  334. }
  335. //---------------------------------------------------------------------------
  336. TLocalCustomCommand::TLocalCustomCommand()
  337. {
  338. }
  339. //---------------------------------------------------------------------------
  340. TLocalCustomCommand::TLocalCustomCommand(const TCustomCommandData & Data,
  341. const AnsiString & Path) :
  342. TFileCustomCommand(Data, Path)
  343. {
  344. }
  345. //---------------------------------------------------------------------------
  346. TLocalCustomCommand::TLocalCustomCommand(const TCustomCommandData & Data,
  347. const AnsiString & Path, const AnsiString & FileName,
  348. const AnsiString & LocalFileName, const AnsiString & FileList) :
  349. TFileCustomCommand(Data, Path, FileName, FileList)
  350. {
  351. FLocalFileName = LocalFileName;
  352. }
  353. //---------------------------------------------------------------------------
  354. int __fastcall TLocalCustomCommand::PatternLen(int Index, char PatternCmd)
  355. {
  356. int Len;
  357. if (PatternCmd == '^')
  358. {
  359. Len = 3;
  360. }
  361. else
  362. {
  363. Len = TFileCustomCommand::PatternLen(Index, PatternCmd);
  364. }
  365. return Len;
  366. }
  367. //---------------------------------------------------------------------------
  368. bool __fastcall TLocalCustomCommand::PatternReplacement(int Index,
  369. const AnsiString & Pattern, AnsiString & Replacement, bool & Delimit)
  370. {
  371. bool Result;
  372. if (Pattern == "!^!")
  373. {
  374. Replacement = FLocalFileName;
  375. Result = true;
  376. }
  377. else
  378. {
  379. Result = TFileCustomCommand::PatternReplacement(Index, Pattern, Replacement, Delimit);
  380. }
  381. return Result;
  382. }
  383. //---------------------------------------------------------------------------
  384. void __fastcall TLocalCustomCommand::DelimitReplacement(
  385. AnsiString & /*Replacement*/, char /*Quote*/)
  386. {
  387. // never delimit local commands
  388. }
  389. //---------------------------------------------------------------------------
  390. bool __fastcall TLocalCustomCommand::HasLocalFileName(const AnsiString & Command)
  391. {
  392. return FindPattern(Command, '^');
  393. }
  394. //---------------------------------------------------------------------------
  395. bool __fastcall TLocalCustomCommand::IsFileCommand(const AnsiString & Command)
  396. {
  397. return TFileCustomCommand::IsFileCommand(Command) || HasLocalFileName(Command);
  398. }