Common.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455
  1. //---------------------------------------------------------------------------
  2. #define NO_WIN32_LEAN_AND_MEAN
  3. #include <vcl.h>
  4. #pragma hdrstop
  5. #include "Common.h"
  6. #include "Exceptions.h"
  7. #include "TextsCore.h"
  8. #include "Interface.h"
  9. #include <StrUtils.hpp>
  10. #include <math.h>
  11. #include <shfolder.h>
  12. //---------------------------------------------------------------------------
  13. #pragma package(smart_init)
  14. //---------------------------------------------------------------------------
  15. //---------------------------------------------------------------------------
  16. // TCriticalSection
  17. //---------------------------------------------------------------------------
  18. __fastcall TCriticalSection::TCriticalSection()
  19. {
  20. FAcquired = 0;
  21. InitializeCriticalSection(&FSection);
  22. }
  23. //---------------------------------------------------------------------------
  24. __fastcall TCriticalSection::~TCriticalSection()
  25. {
  26. assert(FAcquired == 0);
  27. DeleteCriticalSection(&FSection);
  28. }
  29. //---------------------------------------------------------------------------
  30. void __fastcall TCriticalSection::Enter()
  31. {
  32. EnterCriticalSection(&FSection);
  33. FAcquired++;
  34. }
  35. //---------------------------------------------------------------------------
  36. void __fastcall TCriticalSection::Leave()
  37. {
  38. FAcquired--;
  39. LeaveCriticalSection(&FSection);
  40. }
  41. //---------------------------------------------------------------------------
  42. // TGuard
  43. //---------------------------------------------------------------------------
  44. __fastcall TGuard::TGuard(TCriticalSection * ACriticalSection) :
  45. FCriticalSection(ACriticalSection)
  46. {
  47. assert(ACriticalSection != NULL);
  48. FCriticalSection->Enter();
  49. }
  50. //---------------------------------------------------------------------------
  51. __fastcall TGuard::~TGuard()
  52. {
  53. FCriticalSection->Leave();
  54. }
  55. //---------------------------------------------------------------------------
  56. // TUnguard
  57. //---------------------------------------------------------------------------
  58. __fastcall TUnguard::TUnguard(TCriticalSection * ACriticalSection) :
  59. FCriticalSection(ACriticalSection)
  60. {
  61. assert(ACriticalSection != NULL);
  62. FCriticalSection->Leave();
  63. }
  64. //---------------------------------------------------------------------------
  65. __fastcall TUnguard::~TUnguard()
  66. {
  67. FCriticalSection->Enter();
  68. }
  69. //---------------------------------------------------------------------------
  70. //---------------------------------------------------------------------------
  71. const char EngShortMonthNames[12][4] =
  72. {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  73. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  74. //---------------------------------------------------------------------------
  75. AnsiString ReplaceChar(AnsiString Str, Char A, Char B)
  76. {
  77. for (Integer Index = 0; Index < Str.Length(); Index++)
  78. if (Str[Index+1] == A) Str[Index+1] = B;
  79. return Str;
  80. }
  81. //---------------------------------------------------------------------------
  82. AnsiString DeleteChar(AnsiString Str, Char C)
  83. {
  84. int P;
  85. while ((P = Str.Pos(C)) > 0)
  86. {
  87. Str.Delete(P, 1);
  88. }
  89. return Str;
  90. }
  91. //---------------------------------------------------------------------------
  92. void PackStr(AnsiString &Str)
  93. {
  94. // Following will free unnecessary bytes
  95. Str = Str.c_str();
  96. }
  97. //---------------------------------------------------------------------------
  98. AnsiString MakeValidFileName(AnsiString FileName)
  99. {
  100. AnsiString IllegalChars = ";,=+<>|\"[] \\/?*";
  101. for (int Index = 0; Index < IllegalChars.Length(); Index++)
  102. {
  103. FileName = ReplaceChar(FileName, IllegalChars[Index+1], '-');
  104. }
  105. return FileName;
  106. }
  107. //---------------------------------------------------------------------------
  108. AnsiString RootKeyToStr(HKEY RootKey)
  109. {
  110. if (RootKey == HKEY_USERS) return "HKEY_USERS";
  111. else
  112. if (RootKey == HKEY_LOCAL_MACHINE) return "HKEY_LOCAL_MACHINE";
  113. else
  114. if (RootKey == HKEY_CURRENT_USER) return "HKEY_CURRENT_USER";
  115. else
  116. if (RootKey == HKEY_CLASSES_ROOT) return "HKEY_CLASSES_ROOT";
  117. else
  118. if (RootKey == HKEY_CURRENT_CONFIG) return "HKEY_CURRENT_CONFIG";
  119. else
  120. if (RootKey == HKEY_DYN_DATA) return "HKEY_DYN_DATA";
  121. else
  122. { Abort(); return ""; };
  123. }
  124. //---------------------------------------------------------------------------
  125. AnsiString BooleanToEngStr(bool B)
  126. {
  127. if (B)
  128. {
  129. return "Yes";
  130. }
  131. else
  132. {
  133. return "No";
  134. }
  135. }
  136. //---------------------------------------------------------------------------
  137. AnsiString BooleanToStr(bool B)
  138. {
  139. if (B)
  140. {
  141. return LoadStr(YES_STR);
  142. }
  143. else
  144. {
  145. return LoadStr(NO_STR);
  146. }
  147. }
  148. //---------------------------------------------------------------------------
  149. AnsiString DefaultStr(const AnsiString & Str, const AnsiString & Default)
  150. {
  151. if (!Str.IsEmpty())
  152. {
  153. return Str;
  154. }
  155. else
  156. {
  157. return Default;
  158. }
  159. }
  160. //---------------------------------------------------------------------------
  161. AnsiString CutToChar(AnsiString &Str, Char Ch, bool Trim)
  162. {
  163. Integer P = Str.Pos(Ch);
  164. AnsiString Result;
  165. if (P)
  166. {
  167. Result = Str.SubString(1, P-1);
  168. Str.Delete(1, P);
  169. }
  170. else
  171. {
  172. Result = Str;
  173. Str = "";
  174. }
  175. if (Trim)
  176. {
  177. Result = Result.TrimRight();
  178. Str = Str.TrimLeft();
  179. }
  180. return Result;
  181. }
  182. //---------------------------------------------------------------------------
  183. AnsiString CopyToChars(const AnsiString & Str, int & From, AnsiString Chs, bool Trim,
  184. char * Delimiter)
  185. {
  186. int P;
  187. for (P = From; P <= Str.Length(); P++)
  188. {
  189. if (IsDelimiter(Chs, Str, P))
  190. {
  191. break;
  192. }
  193. }
  194. AnsiString Result;
  195. if (P <= Str.Length())
  196. {
  197. if (Delimiter != NULL)
  198. {
  199. *Delimiter = Str[P];
  200. }
  201. Result = Str.SubString(From, P-From);
  202. From = P+1;
  203. }
  204. else
  205. {
  206. if (Delimiter != NULL)
  207. {
  208. *Delimiter = '\0';
  209. }
  210. Result = Str.SubString(From, Str.Length() - From + 1);
  211. From = P;
  212. }
  213. if (Trim)
  214. {
  215. Result = Result.TrimRight();
  216. while ((P <= Str.Length()) && (Str[P] == ' '))
  217. {
  218. P++;
  219. }
  220. }
  221. return Result;
  222. }
  223. //---------------------------------------------------------------------------
  224. AnsiString DelimitStr(AnsiString Str, AnsiString Chars)
  225. {
  226. for (int i = 1; i <= Str.Length(); i++)
  227. {
  228. if (Str.IsDelimiter(Chars, i))
  229. {
  230. Str.Insert("\\", i);
  231. i++;
  232. }
  233. }
  234. return Str;
  235. }
  236. //---------------------------------------------------------------------------
  237. AnsiString ShellDelimitStr(AnsiString Str, char Quote)
  238. {
  239. AnsiString Chars = "$\\";
  240. if (Quote == '"')
  241. {
  242. Chars += "`\"";
  243. }
  244. return DelimitStr(Str, Chars);
  245. }
  246. //---------------------------------------------------------------------------
  247. AnsiString ExceptionLogString(Exception *E)
  248. {
  249. assert(E);
  250. if (E->InheritsFrom(__classid(Exception)))
  251. {
  252. AnsiString Msg;
  253. Msg = FORMAT("(%s) %s", (E->ClassName(), E->Message));
  254. if (E->InheritsFrom(__classid(ExtException)))
  255. {
  256. TStrings * MoreMessages = ((ExtException*)E)->MoreMessages;
  257. if (MoreMessages)
  258. {
  259. Msg += "\n" +
  260. StringReplace(MoreMessages->Text, "\r", "", TReplaceFlags() << rfReplaceAll);
  261. }
  262. }
  263. return Msg;
  264. }
  265. else
  266. {
  267. char Buffer[1024];
  268. ExceptionErrorMessage(ExceptObject(), ExceptAddr(), Buffer, sizeof(Buffer));
  269. return AnsiString(Buffer);
  270. }
  271. }
  272. //---------------------------------------------------------------------------
  273. bool IsNumber(const AnsiString Str)
  274. {
  275. int Value;
  276. return TryStrToInt(Str, Value);
  277. }
  278. //---------------------------------------------------------------------------
  279. AnsiString __fastcall SystemTemporaryDirectory()
  280. {
  281. AnsiString TempDir;
  282. TempDir.SetLength(MAX_PATH);
  283. TempDir.SetLength(GetTempPath(MAX_PATH, TempDir.c_str()));
  284. return TempDir;
  285. }
  286. //---------------------------------------------------------------------------
  287. AnsiString __fastcall GetShellFolderPath(int CSIdl)
  288. {
  289. AnsiString Result;
  290. HMODULE Shell32Lib = LoadLibrary("SHELL32.DLL");
  291. if (Shell32Lib != NULL)
  292. {
  293. PFNSHGETFOLDERPATH SHGetFolderPath = (PFNSHGETFOLDERPATH)
  294. GetProcAddress(Shell32Lib, "SHGetFolderPathA");
  295. if (SHGetFolderPath != NULL)
  296. {
  297. char Path[2 * MAX_PATH + 10] = "\0";
  298. if (SUCCEEDED(SHGetFolderPath(NULL, CSIdl, NULL, SHGFP_TYPE_CURRENT, Path)))
  299. {
  300. Result = Path;
  301. }
  302. }
  303. }
  304. return Result;
  305. }
  306. //---------------------------------------------------------------------------
  307. AnsiString __fastcall StripPathQuotes(const AnsiString Path)
  308. {
  309. if ((Path.Length() >= 2) &&
  310. (Path[1] == '\"') && (Path[Path.Length()] == '\"'))
  311. {
  312. return Path.SubString(2, Path.Length() - 2);
  313. }
  314. else
  315. {
  316. return Path;
  317. }
  318. }
  319. //---------------------------------------------------------------------------
  320. AnsiString __fastcall AddPathQuotes(AnsiString Path)
  321. {
  322. Path = StripPathQuotes(Path);
  323. if (Path.Pos(" "))
  324. {
  325. Path = "\"" + Path + "\"";
  326. }
  327. return Path;
  328. }
  329. //---------------------------------------------------------------------------
  330. void __fastcall SplitCommand(AnsiString Command, AnsiString &Program,
  331. AnsiString & Params, AnsiString & Dir)
  332. {
  333. Command = Command.Trim();
  334. Params = "";
  335. Dir = "";
  336. if (!Command.IsEmpty() && (Command[1] == '\"'))
  337. {
  338. Command.Delete(1, 1);
  339. int P = Command.Pos('"');
  340. if (P)
  341. {
  342. Program = Command.SubString(1, P-1).Trim();
  343. Params = Command.SubString(P + 1, Command.Length() - P).Trim();
  344. }
  345. else
  346. {
  347. throw Exception(FMTLOAD(INVALID_SHELL_COMMAND, ("\"" + Command)));
  348. }
  349. }
  350. else
  351. {
  352. int P = Command.Pos(" ");
  353. if (P)
  354. {
  355. Program = Command.SubString(1, P).Trim();
  356. Params = Command.SubString(P + 1, Command.Length() - P).Trim();
  357. }
  358. else
  359. {
  360. Program = Command;
  361. }
  362. }
  363. int B = Program.LastDelimiter("\\/");
  364. if (B)
  365. {
  366. Dir = Program.SubString(1, B).Trim();
  367. }
  368. }
  369. //---------------------------------------------------------------------------
  370. AnsiString __fastcall ExtractProgram(AnsiString Command)
  371. {
  372. AnsiString Program;
  373. AnsiString Params;
  374. AnsiString Dir;
  375. SplitCommand(Command, Program, Params, Dir);
  376. return Program;
  377. }
  378. //---------------------------------------------------------------------------
  379. AnsiString __fastcall FormatCommand(AnsiString Program, AnsiString Params)
  380. {
  381. Program = Program.Trim();
  382. Params = Params.Trim();
  383. if (!Params.IsEmpty()) Params = " " + Params;
  384. if (Program.Pos(" ")) Program = "\"" + Program + "\"";
  385. return Program + Params;
  386. }
  387. //---------------------------------------------------------------------------
  388. const char ShellCommandFileNamePattern[] = "!.!";
  389. //---------------------------------------------------------------------------
  390. void __fastcall ReformatFileNameCommand(AnsiString & Command)
  391. {
  392. AnsiString Program, Params, Dir;
  393. SplitCommand(Command, Program, Params, Dir);
  394. if (Params.Pos(ShellCommandFileNamePattern) == 0)
  395. {
  396. Params = Params + (Params.IsEmpty() ? "" : " ") + ShellCommandFileNamePattern;
  397. }
  398. Command = FormatCommand(Program, Params);
  399. }
  400. //---------------------------------------------------------------------------
  401. AnsiString __fastcall ExpandFileNameCommand(const AnsiString Command,
  402. const AnsiString FileName)
  403. {
  404. return AnsiReplaceStr(Command, ShellCommandFileNamePattern,
  405. AddPathQuotes(FileName));
  406. }
  407. //---------------------------------------------------------------------------
  408. AnsiString __fastcall ExpandEnvironmentVariables(const AnsiString & Str)
  409. {
  410. AnsiString Buf;
  411. unsigned int Size = 1024;
  412. Buf.SetLength(Size);
  413. Buf.Unique();
  414. unsigned int Len = ExpandEnvironmentStrings(Str.c_str(), Buf.c_str(), Size);
  415. if (Len > Size)
  416. {
  417. Buf.SetLength(Len);
  418. Buf.Unique();
  419. ExpandEnvironmentStrings(Str.c_str(), Buf.c_str(), Len);
  420. }
  421. PackStr(Buf);
  422. return Buf;
  423. }
  424. //---------------------------------------------------------------------------
  425. bool __fastcall CompareFileName(const AnsiString & Path1, const AnsiString & Path2)
  426. {
  427. AnsiString ShortPath1 = ExtractShortPathName(Path1);
  428. AnsiString ShortPath2 = ExtractShortPathName(Path2);
  429. bool Result;
  430. // ExtractShortPathName returns empty string if file does not exist
  431. if (ShortPath1.IsEmpty() || ShortPath2.IsEmpty())
  432. {
  433. Result = AnsiSameText(Path1, Path2);
  434. }
  435. else
  436. {
  437. Result = AnsiSameText(ShortPath1, ShortPath2);
  438. }
  439. return Result;
  440. }
  441. //---------------------------------------------------------------------------
  442. bool __fastcall ComparePaths(const AnsiString & Path1, const AnsiString & Path2)
  443. {
  444. // TODO: ExpandUNCFileName
  445. return AnsiSameText(IncludeTrailingBackslash(Path1), IncludeTrailingBackslash(Path2));
  446. }
  447. //---------------------------------------------------------------------------
  448. bool __fastcall IsReservedName(AnsiString FileName)
  449. {
  450. int P = FileName.Pos(".");
  451. int Len = (P > 0) ? P - 1 : FileName.Length();
  452. if ((Len == 3) || (Len == 4))
  453. {
  454. if (P > 0)
  455. {
  456. FileName.SetLength(P - 1);
  457. }
  458. static AnsiString Reserved[] = {
  459. "CON", "PRN", "AUX", "NUL",
  460. "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
  461. "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9" };
  462. for (int Index = 0; Index < LENOF(Reserved); Index++)
  463. {
  464. if (SameText(FileName, Reserved[Index]))
  465. {
  466. return true;
  467. }
  468. }
  469. }
  470. return false;
  471. }
  472. //---------------------------------------------------------------------------
  473. AnsiString __fastcall DisplayableStr(const AnsiString Str)
  474. {
  475. bool Displayable = true;
  476. int Index = 1;
  477. while ((Index <= Str.Length()) && Displayable)
  478. {
  479. if ((Str[Index] < '\32') &&
  480. (Str[Index] != '\n') && (Str[Index] != '\r') && (Str[Index] != '\t') && (Str[Index] != '\b'))
  481. {
  482. Displayable = false;
  483. }
  484. Index++;
  485. }
  486. AnsiString Result;
  487. if (Displayable)
  488. {
  489. Result = "\"";
  490. for (int Index = 1; Index <= Str.Length(); Index++)
  491. {
  492. switch (Str[Index])
  493. {
  494. case '\n':
  495. Result += "\\n";
  496. break;
  497. case '\r':
  498. Result += "\\r";
  499. break;
  500. case '\t':
  501. Result += "\\t";
  502. break;
  503. case '\b':
  504. Result += "\\b";
  505. break;
  506. case '\\':
  507. Result += "\\\\";
  508. break;
  509. case '"':
  510. Result += "\\\"";
  511. break;
  512. default:
  513. Result += Str[Index];
  514. break;
  515. }
  516. }
  517. Result += "\"";
  518. }
  519. else
  520. {
  521. Result = "0x" + StrToHex(Str);
  522. }
  523. return Result;
  524. }
  525. //---------------------------------------------------------------------------
  526. AnsiString __fastcall CharToHex(char Ch, bool UpperCase)
  527. {
  528. static char UpperDigits[] = "0123456789ABCDEF";
  529. static char LowerDigits[] = "0123456789abcdef";
  530. const char * Digits = (UpperCase ? UpperDigits : LowerDigits);
  531. AnsiString Result;
  532. Result.SetLength(2);
  533. Result[1] = Digits[((unsigned char)Ch & 0xF0) >> 4];
  534. Result[2] = Digits[ (unsigned char)Ch & 0x0F];
  535. return Result;
  536. }
  537. //---------------------------------------------------------------------------
  538. AnsiString __fastcall StrToHex(const AnsiString Str, bool UpperCase, char Separator)
  539. {
  540. AnsiString Result;
  541. for (int i = 1; i <= Str.Length(); i++)
  542. {
  543. Result += CharToHex(Str[i], UpperCase);
  544. if ((Separator != '\0') && (i < Str.Length()))
  545. {
  546. Result += Separator;
  547. }
  548. }
  549. return Result;
  550. }
  551. //---------------------------------------------------------------------------
  552. AnsiString __fastcall HexToStr(const AnsiString Hex)
  553. {
  554. static AnsiString Digits = "0123456789ABCDEF";
  555. AnsiString Result;
  556. int L, P1, P2;
  557. L = Hex.Length();
  558. if (L % 2 == 0)
  559. {
  560. for (int i = 1; i <= Hex.Length(); i += 2)
  561. {
  562. P1 = Digits.Pos((char)toupper(Hex[i]));
  563. P2 = Digits.Pos((char)toupper(Hex[i + 1]));
  564. if (P1 <= 0 || P2 <= 0)
  565. {
  566. Result = "";
  567. break;
  568. }
  569. else
  570. {
  571. Result += static_cast<char>((P1 - 1) * 16 + P2 - 1);
  572. }
  573. }
  574. }
  575. return Result;
  576. }
  577. //---------------------------------------------------------------------------
  578. unsigned int __fastcall HexToInt(const AnsiString Hex, int MinChars)
  579. {
  580. static AnsiString Digits = "0123456789ABCDEF";
  581. int Result = 0;
  582. int I = 1;
  583. while (I <= Hex.Length())
  584. {
  585. int A = Digits.Pos((char)toupper(Hex[I]));
  586. if (A <= 0)
  587. {
  588. if ((MinChars < 0) || (I <= MinChars))
  589. {
  590. Result = 0;
  591. }
  592. break;
  593. }
  594. Result = (Result * 16) + (A - 1);
  595. I++;
  596. }
  597. return Result;
  598. }
  599. //---------------------------------------------------------------------------
  600. char __fastcall HexToChar(const AnsiString Hex, int MinChars)
  601. {
  602. return (char)HexToInt(Hex, MinChars);
  603. }
  604. //---------------------------------------------------------------------------
  605. bool __fastcall FileSearchRec(const AnsiString FileName, TSearchRec & Rec)
  606. {
  607. int FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
  608. bool Result = (FindFirst(FileName, FindAttrs, Rec) == 0);
  609. if (Result)
  610. {
  611. FindClose(Rec);
  612. }
  613. return Result;
  614. }
  615. //---------------------------------------------------------------------------
  616. void __fastcall ProcessLocalDirectory(AnsiString DirName,
  617. TProcessLocalFileEvent CallBackFunc, void * Param,
  618. int FindAttrs)
  619. {
  620. assert(CallBackFunc);
  621. if (FindAttrs < 0)
  622. {
  623. FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
  624. }
  625. TSearchRec SearchRec;
  626. DirName = IncludeTrailingBackslash(DirName);
  627. if (FindFirst(DirName + "*.*", FindAttrs, SearchRec) == 0)
  628. {
  629. try
  630. {
  631. do
  632. {
  633. if ((SearchRec.Name != ".") && (SearchRec.Name != ".."))
  634. {
  635. CallBackFunc(DirName + SearchRec.Name, SearchRec, Param);
  636. }
  637. } while (FindNext(SearchRec) == 0);
  638. }
  639. __finally
  640. {
  641. FindClose(SearchRec);
  642. }
  643. }
  644. }
  645. //---------------------------------------------------------------------------
  646. TDateTime __fastcall EncodeDateVerbose(Word Year, Word Month, Word Day)
  647. {
  648. try
  649. {
  650. return EncodeDate(Year, Month, Day);
  651. }
  652. catch (EConvertError & E)
  653. {
  654. throw EConvertError(FORMAT("%s [%d-%d-%d]", (E.Message, int(Year), int(Month), int(Day))));
  655. }
  656. }
  657. //---------------------------------------------------------------------------
  658. TDateTime __fastcall EncodeTimeVerbose(Word Hour, Word Min, Word Sec, Word MSec)
  659. {
  660. try
  661. {
  662. return EncodeTime(Hour, Min, Sec, MSec);
  663. }
  664. catch (EConvertError & E)
  665. {
  666. throw EConvertError(FORMAT("%s [%d:%d:%d.%d]", (E.Message, int(Hour), int(Min), int(Sec), int(MSec))));
  667. }
  668. }
  669. //---------------------------------------------------------------------------
  670. struct TDateTimeParams
  671. {
  672. TDateTime UnixEpoch;
  673. double BaseDifference;
  674. long BaseDifferenceSec;
  675. double CurrentDaylightDifference;
  676. long CurrentDaylightDifferenceSec;
  677. double CurrentDifference;
  678. long CurrentDifferenceSec;
  679. double StandardDifference;
  680. long StandardDifferenceSec;
  681. double DaylightDifference;
  682. long DaylightDifferenceSec;
  683. SYSTEMTIME StandardDate;
  684. SYSTEMTIME DaylightDate;
  685. };
  686. static bool DateTimeParamsInitialized = false;
  687. static TDateTimeParams DateTimeParams;
  688. static TCriticalSection DateTimeParamsSection;
  689. //---------------------------------------------------------------------------
  690. static TDateTimeParams * __fastcall GetDateTimeParams()
  691. {
  692. if (!DateTimeParamsInitialized)
  693. {
  694. TGuard Guard(&DateTimeParamsSection);
  695. if (!DateTimeParamsInitialized)
  696. {
  697. TIME_ZONE_INFORMATION TZI;
  698. unsigned long GTZI;
  699. GTZI = GetTimeZoneInformation(&TZI);
  700. switch (GTZI)
  701. {
  702. case TIME_ZONE_ID_UNKNOWN:
  703. DateTimeParams.CurrentDaylightDifferenceSec = 0;
  704. break;
  705. case TIME_ZONE_ID_STANDARD:
  706. DateTimeParams.CurrentDaylightDifferenceSec = TZI.StandardBias;
  707. break;
  708. case TIME_ZONE_ID_DAYLIGHT:
  709. DateTimeParams.CurrentDaylightDifferenceSec = TZI.DaylightBias;
  710. break;
  711. case TIME_ZONE_ID_INVALID:
  712. default:
  713. throw Exception(TIMEZONE_ERROR);
  714. }
  715. // Is it same as SysUtils::UnixDateDelta = 25569 ??
  716. DateTimeParams.UnixEpoch = EncodeDateVerbose(1970, 1, 1);
  717. DateTimeParams.BaseDifferenceSec = TZI.Bias;
  718. DateTimeParams.BaseDifference = double(TZI.Bias) / 1440;
  719. DateTimeParams.BaseDifferenceSec *= 60;
  720. DateTimeParams.CurrentDifferenceSec = TZI.Bias +
  721. DateTimeParams.CurrentDaylightDifferenceSec;
  722. DateTimeParams.CurrentDifference =
  723. double(DateTimeParams.CurrentDifferenceSec) / 1440;
  724. DateTimeParams.CurrentDifferenceSec *= 60;
  725. DateTimeParams.CurrentDaylightDifference =
  726. double(DateTimeParams.CurrentDaylightDifferenceSec) / 1440;
  727. DateTimeParams.CurrentDaylightDifferenceSec *= 60;
  728. DateTimeParams.DaylightDifferenceSec = TZI.DaylightBias * 60;
  729. DateTimeParams.DaylightDifference = double(TZI.DaylightBias) / 1440;
  730. DateTimeParams.StandardDifferenceSec = TZI.StandardBias * 60;
  731. DateTimeParams.StandardDifference = double(TZI.StandardBias) / 1440;
  732. DateTimeParams.StandardDate = TZI.StandardDate;
  733. DateTimeParams.DaylightDate = TZI.DaylightDate;
  734. DateTimeParamsInitialized = true;
  735. }
  736. }
  737. return &DateTimeParams;
  738. }
  739. //---------------------------------------------------------------------------
  740. static void __fastcall EncodeDSTMargin(const SYSTEMTIME & Date, unsigned short Year,
  741. TDateTime & Result)
  742. {
  743. if (Date.wYear == 0)
  744. {
  745. TDateTime Temp = EncodeDateVerbose(Year, Date.wMonth, 1);
  746. Result = Temp + ((Date.wDayOfWeek - DayOfWeek(Temp) + 8) % 7) +
  747. (7 * (Date.wDay - 1));
  748. if (Date.wDay == 5)
  749. {
  750. unsigned short Month = static_cast<unsigned short>(Date.wMonth + 1);
  751. if (Month > 12)
  752. {
  753. Month = static_cast<unsigned short>(Month - 12);
  754. Year++;
  755. }
  756. if (Result >= EncodeDateVerbose(Year, Month, 1))
  757. {
  758. Result -= 7;
  759. }
  760. }
  761. Result += EncodeTimeVerbose(Date.wHour, Date.wMinute, Date.wSecond,
  762. Date.wMilliseconds);
  763. }
  764. else
  765. {
  766. Result = EncodeDateVerbose(Year, Date.wMonth, Date.wDay) +
  767. EncodeTimeVerbose(Date.wHour, Date.wMinute, Date.wSecond, Date.wMilliseconds);
  768. }
  769. }
  770. //---------------------------------------------------------------------------
  771. static bool __fastcall IsDateInDST(const TDateTime & DateTime)
  772. {
  773. struct TDSTCache
  774. {
  775. bool Filled;
  776. unsigned short Year;
  777. TDateTime StandardDate;
  778. TDateTime DaylightDate;
  779. };
  780. static TDSTCache DSTCache[10];
  781. static int DSTCacheCount = 0;
  782. static TCriticalSection Section;
  783. TDateTimeParams * Params = GetDateTimeParams();
  784. bool Result;
  785. // On some systems it occurs that StandardDate is unset, while
  786. // DaylightDate is set. MSDN states that this is invalid and
  787. // should be treated as if there is no daylinght saving.
  788. // So check both.
  789. if ((Params->StandardDate.wMonth == 0) ||
  790. (Params->DaylightDate.wMonth == 0))
  791. {
  792. Result = false;
  793. }
  794. else
  795. {
  796. unsigned short Year, Month, Day;
  797. DecodeDate(DateTime, Year, Month, Day);
  798. TDSTCache * CurrentCache = &DSTCache[0];
  799. int CacheIndex = 0;
  800. while ((CacheIndex < DSTCacheCount) && (CacheIndex < LENOF(DSTCache)) &&
  801. CurrentCache->Filled && (CurrentCache->Year != Year))
  802. {
  803. CacheIndex++;
  804. CurrentCache++;
  805. }
  806. if ((CacheIndex < DSTCacheCount) && (CacheIndex < LENOF(DSTCache)) &&
  807. CurrentCache->Filled)
  808. {
  809. assert(CurrentCache->Year == Year);
  810. Result = (DateTime >= CurrentCache->DaylightDate) &&
  811. (DateTime < CurrentCache->StandardDate);
  812. }
  813. else
  814. {
  815. TDSTCache NewCache;
  816. EncodeDSTMargin(Params->StandardDate, Year, NewCache.StandardDate);
  817. EncodeDSTMargin(Params->DaylightDate, Year, NewCache.DaylightDate);
  818. if (DSTCacheCount < LENOF(DSTCache))
  819. {
  820. TGuard Guard(&Section);
  821. if (DSTCacheCount < LENOF(DSTCache))
  822. {
  823. NewCache.Year = Year;
  824. DSTCache[DSTCacheCount] = NewCache;
  825. DSTCache[DSTCacheCount].Filled = true;
  826. DSTCacheCount++;
  827. }
  828. }
  829. Result = (DateTime >= NewCache.DaylightDate) &&
  830. (DateTime < NewCache.StandardDate);
  831. }
  832. }
  833. return Result;
  834. }
  835. //---------------------------------------------------------------------------
  836. TDateTime __fastcall UnixToDateTime(__int64 TimeStamp, TDSTMode DSTMode)
  837. {
  838. TDateTimeParams * Params = GetDateTimeParams();
  839. TDateTime Result;
  840. Result = Params->UnixEpoch + (double(TimeStamp) / 86400);
  841. if ((DSTMode == dstmWin) || (DSTMode == dstmUnix))
  842. {
  843. Result -= Params->CurrentDifference;
  844. }
  845. else if (DSTMode == dstmKeep)
  846. {
  847. Result -= Params->BaseDifference;
  848. }
  849. if ((DSTMode == dstmUnix) || (DSTMode == dstmKeep))
  850. {
  851. Result -= (IsDateInDST(Result) ?
  852. Params->DaylightDifference : Params->StandardDifference);
  853. }
  854. return Result;
  855. }
  856. //---------------------------------------------------------------------------
  857. inline __int64 __fastcall Round(double Number)
  858. {
  859. double Floor = floor(Number);
  860. double Ceil = ceil(Number);
  861. return ((Number - Floor) > (Ceil - Number)) ? Ceil : Floor;
  862. }
  863. //---------------------------------------------------------------------------
  864. #define TIME_POSIX_TO_WIN(t, ft) (*(LONGLONG*)&(ft) = \
  865. ((LONGLONG) (t) + (LONGLONG) 11644473600) * (LONGLONG) 10000000)
  866. #define TIME_WIN_TO_POSIX(ft, t) ((t) = (__int64) \
  867. ((*(LONGLONG*)&(ft)) / (LONGLONG) 10000000 - (LONGLONG) 11644473600))
  868. //---------------------------------------------------------------------------
  869. static __int64 __fastcall DateTimeToUnix(const TDateTime DateTime)
  870. {
  871. TDateTimeParams * Params = GetDateTimeParams();
  872. return Round(double(DateTime - Params->UnixEpoch) * 86400) +
  873. Params->CurrentDifferenceSec;
  874. }
  875. //---------------------------------------------------------------------------
  876. FILETIME __fastcall DateTimeToFileTime(const TDateTime DateTime,
  877. TDSTMode /*DSTMode*/)
  878. {
  879. FILETIME Result;
  880. __int64 UnixTimeStamp = DateTimeToUnix(DateTime);
  881. TIME_POSIX_TO_WIN(UnixTimeStamp, Result);
  882. return Result;
  883. }
  884. //---------------------------------------------------------------------------
  885. __int64 __fastcall ConvertTimestampToUnix(const FILETIME & FileTime,
  886. TDSTMode DSTMode)
  887. {
  888. __int64 Result;
  889. TIME_WIN_TO_POSIX(FileTime, Result);
  890. if ((DSTMode == dstmUnix) || (DSTMode == dstmKeep))
  891. {
  892. FILETIME LocalFileTime;
  893. SYSTEMTIME SystemTime;
  894. TDateTime DateTime;
  895. FileTimeToLocalFileTime(&FileTime, &LocalFileTime);
  896. FileTimeToSystemTime(&LocalFileTime, &SystemTime);
  897. DateTime = SystemTimeToDateTime(SystemTime);
  898. TDateTimeParams * Params = GetDateTimeParams();
  899. Result += (IsDateInDST(DateTime) ?
  900. Params->DaylightDifferenceSec : Params->StandardDifferenceSec);
  901. if (DSTMode == dstmKeep)
  902. {
  903. Result -= Params->CurrentDaylightDifferenceSec;
  904. }
  905. }
  906. return Result;
  907. }
  908. //---------------------------------------------------------------------------
  909. TDateTime __fastcall ConvertTimestampToUTC(TDateTime DateTime)
  910. {
  911. TDateTimeParams * Params = GetDateTimeParams();
  912. DateTime += Params->CurrentDifference;
  913. DateTime +=
  914. (IsDateInDST(DateTime) ?
  915. Params->DaylightDifference : Params->StandardDifference);
  916. return DateTime;
  917. }
  918. //---------------------------------------------------------------------------
  919. __int64 __fastcall ConvertTimestampToUnixSafe(const FILETIME & FileTime,
  920. TDSTMode DSTMode)
  921. {
  922. __int64 Result;
  923. if ((FileTime.dwLowDateTime == 0) &&
  924. (FileTime.dwHighDateTime == 0))
  925. {
  926. Result = DateTimeToUnix(Now());
  927. }
  928. else
  929. {
  930. Result = ConvertTimestampToUnix(FileTime, DSTMode);
  931. }
  932. return Result;
  933. }
  934. //---------------------------------------------------------------------------
  935. TDateTime __fastcall AdjustDateTimeFromUnix(TDateTime DateTime, TDSTMode DSTMode)
  936. {
  937. TDateTimeParams * Params = GetDateTimeParams();
  938. if ((DSTMode == dstmWin) || (DSTMode == dstmUnix))
  939. {
  940. DateTime = DateTime - Params->CurrentDaylightDifference;
  941. }
  942. if (!IsDateInDST(DateTime))
  943. {
  944. if (DSTMode == dstmWin)
  945. {
  946. DateTime = DateTime - Params->DaylightDifference;
  947. }
  948. }
  949. else
  950. {
  951. DateTime = DateTime - Params->StandardDifference;
  952. }
  953. return DateTime;
  954. }
  955. //---------------------------------------------------------------------------
  956. __inline static bool __fastcall UnifySignificance(unsigned short & V1,
  957. unsigned short & V2)
  958. {
  959. bool Result = (V1 == 0) || (V2 == 0);
  960. if (Result)
  961. {
  962. V1 = 0;
  963. V2 = 0;
  964. }
  965. return Result;
  966. }
  967. //---------------------------------------------------------------------------
  968. void __fastcall UnifyDateTimePrecision(TDateTime & DateTime1, TDateTime & DateTime2)
  969. {
  970. unsigned short Y1, M1, D1, H1, N1, S1, MS1;
  971. unsigned short Y2, M2, D2, H2, N2, S2, MS2;
  972. bool Changed;
  973. if (DateTime1 != DateTime2)
  974. {
  975. DateTime1.DecodeDate(&Y1, &M1, &D1);
  976. DateTime1.DecodeTime(&H1, &N1, &S1, &MS1);
  977. DateTime2.DecodeDate(&Y2, &M2, &D2);
  978. DateTime2.DecodeTime(&H2, &N2, &S2, &MS2);
  979. Changed = UnifySignificance(MS1, MS2);
  980. if (Changed && UnifySignificance(S1, S2) && UnifySignificance(N1, N2) &&
  981. UnifySignificance(H1, H2) && UnifySignificance(D1, D2) &&
  982. UnifySignificance(M1, M2))
  983. {
  984. UnifySignificance(Y1, Y2);
  985. }
  986. if (Changed)
  987. {
  988. DateTime1 = EncodeDateVerbose(Y1, M1, D1) + EncodeTimeVerbose(H1, N1, S1, MS1);
  989. DateTime2 = EncodeDateVerbose(Y2, M2, D2) + EncodeTimeVerbose(H2, N2, S2, MS2);
  990. }
  991. }
  992. }
  993. //---------------------------------------------------------------------------
  994. AnsiString __fastcall FixedLenDateTimeFormat(const AnsiString & Format)
  995. {
  996. AnsiString Result = Format;
  997. bool AsIs = false;
  998. int Index = 1;
  999. while (Index <= Result.Length())
  1000. {
  1001. char F = Result[Index];
  1002. if ((F == '\'') || (F == '\"'))
  1003. {
  1004. AsIs = !AsIs;
  1005. Index++;
  1006. }
  1007. else if (!AsIs && ((F == 'a') || (F == 'A')))
  1008. {
  1009. if (Result.SubString(Index, 5).LowerCase() == "am/pm")
  1010. {
  1011. Index += 5;
  1012. }
  1013. else if (Result.SubString(Index, 3).LowerCase() == "a/p")
  1014. {
  1015. Index += 3;
  1016. }
  1017. else if (Result.SubString(Index, 4).LowerCase() == "ampm")
  1018. {
  1019. Index += 4;
  1020. }
  1021. else
  1022. {
  1023. Index++;
  1024. }
  1025. }
  1026. else
  1027. {
  1028. if (!AsIs && (strchr("dDeEmMhHnNsS", F) != NULL) &&
  1029. ((Index == Result.Length()) || (Result[Index + 1] != F)))
  1030. {
  1031. Result.Insert(F, Index);
  1032. }
  1033. while ((Index <= Result.Length()) && (F == Result[Index]))
  1034. {
  1035. Index++;
  1036. }
  1037. }
  1038. }
  1039. return Result;
  1040. }
  1041. //---------------------------------------------------------------------------
  1042. int __fastcall CompareFileTime(TDateTime T1, TDateTime T2)
  1043. {
  1044. // "FAT" time precision
  1045. // (when one time is seconds-precision and other is millisecond-precision,
  1046. // we may have times like 12:00:00.000 and 12:00:01.999, which should
  1047. // be treated the same)
  1048. static TDateTime TwoSeconds(0, 0, 2, 0);
  1049. int Result;
  1050. if (T1 == T2)
  1051. {
  1052. // just optimalisation
  1053. Result = 0;
  1054. }
  1055. else if ((T1 < T2) && (T2 - T1 >= TwoSeconds))
  1056. {
  1057. Result = -1;
  1058. }
  1059. else if ((T1 > T2) && (T1 - T2 >= TwoSeconds))
  1060. {
  1061. Result = 1;
  1062. }
  1063. else
  1064. {
  1065. Result = 0;
  1066. }
  1067. return Result;
  1068. }
  1069. //---------------------------------------------------------------------------
  1070. bool __fastcall RecursiveDeleteFile(const AnsiString FileName, bool ToRecycleBin)
  1071. {
  1072. SHFILEOPSTRUCT Data;
  1073. memset(&Data, 0, sizeof(Data));
  1074. Data.hwnd = NULL;
  1075. Data.wFunc = FO_DELETE;
  1076. AnsiString FileList(FileName);
  1077. FileList.SetLength(FileList.Length() + 2);
  1078. FileList[FileList.Length() - 1] = '\0';
  1079. FileList[FileList.Length()] = '\0';
  1080. Data.pFrom = FileList.c_str();
  1081. Data.pTo = "";
  1082. Data.fFlags = FOF_NOCONFIRMATION | FOF_RENAMEONCOLLISION | FOF_NOCONFIRMMKDIR |
  1083. FOF_NOERRORUI | FOF_SILENT;
  1084. if (ToRecycleBin)
  1085. {
  1086. Data.fFlags |= FOF_ALLOWUNDO;
  1087. }
  1088. int ErrorCode = SHFileOperation(&Data);
  1089. bool Result = (ErrorCode == 0);
  1090. if (!Result)
  1091. {
  1092. // according to MSDN, SHFileOperation may return following non-Win32
  1093. // error codes
  1094. if (((ErrorCode >= 0x71) && (ErrorCode <= 0x88)) ||
  1095. (ErrorCode == 0xB7) || (ErrorCode == 0x402) || (ErrorCode == 0x10000) ||
  1096. (ErrorCode == 0x10074))
  1097. {
  1098. ErrorCode = 0;
  1099. }
  1100. SetLastError(ErrorCode);
  1101. }
  1102. return Result;
  1103. }
  1104. //---------------------------------------------------------------------------
  1105. int __fastcall CancelAnswer(int Answers)
  1106. {
  1107. int Result;
  1108. if ((Answers & qaCancel) != 0)
  1109. {
  1110. Result = qaCancel;
  1111. }
  1112. else if ((Answers & qaNo) != 0)
  1113. {
  1114. Result = qaNo;
  1115. }
  1116. else if ((Answers & qaAbort) != 0)
  1117. {
  1118. Result = qaAbort;
  1119. }
  1120. else if ((Answers & qaOK) != 0)
  1121. {
  1122. Result = qaOK;
  1123. }
  1124. else
  1125. {
  1126. assert(false);
  1127. Result = qaCancel;
  1128. }
  1129. return Result;
  1130. }
  1131. //---------------------------------------------------------------------------
  1132. int __fastcall AbortAnswer(int Answers)
  1133. {
  1134. int Result;
  1135. if (FLAGSET(Answers, qaAbort))
  1136. {
  1137. Result = qaAbort;
  1138. }
  1139. else
  1140. {
  1141. Result = CancelAnswer(Answers);
  1142. }
  1143. return Result;
  1144. }
  1145. //---------------------------------------------------------------------------
  1146. int __fastcall ContinueAnswer(int Answers)
  1147. {
  1148. int Result;
  1149. if (FLAGSET(Answers, qaSkip))
  1150. {
  1151. Result = qaSkip;
  1152. }
  1153. else if (FLAGSET(Answers, qaIgnore))
  1154. {
  1155. Result = qaIgnore;
  1156. }
  1157. else if (FLAGSET(Answers, qaYes))
  1158. {
  1159. Result = qaYes;
  1160. }
  1161. else if (FLAGSET(Answers, qaOK))
  1162. {
  1163. Result = qaOK;
  1164. }
  1165. else if (FLAGSET(Answers, qaRetry))
  1166. {
  1167. Result = qaRetry;
  1168. }
  1169. else
  1170. {
  1171. Result = CancelAnswer(Answers);
  1172. }
  1173. return Result;
  1174. }
  1175. //---------------------------------------------------------------------------
  1176. TPasLibModule * __fastcall FindModule(void * Instance)
  1177. {
  1178. TPasLibModule * CurModule;
  1179. CurModule = reinterpret_cast<TPasLibModule*>(LibModuleList);
  1180. while (CurModule)
  1181. {
  1182. if (CurModule->Instance == Instance)
  1183. {
  1184. break;
  1185. }
  1186. else
  1187. {
  1188. CurModule = CurModule->Next;
  1189. }
  1190. }
  1191. return CurModule;
  1192. }
  1193. //---------------------------------------------------------------------------
  1194. AnsiString __fastcall LoadStr(int Ident, unsigned int MaxLength)
  1195. {
  1196. TPasLibModule * MainModule = FindModule(HInstance);
  1197. assert(MainModule != NULL);
  1198. AnsiString Result;
  1199. Result.SetLength(MaxLength);
  1200. int Length = LoadString(MainModule->ResInstance, Ident, Result.c_str(), MaxLength);
  1201. Result.SetLength(Length);
  1202. return Result;
  1203. }
  1204. //---------------------------------------------------------------------------
  1205. AnsiString __fastcall LoadStrPart(int Ident, int Part)
  1206. {
  1207. AnsiString Result;
  1208. AnsiString Str = LoadStr(Ident);
  1209. while (Part > 0)
  1210. {
  1211. Result = CutToChar(Str, '|', false);
  1212. Part--;
  1213. }
  1214. return Result;
  1215. }
  1216. //---------------------------------------------------------------------------
  1217. AnsiString __fastcall DecodeUrlChars(AnsiString S)
  1218. {
  1219. int i = 1;
  1220. while (i <= S.Length())
  1221. {
  1222. switch (S[i])
  1223. {
  1224. case '+':
  1225. S[i] = ' ';
  1226. break;
  1227. case '%':
  1228. if (i <= S.Length() - 2)
  1229. {
  1230. AnsiString C = HexToStr(S.SubString(i + 1, 2));
  1231. if (C.Length() == 1)
  1232. {
  1233. S[i] = C[1];
  1234. S.Delete(i + 1, 2);
  1235. }
  1236. }
  1237. break;
  1238. }
  1239. i++;
  1240. }
  1241. return S;
  1242. }
  1243. //---------------------------------------------------------------------------
  1244. AnsiString __fastcall DoEncodeUrl(AnsiString S, AnsiString Chars)
  1245. {
  1246. int i = 1;
  1247. while (i <= S.Length())
  1248. {
  1249. if (Chars.Pos(S[i]) > 0)
  1250. {
  1251. AnsiString H = CharToHex(S[i]);
  1252. S.Insert(H, i + 1);
  1253. S[i] = '%';
  1254. i += H.Length();
  1255. }
  1256. i++;
  1257. }
  1258. return S;
  1259. }
  1260. //---------------------------------------------------------------------------
  1261. AnsiString __fastcall EncodeUrlChars(AnsiString S, AnsiString Ignore)
  1262. {
  1263. AnsiString Chars;
  1264. if (Ignore.Pos(' ') == 0)
  1265. {
  1266. Chars += ' ';
  1267. }
  1268. if (Ignore.Pos('/') == 0)
  1269. {
  1270. Chars += '/';
  1271. }
  1272. return DoEncodeUrl(S, Chars);
  1273. }
  1274. //---------------------------------------------------------------------------
  1275. AnsiString __fastcall NonUrlChars()
  1276. {
  1277. AnsiString S;
  1278. for (unsigned int I = 0; I <= 255; I++)
  1279. {
  1280. char C = static_cast<char>(I);
  1281. if (((C >= 'a') && (C <= 'z')) ||
  1282. ((C >= 'A') && (C <= 'Z')) ||
  1283. ((C >= '0') && (C <= '9')) ||
  1284. (C == '_') || (C == '-') || (C == '.'))
  1285. {
  1286. // noop
  1287. }
  1288. else
  1289. {
  1290. S += C;
  1291. }
  1292. }
  1293. return S;
  1294. }
  1295. //---------------------------------------------------------------------------
  1296. AnsiString __fastcall EncodeUrlString(AnsiString S)
  1297. {
  1298. return DoEncodeUrl(S, NonUrlChars());
  1299. }
  1300. //---------------------------------------------------------------------------
  1301. void __fastcall OemToAnsi(AnsiString & Str)
  1302. {
  1303. if (!Str.IsEmpty())
  1304. {
  1305. Str.Unique();
  1306. OemToChar(Str.c_str(), Str.c_str());
  1307. }
  1308. }
  1309. //---------------------------------------------------------------------------
  1310. void __fastcall AnsiToOem(AnsiString & Str)
  1311. {
  1312. if (!Str.IsEmpty())
  1313. {
  1314. Str.Unique();
  1315. CharToOem(Str.c_str(), Str.c_str());
  1316. }
  1317. }
  1318. //---------------------------------------------------------------------------
  1319. AnsiString __fastcall EscapeHotkey(const AnsiString & Caption)
  1320. {
  1321. return StringReplace(Caption, "&", "&&", TReplaceFlags() << rfReplaceAll);
  1322. }
  1323. //---------------------------------------------------------------------------
  1324. // duplicated in console's Main.cpp
  1325. bool __fastcall CutToken(AnsiString & Str, AnsiString & Token)
  1326. {
  1327. bool Result;
  1328. Token = "";
  1329. // inspired by Putty's sftp_getcmd() from PSFTP.C
  1330. int Index = 1;
  1331. while ((Index <= Str.Length()) &&
  1332. ((Str[Index] == ' ') || (Str[Index] == '\t')))
  1333. {
  1334. Index++;
  1335. }
  1336. if (Index <= Str.Length())
  1337. {
  1338. bool Quoting = false;
  1339. while (Index <= Str.Length())
  1340. {
  1341. if (!Quoting && ((Str[Index] == ' ') || (Str[Index] == '\t')))
  1342. {
  1343. break;
  1344. }
  1345. else if ((Str[Index] == '"') && (Index + 1 <= Str.Length()) &&
  1346. (Str[Index + 1] == '"'))
  1347. {
  1348. Index += 2;
  1349. Token += '"';
  1350. }
  1351. else if (Str[Index] == '"')
  1352. {
  1353. Index++;
  1354. Quoting = !Quoting;
  1355. }
  1356. else
  1357. {
  1358. Token += Str[Index];
  1359. Index++;
  1360. }
  1361. }
  1362. if (Index <= Str.Length())
  1363. {
  1364. Index++;
  1365. }
  1366. Str = Str.SubString(Index, Str.Length());
  1367. Result = true;
  1368. }
  1369. else
  1370. {
  1371. Result = false;
  1372. Str = "";
  1373. }
  1374. return Result;
  1375. }
  1376. //---------------------------------------------------------------------------
  1377. void __fastcall AddToList(AnsiString & List, const AnsiString & Value, char Delimiter)
  1378. {
  1379. if (!List.IsEmpty() && (List[List.Length()] != Delimiter))
  1380. {
  1381. List += Delimiter;
  1382. }
  1383. List += Value;
  1384. }