Quick.Commons.pas 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312
  1. { ***************************************************************************
  2. Copyright (c) 2016-2019 Kike Pérez
  3. Unit : Quick.Commons
  4. Description : Common functions
  5. Author : Kike Pérez
  6. Version : 1.7
  7. Created : 14/07/2017
  8. Modified : 20/02/2019
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.Commons;
  22. {$i QuickLib.inc}
  23. interface
  24. uses
  25. Classes,
  26. SysUtils,
  27. Types,
  28. {$IFDEF MSWINDOWS}
  29. Windows,
  30. ShlObj,
  31. Registry,
  32. {$ENDIF MSWINDOWS}
  33. {$IFDEF FPC}
  34. Quick.Files,
  35. {$IFDEF LINUX}
  36. FileInfo,
  37. {$ENDIF}
  38. {$ELSE}
  39. IOUtils,
  40. {$ENDIF}
  41. {$IFDEF ANDROID}
  42. Androidapi.JNI.Os,
  43. Androidapi.Helpers,
  44. Androidapi.JNI.JavaTypes,
  45. Androidapi.JNI.GraphicsContentViewText,
  46. {$ENDIF}
  47. {$IFDEF IOS}
  48. iOSapi.UIKit,
  49. Posix.SysSysctl,
  50. Posix.StdDef,
  51. iOSapi.Foundation,
  52. Macapi.ObjectiveC,
  53. Macapi.Helpers,
  54. {$ENDIF}
  55. {$IFDEF OSX}
  56. Macapi.Foundation,
  57. Macapi.Helpers,
  58. FMX.Helpers.Mac,
  59. Macapi.ObjectiveC,
  60. {$ENDIF}
  61. {$IFDEF POSIX}
  62. Posix.Unistd,
  63. {$ENDIF}
  64. DateUtils;
  65. type
  66. TLogEventType = (etInfo, etSuccess, etWarning, etError, etDebug, etTrace);
  67. TLogVerbose = set of TLogEventType;
  68. const
  69. LOG_ONLYERRORS = [etInfo,etError];
  70. LOG_ERRORSANDWARNINGS = [etInfo,etWarning,etError];
  71. LOG_TRACE = [etInfo,etError,etWarning,etTrace];
  72. LOG_ALL = [etInfo,etSuccess,etWarning,etError,etTrace];
  73. LOG_DEBUG = [etInfo,etSuccess,etWarning,etError,etDebug];
  74. {$IFDEF DELPHIXE7_UP}
  75. EventStr : array of string = ['INFO','SUCC','WARN','ERROR','DEBUG','TRACE'];
  76. {$ELSE}
  77. EventStr : array[0..5] of string = ('INFO','SUCC','WARN','ERROR','DEBUG','TRACE');
  78. {$ENDIF}
  79. type
  80. TPasswordComplexity = set of (pfIncludeNumbers,pfIncludeSigns);
  81. {$IFDEF MSWINDOWS}
  82. TEnvironmentPath = record
  83. EXEPATH : string;
  84. WINDOWS : string;
  85. SYSTEM : string;
  86. PROGRAMFILES : string;
  87. COMMONFILES : string;
  88. HOMEDRIVE : string;
  89. TEMP : string;
  90. USERPROFILE : string;
  91. INSTDRIVE : string;
  92. DESKTOP : string;
  93. STARTMENU : string;
  94. DESKTOP_ALLUSERS : string;
  95. STARTMENU_ALLUSERS : string;
  96. STARTUP : string;
  97. APPDATA : String;
  98. PROGRAMDATA : string;
  99. ALLUSERSPROFILE : string;
  100. end;
  101. {$ENDIF MSWINDOWS}
  102. {$IFNDEF FPC}
  103. TFileHelper = record helper for TFile
  104. {$IF DEFINED(MSWINDOWS) OR DEFINED(DELPHILINUX)}
  105. class function IsInUse(const FileName : string) : Boolean; static;
  106. {$ENDIF}
  107. class function GetSize(const FileName: String): Int64; static;
  108. end;
  109. TDirectoryHelper = record helper for TDirectory
  110. class function GetSize(const Path: String): Int64; static;
  111. end;
  112. {$ENDIF}
  113. {$IFDEF FPC}
  114. {$IFDEF LINUX}
  115. UINT = cardinal;
  116. {$ENDIF}
  117. PLASTINPUTINFO = ^LASTINPUTINFO;
  118. tagLASTINPUTINFO = record
  119. cbSize: UINT;
  120. dwTime: DWORD;
  121. end;
  122. LASTINPUTINFO = tagLASTINPUTINFO;
  123. TLastInputInfo = LASTINPUTINFO;
  124. type
  125. TCmdLineSwitchType = (clstValueNextParam, clstValueAppended);
  126. TCmdLineSwitchTypes = set of TCmdLineSwitchType;
  127. {$ENDIF}
  128. TCounter = record
  129. private
  130. fMaxValue : Integer;
  131. fCurrentValue : Integer;
  132. public
  133. property MaxValue : Integer read fMaxValue;
  134. procedure Init(aMaxValue : Integer);
  135. function Count : Integer;
  136. function CountIs(aValue : Integer) : Boolean;
  137. function Check : Boolean;
  138. procedure Reset;
  139. end;
  140. TTimeCounter = record
  141. private
  142. fCurrentTime : TDateTime;
  143. fDoneEvery : Integer;
  144. public
  145. property DoneEvery : Integer read fDoneEvery;
  146. procedure Init(MillisecondsToReach : Integer);
  147. function Check : Boolean;
  148. procedure Reset;
  149. end;
  150. EEnvironmentPath = class(Exception);
  151. EShellError = class(Exception);
  152. //generates a random password with complexity options
  153. function RandomPassword(const PasswordLength : Integer; Complexity : TPasswordComplexity = [pfIncludeNumbers,pfIncludeSigns]) : string;
  154. //extracts file extension from a filename
  155. function ExtractFileNameWithoutExt(const FileName: string): string;
  156. //converts a Unix path to Windows path
  157. function UnixToWindowsPath(const UnixPath: string): string;
  158. //converts a Windows path to Unix path
  159. function WindowsToUnixPath(const WindowsPath: string): string;
  160. //corrects malformed urls
  161. function CorrectURLPath(cUrl : string) : string;
  162. {$IFDEF MSWINDOWS}
  163. //get typical environment paths as temp, desktop, etc
  164. procedure GetEnvironmentPaths;
  165. function GetSpecialFolderPath(folderID : Integer) : string;
  166. //checks if running on a 64bit OS
  167. function Is64bitOS : Boolean;
  168. //checks if is a console app
  169. function IsConsole : Boolean;
  170. //checks if compiled in debug mode
  171. {$ENDIF}
  172. function IsDebug : Boolean;
  173. {$IFDEF MSWINDOWS}
  174. //checks if running as a service
  175. function IsService : Boolean;
  176. //gets number of seconds without user interaction (mouse, keyboard)
  177. function SecondsIdle: DWord;
  178. //frees process memory not needed
  179. procedure FreeUnusedMem;
  180. //changes screen resolution
  181. function SetScreenResolution(Width, Height: integer): Longint;
  182. {$ENDIF MSWINDOWS}
  183. //returns last day of current month
  184. function LastDayCurrentMonth: TDateTime;
  185. {$IFDEF FPC}
  186. function DateTimeInRange(ADateTime: TDateTime; AStartDateTime, AEndDateTime: TDateTime; aInclusive: Boolean = True): Boolean;
  187. {$ENDIF}
  188. //checks if two datetimes are in same day
  189. function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
  190. //change Time of a DateTime
  191. function ChangeTimeOfADay(aDate : TDateTime; aHour, aMinute, aSecond : Word; aMilliSecond : Word = 0) : TDateTime;
  192. //change Date of a DateTime
  193. function ChangeDateOfADay(aDate : TDateTime; aYear, aMonth, aDay : Word) : TDateTime;
  194. //returns n times a char
  195. function FillStr(const C : Char; const Count : Byte) : string;
  196. //checks if string exists in array of string
  197. function StrInArray(const aValue : string; const aInArray : array of string) : Boolean;
  198. //checks if integer exists in array of integer
  199. function IntInArray(const aValue : Integer; const aInArray : array of Integer) : Boolean;
  200. //returns a number leading zero
  201. function Zeroes(const Number, Len : Int64) : string;
  202. //converts a number to thousand delimeter string
  203. function NumberToStr(const Number : Int64) : string;
  204. //returns n spaces
  205. function Spaces(const Count : Integer) : string;
  206. //returns current date as a string
  207. function NowStr : string;
  208. //returns a new GUID as string
  209. function NewGuidStr : string;
  210. //compare a string with a wildcard pattern (? or *)
  211. function IsLike(cText, Pattern: string) : Boolean;
  212. //Upper case for first letter
  213. function Capitalize(s: string): string;
  214. function CapitalizeWords(s: string): string;
  215. //returns current logged user
  216. function GetLoggedUserName : string;
  217. //returns computer name
  218. function GetComputerName : string;
  219. //Changes incorrect delims in path
  220. function NormalizePathDelim(const cPath : string; const Delim : Char) : string;
  221. //Removes last segment of a path
  222. function RemoveLastPathSegment(cDir : string) : string;
  223. //finds swith in commandline params
  224. function ParamFindSwitch(const Switch : string) : Boolean;
  225. //gets value for a switch if exists
  226. function ParamGetSwitch(const Switch : string; var cvalue : string) : Boolean;
  227. //returns app name (filename based)
  228. function GetAppName : string;
  229. //returns app version (major & minor)
  230. function GetAppVersionStr: string;
  231. //returns app version full (major, minor, release & compiled)
  232. function GetAppVersionFullStr: string;
  233. //convert UTC DateTime to Local DateTime
  234. function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
  235. //convert Local DateTime to UTC DateTime
  236. function LocalTimeToUTC(LocalTime : TDateTime): TDateTime;
  237. //convert DateTime to GTM Time string
  238. function DateTimeToGMT(aDate : TDateTime) : string;
  239. //convert GMT Time string to DateTime
  240. function GMTToDateTime(aDate : string) : TDateTime;
  241. //convert DateTime to Json Date format
  242. function DateTimeToJsonDate(aDateTime : TDateTime) : string;
  243. //convert Json Date format to DateTime
  244. function JsonDateToDateTime(const aJsonDate : string) : TDateTime;
  245. //count number of digits of a Integer
  246. function CountDigits(anInt: Cardinal): Cardinal; inline;
  247. //save stream to file
  248. procedure SaveStreamToFile(stream : TStream; const filename : string);
  249. //returns a real comma separated text from stringlist
  250. function CommaText(aList : TStringList) : string;
  251. {$IFDEF MSWINDOWS}
  252. //process messages on console applications
  253. procedure ProcessMessages;
  254. //get last error message
  255. function GetLastOSError : String;
  256. {$ENDIF}
  257. {$IF DEFINED(FPC) AND DEFINED(MSWINDOWS)}
  258. function GetLastInputInfo(var plii: TLastInputInfo): BOOL;stdcall; external 'user32' name 'GetLastInputInfo';
  259. {$ENDIF}
  260. function RemoveLastChar(const aText : string) : string;
  261. function DateTimeToSQL(aDateTime : TDateTime) : string;
  262. function IsInteger(const aValue : string) : Boolean;
  263. {$IFDEF MSWINDOWS}
  264. var
  265. path : TEnvironmentPath;
  266. {$ENDIF}
  267. implementation
  268. {TFileHelper}
  269. {$IFNDEF FPC}
  270. {$IFDEF MSWINDOWS}
  271. class function TFileHelper.IsInUse(const FileName : string) : Boolean;
  272. var
  273. HFileRes: HFILE;
  274. begin
  275. Result := False;
  276. if not FileExists(FileName) then Exit;
  277. try
  278. HFileRes := CreateFile(PChar(FileName)
  279. ,GENERIC_READ or GENERIC_WRITE
  280. ,0
  281. ,nil
  282. ,OPEN_EXISTING
  283. ,FILE_ATTRIBUTE_NORMAL
  284. ,0);
  285. Result := (HFileRes = INVALID_HANDLE_VALUE);
  286. if not(Result) then begin
  287. CloseHandle(HFileRes);
  288. end;
  289. except
  290. Result := True;
  291. end;
  292. end;
  293. {$ENDIF}
  294. {$IFDEF DELPHILINUX}
  295. class function TFileHelper.IsInUse(const FileName : string) : Boolean;
  296. var
  297. fs : TFileStream;
  298. begin
  299. try
  300. fs := TFileStream.Create(FileName, fmOpenReadWrite, fmShareExclusive);
  301. Result := True;
  302. fs.Free;
  303. except
  304. Result := False;
  305. end;
  306. end;
  307. {$ENDIF}
  308. {$IFDEF MSWINDOWS}
  309. class function TFileHelper.GetSize(const FileName: String): Int64;
  310. var
  311. info: TWin32FileAttributeData;
  312. begin
  313. Result := -1;
  314. if not GetFileAttributesEx(PWideChar(FileName), GetFileExInfoStandard, @info) then Exit;
  315. Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
  316. end;
  317. {$ELSE}
  318. class function TFileHelper.GetSize(const FileName: String): Int64;
  319. var
  320. sr : TSearchRec;
  321. begin
  322. if FindFirst(fileName, faAnyFile, sr ) = 0 then Result := sr.Size
  323. else Result := -1;
  324. end;
  325. {$ENDIF}
  326. {TDirectoryHelper}
  327. class function TDirectoryHelper.GetSize(const Path: String): Int64;
  328. var
  329. filename : string;
  330. begin
  331. Result := -1;
  332. for filename in TDirectory.GetFiles(Path) do
  333. begin
  334. Result := Result + TFile.GetSize(filename);
  335. end;
  336. end;
  337. {$ENDIF}
  338. {other functions}
  339. function RandomPassword(const PasswordLength : Integer; Complexity : TPasswordComplexity = [pfIncludeNumbers,pfIncludeSigns]) : string;
  340. const
  341. PassAlpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  342. PassSigns = '@!&$';
  343. PassNumbers = '1234567890';
  344. var
  345. MinNumbers,
  346. MinSigns : Integer;
  347. NumNumbers,
  348. NumSigns : Integer;
  349. begin
  350. Result := '';
  351. Randomize;
  352. //fill all alfa
  353. repeat
  354. Result := Result + PassAlpha[Random(Length(PassAlpha))+1];
  355. until (Length(Result) = PasswordLength);
  356. //checks if need include numbers
  357. if pfIncludeNumbers in Complexity then
  358. begin
  359. MinNumbers := Round(PasswordLength / 10 * 2);
  360. NumNumbers := 0;
  361. if MinNumbers = 0 then MinNumbers := 1;
  362. repeat
  363. Result[Random(PasswordLength)+1] := PassNumbers[Random(Length(PassNumbers))+1];
  364. Inc(NumNumbers);
  365. until NumNumbers = MinNumbers;
  366. end;
  367. //checks if need include signs
  368. if pfIncludeNumbers in Complexity then
  369. begin
  370. MinSigns := Round(PasswordLength / 10 * 1);
  371. NumSigns := 0;
  372. if MinSigns = 0 then MinSigns := 1;
  373. repeat
  374. Result[Random(PasswordLength)+1] := PassSigns[Random(Length(PassSigns))+1];
  375. Inc(NumSigns);
  376. until NumSigns = MinSigns;
  377. end;
  378. end;
  379. function ExtractFileNameWithoutExt(const FileName: string): string;
  380. begin
  381. Result := TPath.GetFileNameWithoutExtension(FileName);
  382. end;
  383. function UnixToWindowsPath(const UnixPath: string): string;
  384. begin
  385. Result := StringReplace(UnixPath, '/', '\',[rfReplaceAll, rfIgnoreCase]);
  386. end;
  387. function WindowsToUnixPath(const WindowsPath: string): string;
  388. begin
  389. Result := StringReplace(WindowsPath, '\', '/',[rfReplaceAll, rfIgnoreCase]);
  390. end;
  391. function CorrectURLPath(cUrl : string) : string;
  392. var
  393. nurl : string;
  394. begin
  395. nurl := WindowsToUnixPath(cUrl);
  396. nurl := StringReplace(nurl,'//','/',[rfReplaceAll]);
  397. Result := StringReplace(nurl,' ','%20',[rfReplaceAll]);
  398. //TNetEncoding.Url.Encode()
  399. end;
  400. {$IFDEF MSWINDOWS}
  401. procedure GetEnvironmentPaths;
  402. begin
  403. //gets path
  404. path.EXEPATH := TPath.GetDirectoryName(ParamStr(0));
  405. path.WINDOWS := SysUtils.GetEnvironmentVariable('windir');
  406. path.PROGRAMFILES := SysUtils.GetEnvironmentVariable('ProgramFiles');
  407. path.COMMONFILES := SysUtils.GetEnvironmentVariable('CommonProgramFiles(x86)');
  408. path.HOMEDRIVE := SysUtils.GetEnvironmentVariable('SystemDrive');
  409. path.USERPROFILE := SysUtils.GetEnvironmentVariable('USERPROFILE');
  410. path.PROGRAMDATA := SysUtils.GetEnvironmentVariable('ProgramData');
  411. path.ALLUSERSPROFILE := SysUtils.GetEnvironmentVariable('AllUsersProfile');
  412. path.INSTDRIVE := path.HOMEDRIVE;
  413. path.TEMP := SysUtils.GetEnvironmentVariable('TEMP');
  414. path.SYSTEM := GetSpecialFolderPath(CSIDL_SYSTEM);
  415. path.APPDATA:=GetSpecialFolderPath(CSIDL_APPDATA);
  416. //these paths fail if user is SYSTEM
  417. try
  418. path.DESKTOP := GetSpecialFolderPath(CSIDL_DESKTOP);
  419. path.DESKTOP_ALLUSERS := GetSpecialFolderPath(CSIDL_COMMON_DESKTOPDIRECTORY);
  420. path.STARTMENU:=GetSpecialFolderPath(CSIDL_PROGRAMS);
  421. path.STARTMENU_ALLUSERS:=GetSpecialFolderPath(CSIDL_COMMON_PROGRAMS);
  422. path.STARTMENU_ALLUSERS := path.STARTMENU;
  423. path.STARTUP:=GetSpecialFolderPath(CSIDL_STARTUP);
  424. except
  425. //
  426. end;
  427. end;
  428. function GetSpecialFolderPath(folderID : Integer) : string;
  429. var
  430. ppidl: PItemIdList;
  431. begin
  432. SHGetSpecialFolderLocation(0, folderID, ppidl);
  433. SetLength(Result, MAX_PATH);
  434. if not SHGetPathFromIDList(ppidl,{$IFDEF FPC}PAnsiChar(Result){$ELSE}PChar(Result){$ENDIF}) then
  435. begin
  436. raise EShellError.create(Format('GetSpecialFolderPath: Invalid PIPL (%d)',[folderID]));
  437. end;
  438. SetLength(Result, lStrLen({$IFDEF FPC}PAnsiChar(Result){$ELSE}PChar(Result){$ENDIF}));
  439. end;
  440. function Is64bitOS : Boolean;
  441. begin
  442. {$IFDEF WIN64}
  443. Result := True;
  444. {$ELSE}
  445. Result := False;
  446. {$ENDIF WIN64}
  447. end;
  448. function IsConsole: Boolean;
  449. begin
  450. {$IFDEF CONSOLE}
  451. Result := True;
  452. {$ELSE}
  453. Result := False;
  454. {$ENDIF CONSOLE}
  455. end;
  456. {$ENDIF}
  457. function IsDebug: Boolean;
  458. begin
  459. {$IFDEF DEBUG}
  460. Result := True;
  461. {$ELSE}
  462. Result := False;
  463. {$ENDIF DEBUG}
  464. end;
  465. {$IFDEF MSWINDOWS}
  466. function IsService : Boolean;
  467. begin
  468. //only working with my Quick.AppService unit
  469. try
  470. Result := (IsConsole) and (GetStdHandle(STD_OUTPUT_HANDLE) = 0);
  471. except
  472. Result := False;
  473. end;
  474. end;
  475. function SecondsIdle: DWord;
  476. var
  477. liInfo: TLastInputInfo;
  478. begin
  479. liInfo.cbSize := SizeOf(TLastInputInfo) ;
  480. GetLastInputInfo(liInfo) ;
  481. Result := (GetTickCount - liInfo.dwTime) DIV 1000;
  482. end;
  483. procedure FreeUnusedMem;
  484. begin
  485. if Win32Platform = VER_PLATFORM_WIN32_NT then SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
  486. end;
  487. function SetScreenResolution(Width, Height: integer): Longint;
  488. var
  489. DeviceMode: TDeviceMode;
  490. begin
  491. with DeviceMode do
  492. begin
  493. dmSize := SizeOf(TDeviceMode);
  494. dmPelsWidth := Width;
  495. dmPelsHeight := Height;
  496. dmFields := DM_PELSWIDTH or DM_PELSHEIGHT;
  497. end;
  498. Result := ChangeDisplaySettings(DeviceMode, CDS_UPDATEREGISTRY);
  499. end;
  500. {$ENDIF MSWINDOWS}
  501. function LastDayCurrentMonth: TDateTime;
  502. begin
  503. Result := EncodeDate(YearOf(Now),MonthOf(Now), DaysInMonth(Now));
  504. end;
  505. {$IFDEF FPC}
  506. function DateTimeInRange(ADateTime: TDateTime; AStartDateTime, AEndDateTime: TDateTime; aInclusive: Boolean = True): Boolean;
  507. begin
  508. if aInclusive then
  509. Result := (AStartDateTime <= ADateTime) and (ADateTime <= AEndDateTime)
  510. else
  511. Result := (AStartDateTime < ADateTime) and (ADateTime < AEndDateTime);
  512. end;
  513. {$ENDIF}
  514. function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
  515. begin
  516. //Test: Result := MinutesBetween(cBefore,cNow) < 1;
  517. Result := DateTimeInRange(cNow,StartOfTheDay(cBefore),EndOfTheDay(cBefore),True);
  518. end;
  519. function ChangeTimeOfADay(aDate : TDateTime; aHour, aMinute, aSecond : Word; aMilliSecond : Word = 0) : TDateTime;
  520. var
  521. y, m, d : Word;
  522. begin
  523. DecodeDate(aDate,y,m,d);
  524. Result := EncodeDateTime(y,m,d,aHour,aMinute,aSecond,aMilliSecond);
  525. end;
  526. function ChangeDateOfADay(aDate : TDateTime; aYear, aMonth, aDay : Word) : TDateTime;
  527. var
  528. h, m, s, ms : Word;
  529. begin
  530. DecodeTime(aDate,h,m,s,ms);
  531. Result := EncodeDateTime(aYear,aMonth,aDay,h,m,s,0);
  532. end;
  533. function FillStr(const C : Char; const Count : Byte) : string;
  534. var
  535. i : Byte;
  536. begin
  537. Result := '';
  538. for i := 1 to Count do Result := Result + C;
  539. end;
  540. function StrInArray(const aValue : string; const aInArray : array of string) : Boolean;
  541. var
  542. s : string;
  543. begin
  544. for s in aInArray do
  545. begin
  546. if s = aValue then Exit(True);
  547. end;
  548. Result := False;
  549. end;
  550. function IntInArray(const aValue : Integer; const aInArray : array of Integer) : Boolean;
  551. var
  552. i : Integer;
  553. begin
  554. for i in aInArray do
  555. begin
  556. if i = aValue then Exit(True);
  557. end;
  558. Result := False;
  559. end;
  560. function Zeroes(const Number, Len : Int64) : string;
  561. begin
  562. if Len > Length(IntToStr(Number)) then Result := FillStr('0',Len - Length(IntToStr(Number))) + IntToStr(Number)
  563. else Result := IntToStr(Number);
  564. end;
  565. function NumberToStr(const Number : Int64) : string;
  566. begin
  567. try
  568. Result := FormatFloat('0,',Number);
  569. except
  570. Result := '#Error';
  571. end;
  572. end;
  573. function Spaces(const Count : Integer) : string;
  574. begin
  575. Result := FillStr(' ',Count);
  576. end;
  577. function NowStr : string;
  578. begin
  579. Result := DateTimeToStr(Now());
  580. end;
  581. function NewGuidStr : string;
  582. var
  583. guid : TGUID;
  584. begin
  585. guid.NewGuid;
  586. Result := guid.ToString
  587. //GUIDToString(guid);
  588. end;
  589. function IsLike(cText, Pattern: string) : Boolean;
  590. var
  591. i, n : Integer;
  592. match : Boolean;
  593. wildcard : Boolean;
  594. CurrentPattern : Char;
  595. begin
  596. Result := False;
  597. wildcard := False;
  598. cText := LowerCase(cText);
  599. Pattern := LowerCase(Pattern);
  600. match := False;
  601. if (Pattern.Length > cText.Length) or (Pattern = '') then Exit;
  602. if Pattern = '*' then
  603. begin
  604. Result := True;
  605. Exit;
  606. end;
  607. for i := 1 to cText.Length do
  608. begin
  609. CurrentPattern := Pattern[i];
  610. if CurrentPattern = '*' then wildcard := True;
  611. if wildcard then
  612. begin
  613. n := Pos(Copy(Pattern,i+1,Pattern.Length),cText);
  614. if (n > i) or (Pattern.Length = i) then
  615. begin
  616. Result := True;
  617. Exit;
  618. end;
  619. end
  620. else
  621. begin
  622. if (cText[i] = CurrentPattern) or (CurrentPattern = '?') then match := True
  623. else match := False;
  624. end;
  625. end;
  626. Result := match;
  627. end;
  628. function Capitalize(s: string): string;
  629. begin
  630. Result := '';
  631. if s.Length = 0 then Exit;
  632. s := LowerCase(s,loUserLocale);
  633. Result := UpperCase(s[1],loUserLocale) + Trim(Copy(s, 2, s.Length));
  634. end;
  635. function CapitalizeWords(s: string): string;
  636. var
  637. cword : string;
  638. begin
  639. Result := '';
  640. if s.Length = 0 then Exit;
  641. s := LowerCase(s,loUserLocale);
  642. for cword in s.Split([' ']) do
  643. begin
  644. if Result = '' then Result := Capitalize(cword)
  645. else Result := Result + ' ' + Capitalize(cword);
  646. end;
  647. end;
  648. function GetLoggedUserName : string;
  649. {$IFDEF MSWINDOWS}
  650. const
  651. cnMaxUserNameLen = 254;
  652. var
  653. sUserName : string;
  654. dwUserNameLen : DWord;
  655. begin
  656. dwUserNameLen := cnMaxUserNameLen-1;
  657. SetLength( sUserName, cnMaxUserNameLen );
  658. GetUserName(PChar( sUserName ),dwUserNameLen );
  659. SetLength( sUserName, dwUserNameLen );
  660. Result := sUserName;
  661. end;
  662. {$ELSE}
  663. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  664. begin
  665. Result := GetEnvironmentVariable('USERNAME');
  666. end;
  667. {$ELSE}
  668. begin
  669. {$IFDEF POSIX}
  670. Result := string(getlogin);
  671. {$ELSE}
  672. Result := 'N/A';
  673. {$ENDIF}
  674. //raise ENotImplemented.Create('Not Android GetLoggedUserName implemented!');
  675. end;
  676. {$ENDIF}
  677. {$ENDIF}
  678. {$IFDEF IOS}
  679. function GetDeviceModel : String;
  680. var
  681. size : size_t;
  682. buffer : array of Byte;
  683. begin
  684. sysctlbyname('hw.machine',nil,@size,nil,0);
  685. if size > 0 then
  686. begin
  687. SetLength(buffer, size);
  688. sysctlbyname('hw.machine',@buffer[0],@size,nil,0);
  689. Result := UTF8ToString(MarshaledAString(buffer));
  690. end
  691. else Result := EmptyStr;
  692. end;
  693. {$ENDIF}
  694. function GetComputerName : string;
  695. {$IFDEF MSWINDOWS}
  696. var
  697. dwLength: dword;
  698. begin
  699. dwLength := 253;
  700. SetLength(Result, dwLength+1);
  701. if not Windows.GetComputerName(pchar(result), dwLength) then Result := 'Not detected!';
  702. Result := pchar(result);
  703. end;
  704. {$ELSE}
  705. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  706. begin
  707. Result := GetEnvironmentVariable('COMPUTERNAME');
  708. end;
  709. {$ELSE} //Android gets model name
  710. {$IFDEF NEXTGEN}
  711. begin
  712. {$IFDEF ANDROID}
  713. Result := JStringToString(TJBuild.JavaClass.MODEL);
  714. {$ELSE} //IOS
  715. Result := GetDeviceModel;
  716. {$ENDIF}
  717. end;
  718. {$ELSE}
  719. {$IFDEF DELPHILINUX}
  720. var
  721. puser : PAnsiChar;
  722. begin
  723. //puser := '';
  724. try
  725. if gethostname(puser,_SC_HOST_NAME_MAX) = 0 then Result := string(puser)
  726. else Result := 'N/A';
  727. except
  728. Result := 'N/A';
  729. end;
  730. end;
  731. {$ELSE} //OSX
  732. begin
  733. Result := NSStrToStr(TNSHost.Wrap(TNSHost.OCClass.currentHost).localizedName);
  734. end;
  735. {$ENDIF}
  736. {$ENDIF}
  737. {$ENDIF}
  738. {$ENDIF}
  739. function NormalizePathDelim(const cPath : string; const Delim : Char) : string;
  740. begin
  741. if Delim = '\' then Result := StringReplace(cPath,'/',Delim,[rfReplaceAll])
  742. else Result := StringReplace(cPath,'\',Delim,[rfReplaceAll]);
  743. end;
  744. function RemoveLastPathSegment(cDir : string) : string;
  745. var
  746. posi : Integer;
  747. delim : Char;
  748. EndsWithDelim : Boolean;
  749. begin
  750. if cDir.Contains('\') then delim := '\'
  751. else if cDir.Contains('/') then delim := '/'
  752. else
  753. begin
  754. Result := '';
  755. Exit;
  756. end;
  757. NormalizePathDelim(cDir,delim);
  758. if cDir.EndsWith(delim) then
  759. begin
  760. cDir := Copy(cDir,1,cDir.Length-1);
  761. EndsWithDelim := True;
  762. end
  763. else EndsWithDelim := False;
  764. if cDir.CountChar(delim) > 1 then posi := cDir.LastDelimiter(delim)
  765. else posi := Pos(delim,cDir)-1;
  766. if posi = cDir.Length then posi := 0;
  767. Result := Copy(cDir,1,posi);
  768. if (Result <> '') and (EndsWithDelim) then Result := Result + delim;
  769. end;
  770. function ParamFindSwitch(const Switch : string) : Boolean;
  771. begin
  772. Result := FindCmdLineSwitch(Switch,['-', '/'],True);
  773. end;
  774. {$IFDEF FPC}
  775. function FindCmdLineSwitch(const Switch: string; var Value: string; IgnoreCase: Boolean = True;
  776. const SwitchTypes: TCmdLineSwitchTypes = [clstValueNextParam, clstValueAppended]): Boolean; overload;
  777. type
  778. TCompareProc = function(const S1, S2: string): Boolean;
  779. var
  780. Param: string;
  781. I, ValueOfs,
  782. SwitchLen, ParamLen: Integer;
  783. SameSwitch: TCompareProc;
  784. begin
  785. Result := False;
  786. Value := '';
  787. if IgnoreCase then
  788. SameSwitch := SameText else
  789. SameSwitch := SameStr;
  790. SwitchLen := Switch.Length;
  791. for I := 1 to ParamCount do
  792. begin
  793. Param := ParamStr(I);
  794. if CharInSet(Param.Chars[0], SwitchChars) and SameSwitch(Param.SubString(1,SwitchLen), Switch) then
  795. begin
  796. ParamLen := Param.Length;
  797. // Look for an appended value if the param is longer than the switch
  798. if (ParamLen > SwitchLen + 1) then
  799. begin
  800. // If not looking for appended value switches then this is not a matching switch
  801. if not (clstValueAppended in SwitchTypes) then
  802. Continue;
  803. ValueOfs := SwitchLen + 1;
  804. if Param.Chars[ValueOfs] = ':' then
  805. Inc(ValueOfs);
  806. Value := Param.SubString(ValueOfs, MaxInt);
  807. end
  808. // If the next param is not a switch, then treat it as the value
  809. else if (clstValueNextParam in SwitchTypes) and (I < ParamCount) and
  810. not CharInSet(ParamStr(I+1).Chars[0], SwitchChars) then
  811. Value := ParamStr(I+1);
  812. Result := True;
  813. Break;
  814. end;
  815. end;
  816. end;
  817. {$ENDIF}
  818. function ParamGetSwitch(const Switch : string; var cvalue : string) : Boolean;
  819. begin
  820. Result := FindCmdLineSwitch(Switch,cvalue,True,[clstValueAppended]);
  821. end;
  822. function GetAppName : string;
  823. begin
  824. Result := ExtractFilenameWithoutExt(ParamStr(0));
  825. end;
  826. function GetAppVersionStr: string;
  827. {$IFDEF MSWINDOWS}
  828. var
  829. Rec: LongRec;
  830. ver : Cardinal;
  831. begin
  832. ver := GetFileVersion(ParamStr(0));
  833. if ver <> Cardinal(-1) then
  834. begin
  835. Rec := LongRec(ver);
  836. Result := Format('%d.%d', [Rec.Hi, Rec.Lo]);
  837. end
  838. else Result := '';
  839. end;
  840. {$ELSE}
  841. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  842. var
  843. version : TProgramVersion;
  844. begin
  845. if GetProgramVersion(version) then Result := Format('%d.%d', [version.Major, version.Minor])
  846. else Result := '';
  847. end;
  848. {$ELSE}
  849. {$IFDEF NEXTGEN}
  850. {$IFDEF ANDROID}
  851. var
  852. PkgInfo : JPackageInfo;
  853. begin
  854. PkgInfo := SharedActivity.getPackageManager.getPackageInfo(SharedActivity.getPackageName,0);
  855. Result := IntToStr(PkgInfo.VersionCode);
  856. end;
  857. {$ELSE} //IOS
  858. var
  859. AppKey: Pointer;
  860. AppBundle: NSBundle;
  861. BuildStr : NSString;
  862. begin
  863. try
  864. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  865. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  866. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  867. Result := UTF8ToString(BuildStr.UTF8String);
  868. except
  869. Result := 'N/A';
  870. end;
  871. end;
  872. {$ENDIF}
  873. {$ELSE} //OSX
  874. {$IFDEF OSX}
  875. var
  876. AppKey: Pointer;
  877. AppBundle: NSBundle;
  878. BuildStr : NSString;
  879. begin
  880. try
  881. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  882. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  883. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  884. Result := UTF8ToString(BuildStr.UTF8String);
  885. except
  886. Result := '';
  887. end;
  888. end;
  889. {$ELSE}
  890. begin
  891. Result := '';
  892. end;
  893. {$ENDIF}
  894. {$ENDIF}
  895. {$ENDIF}
  896. {$ENDIF}
  897. function GetAppVersionFullStr: string;
  898. {$IFDEF MSWINDOWS}
  899. var
  900. Exe: string;
  901. Size, Handle: DWORD;
  902. Buffer: TBytes;
  903. FixedPtr: PVSFixedFileInfo;
  904. begin
  905. Result := '';
  906. Exe := ParamStr(0);
  907. Size := GetFileVersionInfoSize(PChar(Exe), Handle);
  908. if Size = 0 then
  909. begin
  910. //RaiseLastOSError;
  911. //no version info in file
  912. Exit;
  913. end;
  914. SetLength(Buffer, Size);
  915. if not GetFileVersionInfo(PChar(Exe), Handle, Size, Buffer) then
  916. RaiseLastOSError;
  917. if not VerQueryValue(Buffer, '\', Pointer(FixedPtr), Size) then
  918. RaiseLastOSError;
  919. if (LongRec(FixedPtr.dwFileVersionLS).Hi = 0) and (LongRec(FixedPtr.dwFileVersionLS).Lo = 0) then
  920. begin
  921. Result := Format('%d.%d',
  922. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  923. LongRec(FixedPtr.dwFileVersionMS).Lo]); //minor
  924. end
  925. else if (LongRec(FixedPtr.dwFileVersionLS).Lo = 0) then
  926. begin
  927. Result := Format('%d.%d.%d',
  928. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  929. LongRec(FixedPtr.dwFileVersionMS).Lo, //minor
  930. LongRec(FixedPtr.dwFileVersionLS).Hi]); //release
  931. end
  932. else
  933. begin
  934. Result := Format('%d.%d.%d.%d',
  935. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  936. LongRec(FixedPtr.dwFileVersionMS).Lo, //minor
  937. LongRec(FixedPtr.dwFileVersionLS).Hi, //release
  938. LongRec(FixedPtr.dwFileVersionLS).Lo]); //build
  939. end;
  940. end;
  941. {$ELSE}
  942. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  943. var
  944. version : TProgramVersion;
  945. begin
  946. if GetProgramVersion(version) then Result := Format('%d.%d.%d.%d', [version.Major, version.Minor, version.Revision, version.Build])
  947. else Result := '';
  948. end;
  949. {$ELSE}
  950. {$IFDEF NEXTGEN}
  951. {$IFDEF ANDROID}
  952. var
  953. PkgInfo : JPackageInfo;
  954. begin
  955. PkgInfo := SharedActivity.getPackageManager.getPackageInfo(SharedActivity.getPackageName,0);
  956. Result := JStringToString(PkgInfo.versionName);
  957. end;
  958. {$ELSE} //IOS
  959. var
  960. AppKey: Pointer;
  961. AppBundle: NSBundle;
  962. BuildStr : NSString;
  963. begin
  964. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  965. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  966. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  967. Result := UTF8ToString(BuildStr.UTF8String);
  968. end;
  969. {$ENDIF}
  970. {$ELSE}
  971. {$IFDEF OSX}
  972. var
  973. AppKey: Pointer;
  974. AppBundle: NSBundle;
  975. BuildStr : NSString;
  976. begin
  977. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  978. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  979. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  980. Result := UTF8ToString(BuildStr.UTF8String);
  981. end;
  982. {$ELSE}
  983. begin
  984. Result := 'N/A';
  985. end;
  986. {$ENDIF}
  987. {$ENDIF}
  988. {$ENDIF}
  989. {$ENDIF}
  990. function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
  991. begin
  992. {$IFDEF FPC}
  993. Result := LocalTimeToUniversal(GMTTime);
  994. {$ELSE}
  995. Result := TTimeZone.Local.ToLocalTime(GMTTime);
  996. {$ENDIF}
  997. end;
  998. function LocalTimeToUTC(LocalTime : TDateTime): TDateTime;
  999. begin
  1000. {$IFDEF FPC}
  1001. Result := UniversalTimeToLocal(Localtime);
  1002. {$ELSE}
  1003. Result := TTimeZone.Local.ToUniversalTime(LocalTime);
  1004. {$ENDIF}
  1005. end;
  1006. function DateTimeToGMT(aDate : TDateTime) : string;
  1007. var
  1008. FmtSettings : TFormatSettings;
  1009. begin
  1010. FmtSettings.DateSeparator := '-';
  1011. FmtSettings.TimeSeparator := ':';
  1012. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ" GMT"';
  1013. Result := DateTimeToStr(aDate,FmtSettings);
  1014. end;
  1015. function GMTToDateTime(aDate : string) : TDateTime;
  1016. var
  1017. FmtSettings : TFormatSettings;
  1018. begin
  1019. FmtSettings.DateSeparator := '-';
  1020. FmtSettings.TimeSeparator := ':';
  1021. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ" GMT"';
  1022. Result := StrToDateTime(aDate,FmtSettings);
  1023. end;
  1024. function DateTimeToJsonDate(aDateTime : TDateTime) : string;
  1025. {$IFNDEF DELPHIXE7_UP}
  1026. var
  1027. FmtSettings : TFormatSettings;
  1028. {$ENDIF}
  1029. begin
  1030. {$IFDEF DELPHIXE7_UP}
  1031. Result := DateToISO8601(aDateTime);
  1032. {$ELSE}
  1033. FmtSettings.DateSeparator := '-';
  1034. FmtSettings.TimeSeparator := ':';
  1035. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ"Z"';
  1036. Result := DateTimeToStr(aDateTime,FmtSettings).Trim;
  1037. {$ENDIF}
  1038. end;
  1039. function JsonDateToDateTime(const aJsonDate : string) : TDateTime;
  1040. {$IFNDEF DELPHIXE7_UP}
  1041. var
  1042. FmtSettings : TFormatSettings;
  1043. {$ENDIF}
  1044. {$IFDEF FPC}
  1045. var
  1046. jdate : string;
  1047. {$ENDIF}
  1048. begin
  1049. {$IFDEF DELPHIXE7_UP}
  1050. Result := ISO8601ToDate(aJsonDate);
  1051. {$ELSE}
  1052. FmtSettings.DateSeparator := '-';
  1053. FmtSettings.TimeSeparator := ':';
  1054. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ"Z"';
  1055. {$IFDEF FPC}
  1056. jdate := StringReplace(aJsondate,'T',' ',[rfIgnoreCase]);
  1057. jdate := Copy(jdate,1,Pos('.',jdate)-1);
  1058. Result := StrToDateTime(jdate,FmtSettings);
  1059. {$ELSE}
  1060. Result := StrToDateTime(aJsonDate,FmtSettings);
  1061. {$ENDIF}
  1062. {$ENDIF}
  1063. end;
  1064. function CountDigits(anInt: Cardinal): Cardinal; inline;
  1065. var
  1066. cmp: Cardinal;
  1067. begin
  1068. cmp := 10;
  1069. Result := 1;
  1070. while (Result < 10) and (cmp <= anInt) do
  1071. begin
  1072. cmp := cmp*10;
  1073. Inc(Result);
  1074. end;
  1075. end;
  1076. procedure SaveStreamToFile(stream : TStream; const filename : string);
  1077. var
  1078. fs : TFileStream;
  1079. begin
  1080. fs := TFileStream.Create(filename,fmCreate);
  1081. try
  1082. stream.Seek(0,soBeginning);
  1083. fs.CopyFrom(stream,stream.Size);
  1084. finally
  1085. fs.Free;
  1086. end;
  1087. end;
  1088. function CommaText(aList : TStringList) : string;
  1089. var
  1090. value : string;
  1091. sb : TStringBuilder;
  1092. begin
  1093. if aList.Text = '' then Exit;
  1094. sb := TStringBuilder.Create;
  1095. try
  1096. for value in aList do
  1097. begin
  1098. sb.Append(value);
  1099. sb.Append(',');
  1100. end;
  1101. if sb.Length > 1 then Result := sb.ToString(0, sb.Length - 1);
  1102. finally
  1103. sb.Free;
  1104. end;
  1105. end;
  1106. { TCounter }
  1107. procedure TCounter.Init(aMaxValue : Integer);
  1108. begin
  1109. fMaxValue := aMaxValue;
  1110. fCurrentValue := 0;
  1111. end;
  1112. function TCounter.Count : Integer;
  1113. begin
  1114. Result := fCurrentValue;
  1115. end;
  1116. function TCounter.CountIs(aValue : Integer) : Boolean;
  1117. begin
  1118. Result := fCurrentValue = aValue;
  1119. end;
  1120. function TCounter.Check : Boolean;
  1121. begin
  1122. if fCurrentValue = fMaxValue then
  1123. begin
  1124. Result := True;
  1125. Reset;
  1126. end
  1127. else
  1128. begin
  1129. Result := False;
  1130. Inc(fCurrentValue);
  1131. end;
  1132. end;
  1133. procedure TCounter.Reset;
  1134. begin
  1135. fCurrentValue := fMaxValue;
  1136. end;
  1137. { TimeCounter }
  1138. procedure TTimeCounter.Init(MillisecondsToReach : Integer);
  1139. begin
  1140. fDoneEvery := MillisecondsToReach;
  1141. end;
  1142. function TTimeCounter.Check : Boolean;
  1143. begin
  1144. if MilliSecondsBetween(fCurrentTime,Now) > fDoneEvery then
  1145. begin
  1146. fCurrentTime := Now();
  1147. Result := True;
  1148. end
  1149. else Result := False;
  1150. end;
  1151. procedure TTimeCounter.Reset;
  1152. begin
  1153. fCurrentTime := Now();
  1154. end;
  1155. {$IFDEF MSWINDOWS}
  1156. procedure ProcessMessages;
  1157. var
  1158. Msg: TMsg;
  1159. begin
  1160. while integer(PeekMessage(Msg, 0, 0, 0, PM_REMOVE)) <> 0 do
  1161. begin
  1162. TranslateMessage(Msg);
  1163. DispatchMessage(Msg);
  1164. end;
  1165. end;
  1166. function GetLastOSError: String;
  1167. begin
  1168. Result := SysErrorMessage(Windows.GetLastError);
  1169. end;
  1170. {$ENDIF}
  1171. function RemoveLastChar(const aText : string) : string;
  1172. begin
  1173. Result := aText.Remove(aText.Length - 1);
  1174. end;
  1175. function DateTimeToSQL(aDateTime : TDateTime) : string;
  1176. begin
  1177. Result := FormatDateTime('YYYYMMDD hh:mm:ss',aDateTime);
  1178. end;
  1179. function IsInteger(const aValue : string) : Boolean;
  1180. var
  1181. i : Integer;
  1182. begin
  1183. Result := TryStrToInt(aValue,i);
  1184. end;
  1185. {$IFDEF MSWINDOWS}
  1186. initialization
  1187. try
  1188. GetEnvironmentPaths;
  1189. except
  1190. on E : Exception do
  1191. begin
  1192. if not IsService then
  1193. begin
  1194. if IsConsole then Writeln(Format('[WARN] GetEnvironmentPaths: %s',[E.Message]))
  1195. else raise EEnvironmentPath.Create(Format('Get environment path error: %s',[E.Message]));
  1196. end;
  1197. end;
  1198. end;
  1199. {$ENDIF}
  1200. end.