Common.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "Common.h"
  5. #include "Exceptions.h"
  6. #include "TextsCore.h"
  7. #include <math.h>
  8. #include <shellapi.h>
  9. //---------------------------------------------------------------------------
  10. #pragma package(smart_init)
  11. //---------------------------------------------------------------------------
  12. const char EngShortMonthNames[12][4] =
  13. {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  14. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  15. //---------------------------------------------------------------------------
  16. AnsiString ReplaceChar(AnsiString Str, Char A, Char B)
  17. {
  18. for (Integer Index = 0; Index < Str.Length(); Index++)
  19. if (Str[Index+1] == A) Str[Index+1] = B;
  20. return Str;
  21. }
  22. //---------------------------------------------------------------------------
  23. AnsiString DeleteChar(AnsiString Str, Char C)
  24. {
  25. int P;
  26. while ((P = Str.Pos(C)) > 0)
  27. {
  28. Str.Delete(P, 1);
  29. }
  30. return Str;
  31. }
  32. //---------------------------------------------------------------------------
  33. void PackStr(AnsiString &Str)
  34. {
  35. // Following will free unnecessary bytes
  36. Str = Str.c_str();
  37. }
  38. //---------------------------------------------------------------------------
  39. AnsiString GetTemporaryPath()
  40. {
  41. AnsiString Path;
  42. Path.SetLength(255);
  43. GetTempPath(Path.Length(), Path.c_str());
  44. PackStr(Path);
  45. if (!Path.IsPathDelimiter(Path.Length()))
  46. {
  47. Path += '\\';
  48. }
  49. return Path;
  50. }
  51. //---------------------------------------------------------------------------
  52. AnsiString MakeValidFileName(AnsiString FileName)
  53. {
  54. AnsiString IllegalChars = ";,=+<>|\"[] \\/?*";
  55. for (int Index = 0; Index < IllegalChars.Length(); Index++)
  56. {
  57. ReplaceChar(FileName, IllegalChars[Index+1], '-');
  58. }
  59. return FileName;
  60. }
  61. //---------------------------------------------------------------------------
  62. AnsiString RootKeyToStr(HKEY RootKey)
  63. {
  64. if (RootKey == HKEY_USERS) return "HKEY_USERS";
  65. else
  66. if (RootKey == HKEY_LOCAL_MACHINE) return "HKEY_LOCAL_MACHINE";
  67. else
  68. if (RootKey == HKEY_CURRENT_USER) return "HKEY_CURRENT_USER";
  69. else
  70. if (RootKey == HKEY_CLASSES_ROOT) return "HKEY_CLASSES_ROOT";
  71. else
  72. if (RootKey == HKEY_CURRENT_CONFIG) return "HKEY_CURRENT_CONFIG";
  73. else
  74. if (RootKey == HKEY_DYN_DATA) return "HKEY_DYN_DATA";
  75. else
  76. { Abort(); return ""; };
  77. }
  78. //---------------------------------------------------------------------------
  79. AnsiString BooleanToEngStr(bool B)
  80. {
  81. return B ? "Yes" : "No";
  82. }
  83. //---------------------------------------------------------------------------
  84. AnsiString BooleanToStr(bool B)
  85. {
  86. return B ? LoadStr(YES_STR) : LoadStr(NO_STR);
  87. }
  88. //---------------------------------------------------------------------------
  89. AnsiString CutToChar(AnsiString &Str, Char Ch, bool Trim)
  90. {
  91. Integer P = Str.Pos(Ch);
  92. AnsiString Result;
  93. if (P)
  94. {
  95. Result = Str.SubString(1, P-1);
  96. Str.Delete(1, P);
  97. }
  98. else
  99. {
  100. Result = Str;
  101. Str = "";
  102. }
  103. if (Trim)
  104. {
  105. Result = Result.TrimRight();
  106. Str = Str.TrimLeft();
  107. }
  108. return Result;
  109. }
  110. //---------------------------------------------------------------------------
  111. AnsiString ExceptionLogString(Exception *E)
  112. {
  113. assert(E);
  114. if (E->InheritsFrom(__classid(Exception)))
  115. {
  116. AnsiString Msg;
  117. Msg = FORMAT("(%s) %s", (E->ClassName(), E->Message));
  118. if (E->InheritsFrom(__classid(ExtException)))
  119. {
  120. TStrings * MoreMessages = ((ExtException*)E)->MoreMessages;
  121. if (MoreMessages)
  122. {
  123. Msg += "\n" +
  124. StringReplace(MoreMessages->Text, "\r", "", TReplaceFlags() << rfReplaceAll);
  125. }
  126. }
  127. return Msg;
  128. }
  129. else
  130. {
  131. char Buffer[1024];
  132. ExceptionErrorMessage(ExceptObject(), ExceptAddr(), Buffer, sizeof(Buffer));
  133. return AnsiString(Buffer);
  134. }
  135. }
  136. //---------------------------------------------------------------------------
  137. bool IsDots(const AnsiString Str)
  138. {
  139. char * str = Str.c_str();
  140. return (str[strspn(str, ".")] == '\0');
  141. }
  142. //---------------------------------------------------------------------------
  143. AnsiString __fastcall SystemTemporaryDirectory()
  144. {
  145. AnsiString TempDir;
  146. TempDir.SetLength(MAX_PATH);
  147. TempDir.SetLength(GetTempPath(MAX_PATH, TempDir.c_str()));
  148. return TempDir;
  149. }
  150. //---------------------------------------------------------------------------
  151. AnsiString __fastcall StripPathQuotes(const AnsiString Path)
  152. {
  153. if ((Path.Length() >= 2) &&
  154. (Path[1] == '\"') && (Path[Path.Length()] == '\"'))
  155. {
  156. return Path.SubString(2, Path.Length() - 2);
  157. }
  158. else
  159. {
  160. return Path;
  161. }
  162. }
  163. //---------------------------------------------------------------------------
  164. AnsiString __fastcall AddPathQuotes(AnsiString Path)
  165. {
  166. Path = StripPathQuotes(Path);
  167. if (Path.Pos(" "))
  168. {
  169. Path = "\"" + Path + "\"";
  170. }
  171. return Path;
  172. }
  173. //---------------------------------------------------------------------------
  174. void __fastcall SplitCommand(AnsiString Command, AnsiString &Program,
  175. AnsiString & Params, AnsiString & Dir)
  176. {
  177. Command = Command.Trim();
  178. Params = "";
  179. Dir = "";
  180. if (!Command.IsEmpty() && (Command[1] == '\"'))
  181. {
  182. Command.Delete(1, 1);
  183. int P = Command.Pos('"');
  184. if (P)
  185. {
  186. Program = Command.SubString(1, P-1).Trim();
  187. Params = Command.SubString(P + 1, Command.Length() - P).Trim();
  188. }
  189. else
  190. {
  191. throw Exception(FMTLOAD(INVALID_SHELL_COMMAND, ("\"" + Command)));
  192. }
  193. }
  194. else
  195. {
  196. int P = Command.Pos(" ");
  197. if (P)
  198. {
  199. Program = Command.SubString(1, P).Trim();
  200. Params = Command.SubString(P + 1, Command.Length() - P).Trim();
  201. }
  202. else
  203. {
  204. Program = Command;
  205. }
  206. }
  207. int B = Program.LastDelimiter("\\/");
  208. if (B)
  209. {
  210. Dir = Program.SubString(1, B).Trim();
  211. }
  212. }
  213. //---------------------------------------------------------------------------
  214. AnsiString __fastcall FormatCommand(AnsiString Program, AnsiString Params)
  215. {
  216. Program = Program.Trim();
  217. Params = Params.Trim();
  218. if (!Params.IsEmpty()) Params = " " + Params;
  219. if (Program.Pos(" ")) Program = "\"" + Program + "\"";
  220. return Program + Params;
  221. }
  222. //---------------------------------------------------------------------------
  223. bool __fastcall IsDisplayableStr(const AnsiString Str)
  224. {
  225. bool Displayable = true;
  226. int Index = 1;
  227. while ((Index <= Str.Length()) && Displayable)
  228. {
  229. if (Str[Index] < '\32')
  230. {
  231. Displayable = false;
  232. }
  233. Index++;
  234. }
  235. return Displayable;
  236. }
  237. //---------------------------------------------------------------------------
  238. AnsiString __fastcall StrToHex(const AnsiString Str)
  239. {
  240. AnsiString Result;
  241. for (int i = 1; i <= Str.Length(); i++)
  242. {
  243. Result += IntToHex(Str[i], 2);
  244. }
  245. return Result;
  246. }
  247. //---------------------------------------------------------------------------
  248. AnsiString __fastcall HexToStr(const AnsiString Hex)
  249. {
  250. static AnsiString Digits = "01234556789ABCDEF";
  251. AnsiString Result;
  252. int L, P1, P2;
  253. L = Hex.Length();
  254. if (L % 2 == 0)
  255. {
  256. for (int i = 1; i <= Hex.Length(); i += 2)
  257. {
  258. P1 = Digits.Pos(Hex[i]);
  259. P2 = Digits.Pos(Hex[i + 1]);
  260. if (P1 <= 0 || P2 <= 0)
  261. {
  262. break;
  263. }
  264. else
  265. {
  266. Result += static_cast<char>((P1 - 1) * 16 + P2 - 1);
  267. }
  268. }
  269. }
  270. return Result;
  271. }
  272. //---------------------------------------------------------------------------
  273. bool __fastcall FileSearchRec(const AnsiString FileName, TSearchRec & Rec)
  274. {
  275. int FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
  276. bool Result = (FindFirst(FileName, FindAttrs, Rec) == 0);
  277. if (Result)
  278. {
  279. FindClose(Rec);
  280. }
  281. return Result;
  282. }
  283. //---------------------------------------------------------------------------
  284. void __fastcall ProcessLocalDirectory(AnsiString DirName,
  285. TProcessLocalFileEvent CallBackFunc, void * Param,
  286. int FindAttrs)
  287. {
  288. assert(CallBackFunc);
  289. if (FindAttrs < 0)
  290. {
  291. FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
  292. }
  293. TSearchRec SearchRec;
  294. DirName = IncludeTrailingBackslash(DirName);
  295. if (FindFirst(DirName + "*.*", FindAttrs, SearchRec) == 0)
  296. {
  297. try
  298. {
  299. do
  300. {
  301. if ((SearchRec.Name != ".") && (SearchRec.Name != ".."))
  302. {
  303. if (SearchRec.Attr & faDirectory)
  304. {
  305. ProcessLocalDirectory(DirName + SearchRec.Name, CallBackFunc,
  306. Param, FindAttrs);
  307. }
  308. CallBackFunc(DirName + SearchRec.Name, SearchRec, Param);
  309. }
  310. } while (FindNext(SearchRec) == 0);
  311. }
  312. __finally
  313. {
  314. FindClose(SearchRec);
  315. }
  316. }
  317. }
  318. //---------------------------------------------------------------------------
  319. void __fastcall DateTimeParams(TDateTime * AUnixEpoch,
  320. double * ADifference, long * ADifferenceSec)
  321. {
  322. static double Difference;
  323. static long DifferenceSec;
  324. static TDateTime UnixEpoch = 0;
  325. if (double(UnixEpoch) == 0)
  326. {
  327. TIME_ZONE_INFORMATION TZI;
  328. unsigned long GTZI;
  329. GTZI = GetTimeZoneInformation(&TZI);
  330. switch (GTZI) {
  331. case TIME_ZONE_ID_UNKNOWN:
  332. Difference = 0;
  333. break;
  334. case TIME_ZONE_ID_STANDARD:
  335. DifferenceSec = TZI.Bias + TZI.StandardBias;
  336. break;
  337. case TIME_ZONE_ID_DAYLIGHT:
  338. DifferenceSec = TZI.Bias + TZI.DaylightBias;
  339. break;
  340. case TIME_ZONE_ID_INVALID:
  341. default:
  342. throw Exception(TIMEZONE_ERROR);
  343. }
  344. // Is it same as SysUtils::UnixDateDelta = 25569 ??
  345. UnixEpoch = EncodeDate(1970, 1, 1);
  346. Difference = double(DifferenceSec) / 1440;
  347. DifferenceSec *= 60;
  348. }
  349. if (AUnixEpoch) *AUnixEpoch = UnixEpoch;
  350. if (ADifference) *ADifference = Difference;
  351. if (ADifferenceSec) *ADifferenceSec = DifferenceSec;
  352. }
  353. //---------------------------------------------------------------------------
  354. TDateTime __fastcall UnixToDateTime(unsigned long TimeStamp)
  355. {
  356. TDateTime UnixEpoch;
  357. double Difference;
  358. DateTimeParams(&UnixEpoch, &Difference, NULL);
  359. TDateTime Result;
  360. Result = UnixEpoch + (double(TimeStamp) / 86400) - Difference;
  361. return Result;
  362. }
  363. //---------------------------------------------------------------------------
  364. inline __int64 __fastcall Round(double Number)
  365. {
  366. double Floor = floor(Number);
  367. double Ceil = ceil(Number);
  368. return ((Number - Floor) > (Ceil - Number)) ? Ceil : Floor;
  369. }
  370. //---------------------------------------------------------------------------
  371. FILETIME __fastcall DateTimeToFileTime(const TDateTime DateTime)
  372. {
  373. __int64 UnixTimeStamp;
  374. FILETIME Result;
  375. TDateTime UnixEpoch;
  376. long Difference;
  377. DateTimeParams(&UnixEpoch, NULL, &Difference);
  378. UnixTimeStamp = Round(double(DateTime - UnixEpoch) * 86400) + Difference;
  379. TIME_POSIX_TO_WIN(UnixTimeStamp, Result);
  380. return Result;
  381. }
  382. //---------------------------------------------------------------------------
  383. TDateTime __fastcall AdjustDateTimeFromUnix(const TDateTime DateTime)
  384. {
  385. // to be implemented
  386. return DateTime;
  387. }
  388. //---------------------------------------------------------------------------
  389. __inline static bool __fastcall UnifySignificance(unsigned short & V1,
  390. unsigned short & V2)
  391. {
  392. bool Result = (V1 == 0) || (V2 == 0);
  393. if (Result)
  394. {
  395. V1 = 0;
  396. V2 = 0;
  397. }
  398. return Result;
  399. }
  400. //---------------------------------------------------------------------------
  401. void __fastcall UnifyDateTimePrecision(TDateTime & DateTime1, TDateTime & DateTime2)
  402. {
  403. unsigned short Y1, M1, D1, H1, N1, S1, MS1;
  404. unsigned short Y2, M2, D2, H2, N2, S2, MS2;
  405. bool Changed;
  406. if (DateTime1 != DateTime2)
  407. {
  408. DateTime1.DecodeDate(&Y1, &M1, &D1);
  409. DateTime1.DecodeTime(&H1, &N1, &S1, &MS1);
  410. DateTime2.DecodeDate(&Y2, &M2, &D2);
  411. DateTime2.DecodeTime(&H2, &N2, &S2, &MS2);
  412. Changed = UnifySignificance(MS1, MS2);
  413. if (Changed && UnifySignificance(S1, S2) && UnifySignificance(N1, N2) &&
  414. UnifySignificance(H1, H2) && UnifySignificance(D1, D2) &&
  415. UnifySignificance(M1, M2))
  416. {
  417. UnifySignificance(Y1, Y2);
  418. }
  419. if (Changed)
  420. {
  421. DateTime1 = EncodeDate(Y1, M1, D1) + EncodeTime(H1, N1, S1, MS1);
  422. DateTime2 = EncodeDate(Y2, M2, D2) + EncodeTime(H2, N2, S2, MS2);
  423. }
  424. }
  425. }
  426. //---------------------------------------------------------------------------
  427. bool __fastcall RecursiveDeleteFile(const AnsiString FileName, bool ToRecycleBin)
  428. {
  429. SHFILEOPSTRUCT Data;
  430. memset(&Data, 0, sizeof(Data));
  431. Data.hwnd = NULL;
  432. Data.wFunc = FO_DELETE;
  433. AnsiString FileList(FileName);
  434. FileList.SetLength(FileList.Length() + 2);
  435. FileList[FileList.Length() - 1] = '\0';
  436. FileList[FileList.Length()] = '\0';
  437. Data.pFrom = FileList.c_str();
  438. Data.pTo = "";
  439. Data.fFlags = FOF_NOCONFIRMATION | FOF_RENAMEONCOLLISION | FOF_NOCONFIRMMKDIR |
  440. FOF_NOERRORUI | FOF_SILENT;
  441. if (ToRecycleBin)
  442. {
  443. Data.fFlags |= FOF_ALLOWUNDO;
  444. }
  445. int Result = SHFileOperation(&Data);
  446. return (Result == 0);
  447. }