Common.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "Common.h"
  5. #include "Exceptions.h"
  6. #include "TextsCore.h"
  7. #include "Interface.h"
  8. #include <StrUtils.hpp>
  9. #include <math.h>
  10. #include <shellapi.h>
  11. //---------------------------------------------------------------------------
  12. #pragma package(smart_init)
  13. //---------------------------------------------------------------------------
  14. //---------------------------------------------------------------------------
  15. // TCriticalSection
  16. //---------------------------------------------------------------------------
  17. __fastcall TCriticalSection::TCriticalSection()
  18. {
  19. FAcquired = 0;
  20. InitializeCriticalSection(&FSection);
  21. }
  22. //---------------------------------------------------------------------------
  23. __fastcall TCriticalSection::~TCriticalSection()
  24. {
  25. assert(FAcquired == 0);
  26. DeleteCriticalSection(&FSection);
  27. }
  28. //---------------------------------------------------------------------------
  29. void __fastcall TCriticalSection::Enter()
  30. {
  31. EnterCriticalSection(&FSection);
  32. FAcquired++;
  33. }
  34. //---------------------------------------------------------------------------
  35. void __fastcall TCriticalSection::Leave()
  36. {
  37. FAcquired--;
  38. LeaveCriticalSection(&FSection);
  39. }
  40. //---------------------------------------------------------------------------
  41. // TGuard
  42. //---------------------------------------------------------------------------
  43. __fastcall TGuard::TGuard(TCriticalSection * ACriticalSection) :
  44. FCriticalSection(ACriticalSection)
  45. {
  46. assert(ACriticalSection != NULL);
  47. FCriticalSection->Enter();
  48. }
  49. //---------------------------------------------------------------------------
  50. __fastcall TGuard::~TGuard()
  51. {
  52. FCriticalSection->Leave();
  53. }
  54. //---------------------------------------------------------------------------
  55. // TUnguard
  56. //---------------------------------------------------------------------------
  57. __fastcall TUnguard::TUnguard(TCriticalSection * ACriticalSection) :
  58. FCriticalSection(ACriticalSection)
  59. {
  60. assert(ACriticalSection != NULL);
  61. FCriticalSection->Leave();
  62. }
  63. //---------------------------------------------------------------------------
  64. __fastcall TUnguard::~TUnguard()
  65. {
  66. FCriticalSection->Enter();
  67. }
  68. //---------------------------------------------------------------------------
  69. //---------------------------------------------------------------------------
  70. const char EngShortMonthNames[12][4] =
  71. {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  72. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  73. //---------------------------------------------------------------------------
  74. AnsiString ReplaceChar(AnsiString Str, Char A, Char B)
  75. {
  76. for (Integer Index = 0; Index < Str.Length(); Index++)
  77. if (Str[Index+1] == A) Str[Index+1] = B;
  78. return Str;
  79. }
  80. //---------------------------------------------------------------------------
  81. AnsiString DeleteChar(AnsiString Str, Char C)
  82. {
  83. int P;
  84. while ((P = Str.Pos(C)) > 0)
  85. {
  86. Str.Delete(P, 1);
  87. }
  88. return Str;
  89. }
  90. //---------------------------------------------------------------------------
  91. void PackStr(AnsiString &Str)
  92. {
  93. // Following will free unnecessary bytes
  94. Str = Str.c_str();
  95. }
  96. //---------------------------------------------------------------------------
  97. AnsiString MakeValidFileName(AnsiString FileName)
  98. {
  99. AnsiString IllegalChars = ";,=+<>|\"[] \\/?*";
  100. for (int Index = 0; Index < IllegalChars.Length(); Index++)
  101. {
  102. FileName = ReplaceChar(FileName, IllegalChars[Index+1], '-');
  103. }
  104. return FileName;
  105. }
  106. //---------------------------------------------------------------------------
  107. AnsiString RootKeyToStr(HKEY RootKey)
  108. {
  109. if (RootKey == HKEY_USERS) return "HKEY_USERS";
  110. else
  111. if (RootKey == HKEY_LOCAL_MACHINE) return "HKEY_LOCAL_MACHINE";
  112. else
  113. if (RootKey == HKEY_CURRENT_USER) return "HKEY_CURRENT_USER";
  114. else
  115. if (RootKey == HKEY_CLASSES_ROOT) return "HKEY_CLASSES_ROOT";
  116. else
  117. if (RootKey == HKEY_CURRENT_CONFIG) return "HKEY_CURRENT_CONFIG";
  118. else
  119. if (RootKey == HKEY_DYN_DATA) return "HKEY_DYN_DATA";
  120. else
  121. { Abort(); return ""; };
  122. }
  123. //---------------------------------------------------------------------------
  124. AnsiString BooleanToEngStr(bool B)
  125. {
  126. return B ? "Yes" : "No";
  127. }
  128. //---------------------------------------------------------------------------
  129. AnsiString BooleanToStr(bool B)
  130. {
  131. return B ? LoadStr(YES_STR) : LoadStr(NO_STR);
  132. }
  133. //---------------------------------------------------------------------------
  134. AnsiString DefaultStr(const AnsiString & Str, const AnsiString & Default)
  135. {
  136. if (!Str.IsEmpty())
  137. {
  138. return Str;
  139. }
  140. else
  141. {
  142. return Default;
  143. }
  144. }
  145. //---------------------------------------------------------------------------
  146. AnsiString CutToChar(AnsiString &Str, Char Ch, bool Trim)
  147. {
  148. Integer P = Str.Pos(Ch);
  149. AnsiString Result;
  150. if (P)
  151. {
  152. Result = Str.SubString(1, P-1);
  153. Str.Delete(1, P);
  154. }
  155. else
  156. {
  157. Result = Str;
  158. Str = "";
  159. }
  160. if (Trim)
  161. {
  162. Result = Result.TrimRight();
  163. Str = Str.TrimLeft();
  164. }
  165. return Result;
  166. }
  167. //---------------------------------------------------------------------------
  168. AnsiString CutToChars(AnsiString & Str, AnsiString Chs, bool Trim,
  169. char * Delimiter)
  170. {
  171. int P;
  172. for (P = 1; P <= Str.Length(); P++)
  173. {
  174. if (IsDelimiter(Chs, Str, P))
  175. {
  176. break;
  177. }
  178. }
  179. AnsiString Result;
  180. if (P <= Str.Length())
  181. {
  182. if (Delimiter != NULL)
  183. {
  184. *Delimiter = Str[P];
  185. }
  186. Result = Str.SubString(1, P-1);
  187. Str.Delete(1, P);
  188. }
  189. else
  190. {
  191. if (Delimiter != NULL)
  192. {
  193. *Delimiter = '\0';
  194. }
  195. Result = Str;
  196. Str = "";
  197. }
  198. if (Trim)
  199. {
  200. Result = Result.TrimRight();
  201. Str = Str.TrimLeft();
  202. }
  203. return Result;
  204. }
  205. //---------------------------------------------------------------------------
  206. AnsiString DelimitStr(AnsiString Str, AnsiString Chars)
  207. {
  208. for (int i = 1; i <= Str.Length(); i++)
  209. {
  210. if (Str.IsDelimiter(Chars, i))
  211. {
  212. Str.Insert("\\", i);
  213. i++;
  214. }
  215. }
  216. return Str;
  217. }
  218. //---------------------------------------------------------------------------
  219. AnsiString ShellDelimitStr(AnsiString Str, char Quote)
  220. {
  221. AnsiString Chars = "$\\";
  222. if (Quote == '"')
  223. {
  224. Chars += "`\"";
  225. }
  226. return DelimitStr(Str, Chars);
  227. }
  228. //---------------------------------------------------------------------------
  229. AnsiString ExceptionLogString(Exception *E)
  230. {
  231. assert(E);
  232. if (E->InheritsFrom(__classid(Exception)))
  233. {
  234. AnsiString Msg;
  235. Msg = FORMAT("(%s) %s", (E->ClassName(), E->Message));
  236. if (E->InheritsFrom(__classid(ExtException)))
  237. {
  238. TStrings * MoreMessages = ((ExtException*)E)->MoreMessages;
  239. if (MoreMessages)
  240. {
  241. Msg += "\n" +
  242. StringReplace(MoreMessages->Text, "\r", "", TReplaceFlags() << rfReplaceAll);
  243. }
  244. }
  245. return Msg;
  246. }
  247. else
  248. {
  249. char Buffer[1024];
  250. ExceptionErrorMessage(ExceptObject(), ExceptAddr(), Buffer, sizeof(Buffer));
  251. return AnsiString(Buffer);
  252. }
  253. }
  254. //---------------------------------------------------------------------------
  255. bool IsDots(const AnsiString Str)
  256. {
  257. char * str = Str.c_str();
  258. return (str[strspn(str, ".")] == '\0');
  259. }
  260. //---------------------------------------------------------------------------
  261. AnsiString __fastcall SystemTemporaryDirectory()
  262. {
  263. AnsiString TempDir;
  264. TempDir.SetLength(MAX_PATH);
  265. TempDir.SetLength(GetTempPath(MAX_PATH, TempDir.c_str()));
  266. return TempDir;
  267. }
  268. //---------------------------------------------------------------------------
  269. AnsiString __fastcall StripPathQuotes(const AnsiString Path)
  270. {
  271. if ((Path.Length() >= 2) &&
  272. (Path[1] == '\"') && (Path[Path.Length()] == '\"'))
  273. {
  274. return Path.SubString(2, Path.Length() - 2);
  275. }
  276. else
  277. {
  278. return Path;
  279. }
  280. }
  281. //---------------------------------------------------------------------------
  282. AnsiString __fastcall AddPathQuotes(AnsiString Path)
  283. {
  284. Path = StripPathQuotes(Path);
  285. if (Path.Pos(" "))
  286. {
  287. Path = "\"" + Path + "\"";
  288. }
  289. return Path;
  290. }
  291. //---------------------------------------------------------------------------
  292. void __fastcall SplitCommand(AnsiString Command, AnsiString &Program,
  293. AnsiString & Params, AnsiString & Dir)
  294. {
  295. Command = Command.Trim();
  296. Params = "";
  297. Dir = "";
  298. if (!Command.IsEmpty() && (Command[1] == '\"'))
  299. {
  300. Command.Delete(1, 1);
  301. int P = Command.Pos('"');
  302. if (P)
  303. {
  304. Program = Command.SubString(1, P-1).Trim();
  305. Params = Command.SubString(P + 1, Command.Length() - P).Trim();
  306. }
  307. else
  308. {
  309. throw Exception(FMTLOAD(INVALID_SHELL_COMMAND, ("\"" + Command)));
  310. }
  311. }
  312. else
  313. {
  314. int P = Command.Pos(" ");
  315. if (P)
  316. {
  317. Program = Command.SubString(1, P).Trim();
  318. Params = Command.SubString(P + 1, Command.Length() - P).Trim();
  319. }
  320. else
  321. {
  322. Program = Command;
  323. }
  324. }
  325. int B = Program.LastDelimiter("\\/");
  326. if (B)
  327. {
  328. Dir = Program.SubString(1, B).Trim();
  329. }
  330. }
  331. //---------------------------------------------------------------------------
  332. AnsiString __fastcall ExtractProgram(AnsiString Command)
  333. {
  334. AnsiString Program;
  335. AnsiString Params;
  336. AnsiString Dir;
  337. SplitCommand(Command, Program, Params, Dir);
  338. return Program;
  339. }
  340. //---------------------------------------------------------------------------
  341. AnsiString __fastcall FormatCommand(AnsiString Program, AnsiString Params)
  342. {
  343. Program = Program.Trim();
  344. Params = Params.Trim();
  345. if (!Params.IsEmpty()) Params = " " + Params;
  346. if (Program.Pos(" ")) Program = "\"" + Program + "\"";
  347. return Program + Params;
  348. }
  349. //---------------------------------------------------------------------------
  350. const char ShellCommandFileNamePattern[] = "!.!";
  351. //---------------------------------------------------------------------------
  352. void __fastcall ReformatFileNameCommand(AnsiString & Command)
  353. {
  354. AnsiString Program, Params, Dir;
  355. SplitCommand(Command, Program, Params, Dir);
  356. if (Params.Pos(ShellCommandFileNamePattern) == 0)
  357. {
  358. Params = Params + (Params.IsEmpty() ? "" : " ") + ShellCommandFileNamePattern;
  359. }
  360. Command = FormatCommand(Program, Params);
  361. }
  362. //---------------------------------------------------------------------------
  363. AnsiString __fastcall ExpandFileNameCommand(const AnsiString Command,
  364. const AnsiString FileName)
  365. {
  366. return AnsiReplaceStr(Command, ShellCommandFileNamePattern,
  367. AddPathQuotes(FileName));
  368. }
  369. //---------------------------------------------------------------------------
  370. AnsiString __fastcall ExpandEnvironmentVariables(const AnsiString & Str)
  371. {
  372. AnsiString Buf;
  373. unsigned int Size = 1024;
  374. Buf.SetLength(Size);
  375. Buf.Unique();
  376. unsigned int Len = ExpandEnvironmentStrings(Str.c_str(), Buf.c_str(), Size);
  377. if (Len > Size)
  378. {
  379. Buf.SetLength(Len);
  380. Buf.Unique();
  381. ExpandEnvironmentStrings(Str.c_str(), Buf.c_str(), Len);
  382. }
  383. PackStr(Buf);
  384. return Buf;
  385. }
  386. //---------------------------------------------------------------------------
  387. bool __fastcall CompareFileName(const AnsiString & Path1, const AnsiString & Path2)
  388. {
  389. AnsiString ShortPath1 = ExtractShortPathName(Path1);
  390. AnsiString ShortPath2 = ExtractShortPathName(Path2);
  391. bool Result;
  392. // ExtractShortPathName returns empty string if file does not exist
  393. if (ShortPath1.IsEmpty() || ShortPath2.IsEmpty())
  394. {
  395. Result = AnsiSameText(Path1, Path2);
  396. }
  397. else
  398. {
  399. Result = AnsiSameText(ExtractShortPathName(Path1), ExtractShortPathName(Path2));
  400. }
  401. return Result;
  402. }
  403. //---------------------------------------------------------------------------
  404. bool __fastcall ComparePaths(const AnsiString & Path1, const AnsiString & Path2)
  405. {
  406. // TODO: ExpandUNCFileName
  407. return AnsiSameText(IncludeTrailingBackslash(Path1), IncludeTrailingBackslash(Path2));
  408. }
  409. //---------------------------------------------------------------------------
  410. bool __fastcall IsDisplayableStr(const AnsiString Str)
  411. {
  412. bool Displayable = true;
  413. int Index = 1;
  414. while ((Index <= Str.Length()) && Displayable)
  415. {
  416. if (Str[Index] < '\32')
  417. {
  418. Displayable = false;
  419. }
  420. Index++;
  421. }
  422. return Displayable;
  423. }
  424. //---------------------------------------------------------------------------
  425. AnsiString __fastcall CharToHex(char Ch)
  426. {
  427. return IntToHex((unsigned char)Ch, 2);
  428. }
  429. //---------------------------------------------------------------------------
  430. AnsiString __fastcall StrToHex(const AnsiString Str)
  431. {
  432. AnsiString Result;
  433. for (int i = 1; i <= Str.Length(); i++)
  434. {
  435. Result += CharToHex(Str[i]);
  436. }
  437. return Result;
  438. }
  439. //---------------------------------------------------------------------------
  440. AnsiString __fastcall HexToStr(const AnsiString Hex)
  441. {
  442. static AnsiString Digits = "0123456789ABCDEF";
  443. AnsiString Result;
  444. int L, P1, P2;
  445. L = Hex.Length();
  446. if (L % 2 == 0)
  447. {
  448. for (int i = 1; i <= Hex.Length(); i += 2)
  449. {
  450. P1 = Digits.Pos(Hex[i]);
  451. P2 = Digits.Pos(Hex[i + 1]);
  452. if (P1 <= 0 || P2 <= 0)
  453. {
  454. Result = "";
  455. break;
  456. }
  457. else
  458. {
  459. Result += static_cast<char>((P1 - 1) * 16 + P2 - 1);
  460. }
  461. }
  462. }
  463. return Result;
  464. }
  465. //---------------------------------------------------------------------------
  466. unsigned int __fastcall HexToInt(const AnsiString Hex, int MinChars)
  467. {
  468. static AnsiString Digits = "0123456789ABCDEF";
  469. int Result = 0;
  470. int I = 1;
  471. while (I <= Hex.Length())
  472. {
  473. int A = Digits.Pos(Hex[I]);
  474. if (A <= 0)
  475. {
  476. if ((MinChars < 0) || (I <= MinChars))
  477. {
  478. Result = 0;
  479. }
  480. break;
  481. }
  482. Result = (Result * 16) + (A - 1);
  483. I++;
  484. }
  485. return Result;
  486. }
  487. //---------------------------------------------------------------------------
  488. bool __fastcall FileSearchRec(const AnsiString FileName, TSearchRec & Rec)
  489. {
  490. int FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
  491. bool Result = (FindFirst(FileName, FindAttrs, Rec) == 0);
  492. if (Result)
  493. {
  494. FindClose(Rec);
  495. }
  496. return Result;
  497. }
  498. //---------------------------------------------------------------------------
  499. void __fastcall ProcessLocalDirectory(AnsiString DirName,
  500. TProcessLocalFileEvent CallBackFunc, void * Param,
  501. int FindAttrs)
  502. {
  503. assert(CallBackFunc);
  504. if (FindAttrs < 0)
  505. {
  506. FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
  507. }
  508. TSearchRec SearchRec;
  509. DirName = IncludeTrailingBackslash(DirName);
  510. if (FindFirst(DirName + "*.*", FindAttrs, SearchRec) == 0)
  511. {
  512. try
  513. {
  514. do
  515. {
  516. if ((SearchRec.Name != ".") && (SearchRec.Name != ".."))
  517. {
  518. CallBackFunc(DirName + SearchRec.Name, SearchRec, Param);
  519. }
  520. } while (FindNext(SearchRec) == 0);
  521. }
  522. __finally
  523. {
  524. FindClose(SearchRec);
  525. }
  526. }
  527. }
  528. //---------------------------------------------------------------------------
  529. struct TDateTimeParams
  530. {
  531. TDateTime UnixEpoch;
  532. double BaseDifference;
  533. long BaseDifferenceSec;
  534. double CurrentDaylightDifference;
  535. long CurrentDaylightDifferenceSec;
  536. double CurrentDifference;
  537. long CurrentDifferenceSec;
  538. double StandardDifference;
  539. long StandardDifferenceSec;
  540. double DaylightDifference;
  541. long DaylightDifferenceSec;
  542. SYSTEMTIME StandardDate;
  543. SYSTEMTIME DaylightDate;
  544. };
  545. static bool DateTimeParamsInitialized = false;
  546. static TDateTimeParams DateTimeParams;
  547. static TCriticalSection DateTimeParamsSection;
  548. //---------------------------------------------------------------------------
  549. static TDateTimeParams * __fastcall GetDateTimeParams()
  550. {
  551. if (!DateTimeParamsInitialized)
  552. {
  553. TGuard Guard(&DateTimeParamsSection);
  554. if (!DateTimeParamsInitialized)
  555. {
  556. TIME_ZONE_INFORMATION TZI;
  557. unsigned long GTZI;
  558. GTZI = GetTimeZoneInformation(&TZI);
  559. switch (GTZI)
  560. {
  561. case TIME_ZONE_ID_UNKNOWN:
  562. DateTimeParams.CurrentDifferenceSec = 0;
  563. DateTimeParams.CurrentDaylightDifferenceSec = 0;
  564. break;
  565. case TIME_ZONE_ID_STANDARD:
  566. DateTimeParams.CurrentDaylightDifferenceSec = TZI.StandardBias;
  567. break;
  568. case TIME_ZONE_ID_DAYLIGHT:
  569. DateTimeParams.CurrentDaylightDifferenceSec = TZI.DaylightBias;
  570. break;
  571. case TIME_ZONE_ID_INVALID:
  572. default:
  573. throw Exception(TIMEZONE_ERROR);
  574. }
  575. // Is it same as SysUtils::UnixDateDelta = 25569 ??
  576. DateTimeParams.UnixEpoch = EncodeDate(1970, 1, 1);
  577. DateTimeParams.BaseDifferenceSec = TZI.Bias;
  578. DateTimeParams.BaseDifference = double(TZI.Bias) / 1440;
  579. DateTimeParams.BaseDifferenceSec *= 60;
  580. DateTimeParams.CurrentDifferenceSec = TZI.Bias +
  581. DateTimeParams.CurrentDaylightDifferenceSec;
  582. DateTimeParams.CurrentDifference =
  583. double(DateTimeParams.CurrentDifferenceSec) / 1440;
  584. DateTimeParams.CurrentDifferenceSec *= 60;
  585. DateTimeParams.CurrentDaylightDifference =
  586. double(DateTimeParams.CurrentDaylightDifferenceSec) / 1440;
  587. DateTimeParams.CurrentDaylightDifferenceSec *= 60;
  588. DateTimeParams.DaylightDifferenceSec = TZI.DaylightBias * 60;
  589. DateTimeParams.DaylightDifference = double(TZI.DaylightBias) / 1440;
  590. DateTimeParams.StandardDifferenceSec = TZI.StandardBias * 60;
  591. DateTimeParams.StandardDifference = double(TZI.StandardBias) / 1440;
  592. DateTimeParams.StandardDate = TZI.StandardDate;
  593. DateTimeParams.DaylightDate = TZI.DaylightDate;
  594. DateTimeParamsInitialized = true;
  595. }
  596. }
  597. return &DateTimeParams;
  598. }
  599. //---------------------------------------------------------------------------
  600. static void __fastcall EncodeDSTMargin(const SYSTEMTIME & Date, unsigned short Year,
  601. TDateTime & Result)
  602. {
  603. if (Date.wYear == 0)
  604. {
  605. TDateTime Temp = EncodeDate(Year, Date.wMonth, 1);
  606. Result = Temp + ((Date.wDayOfWeek - DayOfWeek(Temp) + 8) % 7) +
  607. (7 * (Date.wDay - 1));
  608. if (Date.wDay == 5)
  609. {
  610. unsigned short Month = static_cast<unsigned short>(Date.wMonth + 1);
  611. if (Month > 12)
  612. {
  613. Month = static_cast<unsigned short>(Month - 12);
  614. Year++;
  615. }
  616. if (Result > EncodeDate(Year, Month, 1))
  617. {
  618. Result -= 7;
  619. }
  620. }
  621. Result += EncodeTime(Date.wHour, Date.wMinute, Date.wSecond,
  622. Date.wMilliseconds);
  623. }
  624. else
  625. {
  626. Result = EncodeDate(Year, Date.wMonth, Date.wDay) +
  627. EncodeTime(Date.wHour, Date.wMinute, Date.wSecond, Date.wMilliseconds);
  628. }
  629. }
  630. //---------------------------------------------------------------------------
  631. static bool __fastcall IsDateInDST(const TDateTime & DateTime)
  632. {
  633. struct TDSTCache
  634. {
  635. bool Filled;
  636. unsigned short Year;
  637. TDateTime StandardDate;
  638. TDateTime DaylightDate;
  639. };
  640. static TDSTCache DSTCache[10];
  641. static int DSTCacheCount = 0;
  642. static TCriticalSection Section;
  643. TDateTimeParams * Params = GetDateTimeParams();
  644. bool Result;
  645. if (Params->StandardDate.wMonth == 0)
  646. {
  647. Result = false;
  648. }
  649. else
  650. {
  651. unsigned short Year, Month, Day;
  652. DecodeDate(DateTime, Year, Month, Day);
  653. TDSTCache * CurrentCache = &DSTCache[0];
  654. int CacheIndex = 0;
  655. while ((CacheIndex < DSTCacheCount) && (CacheIndex < LENOF(DSTCache)) &&
  656. CurrentCache->Filled && (CurrentCache->Year != Year))
  657. {
  658. CacheIndex++;
  659. CurrentCache++;
  660. }
  661. if ((CacheIndex < DSTCacheCount) && (CacheIndex < LENOF(DSTCache)) &&
  662. CurrentCache->Filled)
  663. {
  664. assert(CurrentCache->Year == Year);
  665. Result = (DateTime >= CurrentCache->DaylightDate) &&
  666. (DateTime < CurrentCache->StandardDate);
  667. }
  668. else
  669. {
  670. TDSTCache NewCache;
  671. EncodeDSTMargin(Params->StandardDate, Year, NewCache.StandardDate);
  672. EncodeDSTMargin(Params->DaylightDate, Year, NewCache.DaylightDate);
  673. if (DSTCacheCount < LENOF(DSTCache))
  674. {
  675. TGuard Guard(&Section);
  676. if (DSTCacheCount < LENOF(DSTCache))
  677. {
  678. NewCache.Year = Year;
  679. DSTCache[DSTCacheCount] = NewCache;
  680. DSTCache[DSTCacheCount].Filled = true;
  681. DSTCacheCount++;
  682. }
  683. }
  684. Result = (DateTime >= NewCache.DaylightDate) &&
  685. (DateTime < NewCache.StandardDate);
  686. }
  687. }
  688. return Result;
  689. }
  690. //---------------------------------------------------------------------------
  691. TDateTime __fastcall UnixToDateTime(__int64 TimeStamp, TDSTMode DSTMode)
  692. {
  693. TDateTimeParams * Params = GetDateTimeParams();
  694. TDateTime Result;
  695. Result = Params->UnixEpoch + (double(TimeStamp) / 86400);
  696. if ((DSTMode == dstmWin) || (DSTMode == dstmUnix))
  697. {
  698. Result -= Params->CurrentDifference;
  699. }
  700. else if (DSTMode == dstmKeep)
  701. {
  702. Result -= Params->BaseDifference;
  703. }
  704. if ((DSTMode == dstmUnix) || (DSTMode == dstmKeep))
  705. {
  706. Result -= (IsDateInDST(Result) ?
  707. Params->DaylightDifference : Params->StandardDifference);
  708. }
  709. return Result;
  710. }
  711. //---------------------------------------------------------------------------
  712. inline __int64 __fastcall Round(double Number)
  713. {
  714. double Floor = floor(Number);
  715. double Ceil = ceil(Number);
  716. return ((Number - Floor) > (Ceil - Number)) ? Ceil : Floor;
  717. }
  718. //---------------------------------------------------------------------------
  719. #define TIME_POSIX_TO_WIN(t, ft) (*(LONGLONG*)&(ft) = \
  720. ((LONGLONG) (t) + (LONGLONG) 11644473600) * (LONGLONG) 10000000)
  721. #define TIME_WIN_TO_POSIX(ft, t) ((t) = (__int64) \
  722. ((*(LONGLONG*)&(ft)) / (LONGLONG) 10000000 - (LONGLONG) 11644473600))
  723. //---------------------------------------------------------------------------
  724. static __int64 __fastcall DateTimeToUnix(const TDateTime DateTime)
  725. {
  726. TDateTimeParams * Params = GetDateTimeParams();
  727. return Round(double(DateTime - Params->UnixEpoch) * 86400) +
  728. Params->CurrentDifferenceSec;
  729. }
  730. //---------------------------------------------------------------------------
  731. FILETIME __fastcall DateTimeToFileTime(const TDateTime DateTime,
  732. TDSTMode /*DSTMode*/)
  733. {
  734. FILETIME Result;
  735. __int64 UnixTimeStamp = DateTimeToUnix(DateTime);
  736. TIME_POSIX_TO_WIN(UnixTimeStamp, Result);
  737. return Result;
  738. }
  739. //---------------------------------------------------------------------------
  740. __int64 __fastcall ConvertTimestampToUnix(const FILETIME & FileTime,
  741. TDSTMode DSTMode)
  742. {
  743. __int64 Result;
  744. TIME_WIN_TO_POSIX(FileTime, Result);
  745. if ((DSTMode == dstmUnix) || (DSTMode == dstmKeep))
  746. {
  747. FILETIME LocalFileTime;
  748. SYSTEMTIME SystemTime;
  749. TDateTime DateTime;
  750. FileTimeToLocalFileTime(&FileTime, &LocalFileTime);
  751. FileTimeToSystemTime(&LocalFileTime, &SystemTime);
  752. DateTime = SystemTimeToDateTime(SystemTime);
  753. TDateTimeParams * Params = GetDateTimeParams();
  754. Result += (IsDateInDST(DateTime) ?
  755. Params->DaylightDifferenceSec : Params->StandardDifferenceSec);
  756. if (DSTMode == dstmKeep)
  757. {
  758. Result -= Params->CurrentDaylightDifferenceSec;
  759. }
  760. }
  761. return Result;
  762. }
  763. //---------------------------------------------------------------------------
  764. __int64 __fastcall ConvertTimestampToUnixSafe(const FILETIME & FileTime,
  765. TDSTMode DSTMode)
  766. {
  767. __int64 Result;
  768. if ((FileTime.dwLowDateTime == 0) &&
  769. (FileTime.dwHighDateTime == 0))
  770. {
  771. Result = DateTimeToUnix(Now());
  772. }
  773. else
  774. {
  775. Result = ConvertTimestampToUnix(FileTime, DSTMode);
  776. }
  777. return Result;
  778. }
  779. //---------------------------------------------------------------------------
  780. TDateTime __fastcall AdjustDateTimeFromUnix(TDateTime DateTime, TDSTMode DSTMode)
  781. {
  782. TDateTimeParams * Params = GetDateTimeParams();
  783. if ((DSTMode == dstmWin) || (DSTMode == dstmUnix))
  784. {
  785. DateTime = DateTime - Params->CurrentDaylightDifference;
  786. }
  787. if (!IsDateInDST(DateTime))
  788. {
  789. if (DSTMode == dstmWin)
  790. {
  791. DateTime = DateTime - Params->DaylightDifference;
  792. }
  793. }
  794. else
  795. {
  796. DateTime = DateTime - Params->StandardDifference;
  797. }
  798. return DateTime;
  799. }
  800. //---------------------------------------------------------------------------
  801. __inline static bool __fastcall UnifySignificance(unsigned short & V1,
  802. unsigned short & V2)
  803. {
  804. bool Result = (V1 == 0) || (V2 == 0);
  805. if (Result)
  806. {
  807. V1 = 0;
  808. V2 = 0;
  809. }
  810. return Result;
  811. }
  812. //---------------------------------------------------------------------------
  813. void __fastcall UnifyDateTimePrecision(TDateTime & DateTime1, TDateTime & DateTime2)
  814. {
  815. unsigned short Y1, M1, D1, H1, N1, S1, MS1;
  816. unsigned short Y2, M2, D2, H2, N2, S2, MS2;
  817. bool Changed;
  818. if (DateTime1 != DateTime2)
  819. {
  820. DateTime1.DecodeDate(&Y1, &M1, &D1);
  821. DateTime1.DecodeTime(&H1, &N1, &S1, &MS1);
  822. DateTime2.DecodeDate(&Y2, &M2, &D2);
  823. DateTime2.DecodeTime(&H2, &N2, &S2, &MS2);
  824. Changed = UnifySignificance(MS1, MS2);
  825. if (Changed && UnifySignificance(S1, S2) && UnifySignificance(N1, N2) &&
  826. UnifySignificance(H1, H2) && UnifySignificance(D1, D2) &&
  827. UnifySignificance(M1, M2))
  828. {
  829. UnifySignificance(Y1, Y2);
  830. }
  831. if (Changed)
  832. {
  833. DateTime1 = EncodeDate(Y1, M1, D1) + EncodeTime(H1, N1, S1, MS1);
  834. DateTime2 = EncodeDate(Y2, M2, D2) + EncodeTime(H2, N2, S2, MS2);
  835. }
  836. }
  837. }
  838. //---------------------------------------------------------------------------
  839. AnsiString __fastcall FixedLenDateTimeFormat(const AnsiString & Format)
  840. {
  841. AnsiString Result = Format;
  842. bool AsIs = false;
  843. int Index = 1;
  844. while (Index <= Result.Length())
  845. {
  846. char F = Result[Index];
  847. if ((F == '\'') || (F == '\"'))
  848. {
  849. AsIs = !AsIs;
  850. Index++;
  851. }
  852. else if (!AsIs && ((F == 'a') || (F == 'A')))
  853. {
  854. if (Result.SubString(Index, 5).LowerCase() == "am/pm")
  855. {
  856. Index += 5;
  857. }
  858. else if (Result.SubString(Index, 3).LowerCase() == "a/p")
  859. {
  860. Index += 3;
  861. }
  862. else if (Result.SubString(Index, 4).LowerCase() == "ampm")
  863. {
  864. Index += 4;
  865. }
  866. else
  867. {
  868. Index++;
  869. }
  870. }
  871. else
  872. {
  873. if (!AsIs && (strchr("dDeEmMhHnNsS", F) != NULL) &&
  874. ((Index == Result.Length()) || (Result[Index + 1] != F)))
  875. {
  876. Result.Insert(F, Index);
  877. }
  878. while ((Index <= Result.Length()) && (F == Result[Index]))
  879. {
  880. Index++;
  881. }
  882. }
  883. }
  884. return Result;
  885. }
  886. //---------------------------------------------------------------------------
  887. int __fastcall CompareFileTime(TDateTime T1, TDateTime T2)
  888. {
  889. // "FAT" time precision
  890. // 1 ms more solves the rounding issues (see also CustomDirView.pas)
  891. static TDateTime Second(0, 0, 1, 1);
  892. int Result;
  893. if (T1 == T2)
  894. {
  895. // just optimalisation
  896. Result = 0;
  897. }
  898. else if ((T1 < T2) && (T2 - T1 > Second))
  899. {
  900. Result = -1;
  901. }
  902. else if ((T1 > T2) && (T1 - T2 > Second))
  903. {
  904. Result = 1;
  905. }
  906. else
  907. {
  908. Result = 0;
  909. }
  910. return Result;
  911. }
  912. //---------------------------------------------------------------------------
  913. bool __fastcall RecursiveDeleteFile(const AnsiString FileName, bool ToRecycleBin)
  914. {
  915. SHFILEOPSTRUCT Data;
  916. memset(&Data, 0, sizeof(Data));
  917. Data.hwnd = NULL;
  918. Data.wFunc = FO_DELETE;
  919. AnsiString FileList(FileName);
  920. FileList.SetLength(FileList.Length() + 2);
  921. FileList[FileList.Length() - 1] = '\0';
  922. FileList[FileList.Length()] = '\0';
  923. Data.pFrom = FileList.c_str();
  924. Data.pTo = "";
  925. Data.fFlags = FOF_NOCONFIRMATION | FOF_RENAMEONCOLLISION | FOF_NOCONFIRMMKDIR |
  926. FOF_NOERRORUI | FOF_SILENT;
  927. if (ToRecycleBin)
  928. {
  929. Data.fFlags |= FOF_ALLOWUNDO;
  930. }
  931. int Result = SHFileOperation(&Data);
  932. return (Result == 0);
  933. }
  934. //---------------------------------------------------------------------------
  935. int __fastcall CancelAnswer(int Answers)
  936. {
  937. int Result;
  938. if ((Answers & qaCancel) != 0)
  939. {
  940. Result = qaCancel;
  941. }
  942. else if ((Answers & qaNo) != 0)
  943. {
  944. Result = qaNo;
  945. }
  946. else if ((Answers & qaAbort) != 0)
  947. {
  948. Result = qaAbort;
  949. }
  950. else if ((Answers & qaOK) != 0)
  951. {
  952. Result = qaOK;
  953. }
  954. else
  955. {
  956. assert(false);
  957. Result = qaCancel;
  958. }
  959. return Result;
  960. }
  961. //---------------------------------------------------------------------------
  962. int __fastcall AbortAnswer(int Answers)
  963. {
  964. int Result;
  965. if (FLAGSET(Answers, qaAbort))
  966. {
  967. Result = qaAbort;
  968. }
  969. else
  970. {
  971. Result = CancelAnswer(Answers);
  972. }
  973. return Result;
  974. }
  975. //---------------------------------------------------------------------------
  976. int __fastcall ContinueAnswer(int Answers)
  977. {
  978. int Result;
  979. if (FLAGSET(Answers, qaSkip))
  980. {
  981. Result = qaSkip;
  982. }
  983. else if (FLAGSET(Answers, qaIgnore))
  984. {
  985. Result = qaIgnore;
  986. }
  987. else if (FLAGSET(Answers, qaYes))
  988. {
  989. Result = qaYes;
  990. }
  991. else if (FLAGSET(Answers, qaOK))
  992. {
  993. Result = qaOK;
  994. }
  995. else if (FLAGSET(Answers, qaRetry))
  996. {
  997. Result = qaOK;
  998. }
  999. else
  1000. {
  1001. Result = CancelAnswer(Answers);
  1002. }
  1003. return Result;
  1004. }
  1005. //---------------------------------------------------------------------------
  1006. TPasLibModule * __fastcall FindModule(void * Instance)
  1007. {
  1008. TPasLibModule * CurModule;
  1009. CurModule = reinterpret_cast<TPasLibModule*>(LibModuleList);
  1010. while (CurModule)
  1011. {
  1012. if (CurModule->Instance == Instance)
  1013. {
  1014. break;
  1015. }
  1016. else
  1017. {
  1018. CurModule = CurModule->Next;
  1019. }
  1020. }
  1021. return CurModule;
  1022. }
  1023. //---------------------------------------------------------------------------
  1024. AnsiString __fastcall LoadStr(int Ident, unsigned int MaxLength)
  1025. {
  1026. TPasLibModule * MainModule = FindModule(HInstance);
  1027. assert(MainModule != NULL);
  1028. AnsiString Result;
  1029. Result.SetLength(MaxLength);
  1030. int Length = LoadString(MainModule->ResInstance, Ident, Result.c_str(), MaxLength);
  1031. Result.SetLength(Length);
  1032. return Result;
  1033. }
  1034. //---------------------------------------------------------------------------
  1035. AnsiString __fastcall LoadStrPart(int Ident, int Part)
  1036. {
  1037. AnsiString Result;
  1038. AnsiString Str = LoadStr(Ident);
  1039. while (Part > 0)
  1040. {
  1041. Result = CutToChar(Str, '|', false);
  1042. Part--;
  1043. }
  1044. return Result;
  1045. }
  1046. //---------------------------------------------------------------------------
  1047. AnsiString __fastcall DecodeUrlChars(AnsiString S)
  1048. {
  1049. int i = 1;
  1050. while (i <= S.Length())
  1051. {
  1052. switch (S[i])
  1053. {
  1054. case '+':
  1055. S[i] = ' ';
  1056. break;
  1057. case '%':
  1058. if (i <= S.Length() - 2)
  1059. {
  1060. S[i] = HexToStr(S.SubString(i + 1, 2))[1];
  1061. S.Delete(i + 1, 2);
  1062. }
  1063. break;
  1064. }
  1065. i++;
  1066. }
  1067. return S;
  1068. }
  1069. //---------------------------------------------------------------------------
  1070. AnsiString __fastcall EncodeUrlChars(AnsiString S, AnsiString Ignore)
  1071. {
  1072. AnsiString Encode = "/ ";
  1073. int i = 1;
  1074. while (i <= S.Length())
  1075. {
  1076. if ((Encode.Pos(S[i]) > 0) &&
  1077. (Ignore.Pos(S[i]) == 0))
  1078. {
  1079. AnsiString H = CharToHex(S[i]);
  1080. S.Insert(H, i + 1);
  1081. S[i] = '%';
  1082. i += H.Length();
  1083. }
  1084. i++;
  1085. }
  1086. return S;
  1087. }
  1088. //---------------------------------------------------------------------------
  1089. void __fastcall OemToAnsi(AnsiString & Str)
  1090. {
  1091. if (!Str.IsEmpty())
  1092. {
  1093. Str.Unique();
  1094. OemToChar(Str.c_str(), Str.c_str());
  1095. }
  1096. }
  1097. //---------------------------------------------------------------------------
  1098. void __fastcall AnsiToOem(AnsiString & Str)
  1099. {
  1100. if (!Str.IsEmpty())
  1101. {
  1102. Str.Unique();
  1103. CharToOem(Str.c_str(), Str.c_str());
  1104. }
  1105. }