Common.cpp 28 KB

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