浏览代码

fpc compatibility

Unknown 7 年之前
父节点
当前提交
3f2e0fbdd3
共有 100 个文件被更改,包括 4847 次插入192 次删除
  1. 2 2
      Quick.Amazon.pas
  2. 16 2
      Quick.AppService.pas
  3. 4 2
      Quick.Base64.pas
  4. 18 2
      Quick.Chrono.pas
  5. 112 17
      Quick.Commons.pas
  6. 55 12
      Quick.Config.Provider.Json.pas
  7. 32 9
      Quick.Config.Provider.Registry.pas
  8. 73 24
      Quick.Config.pas
  9. 35 6
      Quick.Console.pas
  10. 10 4
      Quick.FileMonitor.pas
  11. 711 23
      Quick.Files.pas
  12. 5 3
      Quick.Format.pas
  13. 3 3
      Quick.JSONUtils.pas
  14. 24 11
      Quick.Log.pas
  15. 4 3
      Quick.Network.pas
  16. 48 9
      Quick.Process.pas
  17. 3 1
      Quick.SMTP.pas
  18. 21 7
      Quick.Service.pas
  19. 150 15
      Quick.Threads.pas
  20. 142 0
      QuickLib.inc
  21. 1 2
      README.md
  22. 103 0
      quicklib.lpk
  23. 18 0
      quicklib.pas
  24. 0 1
      samples/QuickConfig/Win32/Debug/prueba.json
  25. 80 0
      samples/delphi/QuickAppService/ConsoleAndService/MyServiceConsole.dpr
  26. 589 0
      samples/delphi/QuickAppService/ConsoleAndService/MyServiceConsole.dproj
  27. 二进制
      samples/delphi/QuickAppService/ConsoleAndService/MyServiceConsole.res
  28. 0 0
      samples/delphi/QuickChrono/ChronoDemo.dpr
  29. 0 0
      samples/delphi/QuickChrono/ChronoDemo.dproj
  30. 二进制
      samples/delphi/QuickChrono/ChronoDemo.ico
  31. 二进制
      samples/delphi/QuickChrono/ChronoDemo.res
  32. 0 0
      samples/delphi/QuickChrono/Main.dfm
  33. 0 0
      samples/delphi/QuickChrono/Main.pas
  34. 0 0
      samples/delphi/QuickConfig/ConfigToFileAndRegistry/Main.dfm
  35. 0 0
      samples/delphi/QuickConfig/ConfigToFileAndRegistry/Main.pas
  36. 0 0
      samples/delphi/QuickConfig/ConfigToFileAndRegistry/QuickConfigDemo.dpr
  37. 0 0
      samples/delphi/QuickConfig/ConfigToFileAndRegistry/QuickConfigDemo.dproj
  38. 0 0
      samples/delphi/QuickConfig/ConfigToFileAndRegistry/QuickConfigDemo.res
  39. 0 0
      samples/delphi/QuickConfig/ConfigToFileAndRegistry/Win64/Debug/Config.json
  40. 23 12
      samples/delphi/QuickConsole/ConsoleMenu/QuickConsoleMenu.dpr
  41. 0 0
      samples/delphi/QuickConsole/ConsoleMenu/QuickConsoleMenu.dproj
  42. 0 0
      samples/delphi/QuickConsole/ConsoleMenu/QuickConsoleMenu.res
  43. 32 0
      samples/delphi/QuickConsole/ConsoleOut/ConsoleOut.dpr
  44. 4 4
      samples/delphi/QuickConsole/ConsoleOut/ConsoleOut.dproj
  45. 0 0
      samples/delphi/QuickConsole/ConsoleOut/ConsoleOut.res
  46. 2 2
      samples/delphi/QuickNetwork/GetIPRange/GetIPRanges.dpr
  47. 6 6
      samples/delphi/QuickNetwork/GetIPRange/GetIPRanges.dproj
  48. 0 0
      samples/delphi/QuickNetwork/GetIPRange/GetIPRanges.res
  49. 2 3
      samples/delphi/QuickService/ServiceManagement/ServiceManagement.dpr
  50. 5 5
      samples/delphi/QuickService/ServiceManagement/ServiceManagement.dproj
  51. 0 0
      samples/delphi/QuickService/ServiceManagement/ServiceManagement.res
  52. 62 0
      samples/fpc/QuickAppService/ConsoleAndService/MyServiceConsole.lpi
  53. 66 0
      samples/fpc/QuickAppService/ConsoleAndService/MyServiceConsole.lpr
  54. 22 0
      samples/fpc/QuickAppService/ConsoleAndService/MyServiceConsole.lps
  55. 二进制
      samples/fpc/QuickAppService/ConsoleAndService/MyServiceConsole.res
  56. 62 0
      samples/fpc/QuickAppService/ConsoleAndService/backup/MyServiceConsole.lpi
  57. 22 0
      samples/fpc/QuickAppService/ConsoleAndService/backup/MyServiceConsole.lps
  58. 80 0
      samples/fpc/QuickAppService/ConsoleAndService/backup/MyServiceConsole.pas
  59. 88 0
      samples/fpc/QuickAppService/ConsoleAndService/backup/QuickAppServiceSample.lps
  60. 二进制
      samples/fpc/QuickAppService/ConsoleAndService/lib/i386-win32/MyServiceConsole.or
  61. 二进制
      samples/fpc/QuickAppService/ConsoleAndService/lib/i386-win32/MyServiceConsole.res
  62. 二进制
      samples/fpc/QuickAppService/ConsoleAndService/lib/i386-win32/QuickAppServiceSample.or
  63. 二进制
      samples/fpc/QuickAppService/ConsoleAndService/lib/i386-win32/QuickAppServiceSample.res
  64. 二进制
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/QuickConfig.ico
  65. 85 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/QuickConfig.lpi
  66. 20 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/QuickConfig.lpr
  67. 117 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/QuickConfig.lps
  68. 13 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/QuickConfig.pas
  69. 二进制
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/QuickConfig.res
  70. 64 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/Main.dfm
  71. 225 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/Main.pas
  72. 85 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/QuickConfig.lpi
  73. 141 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/QuickConfig.lps
  74. 14 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/QuickConfigDemo.dpr
  75. 85 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/QuickConfigDemo.lpi
  76. 248 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/QuickConfigDemo.lps
  77. 39 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/umain.lfm
  78. 186 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/umain.pas
  79. 二进制
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/lib/i386-win32/QuickConfig.or
  80. 二进制
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/lib/i386-win32/QuickConfig.res
  81. 二进制
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/lib/i386-win32/QuickConfigDemo.or
  82. 二进制
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/lib/i386-win32/QuickConfigDemo.res
  83. 39 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/lib/i386-win32/umain.lfm
  84. 39 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/umain.lfm
  85. 186 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/umain.pas
  86. 62 0
      samples/fpc/QuickConsole/ConsoleMenu/ConsoleMenu.lpi
  87. 37 0
      samples/fpc/QuickConsole/ConsoleMenu/ConsoleMenu.lps
  88. 79 0
      samples/fpc/QuickConsole/ConsoleMenu/ConsoleMenu.pas
  89. 二进制
      samples/fpc/QuickConsole/ConsoleMenu/ConsoleMenu.res
  90. 62 0
      samples/fpc/QuickConsole/ConsoleMenu/backup/ConsoleMenu.lpi
  91. 38 0
      samples/fpc/QuickConsole/ConsoleMenu/backup/ConsoleMenu.lps
  92. 85 0
      samples/fpc/QuickConsole/ConsoleMenu/backup/ConsoleMenu.pas
  93. 二进制
      samples/fpc/QuickConsole/ConsoleMenu/lib/i386-win32/ConsoleMenu.or
  94. 二进制
      samples/fpc/QuickConsole/ConsoleMenu/lib/i386-win32/ConsoleMenu.res
  95. 62 0
      samples/fpc/QuickConsole/ConsoleOut/ConsoleOut.lpi
  96. 30 0
      samples/fpc/QuickConsole/ConsoleOut/ConsoleOut.lps
  97. 4 2
      samples/fpc/QuickConsole/ConsoleOut/ConsoleOut.pas
  98. 二进制
      samples/fpc/QuickConsole/ConsoleOut/ConsoleOut.res
  99. 35 0
      samples/fpc/QuickConsole/ConsoleOut/backup/ConsoleOut.lps
  100. 32 0
      samples/fpc/QuickConsole/ConsoleOut/backup/ConsoleOut.pas

+ 2 - 2
Quick.Amazon.pas

@@ -33,8 +33,8 @@ interface
 
 uses
   Classes,
-  SysUtils,
-  Generics.Collections,
+  System.SysUtils,
+  System.Generics.Collections,
   IPPeerClient,
   Data.Cloud.CloudAPI,
   Data.Cloud.AmazonAPI;

+ 16 - 2
Quick.AppService.pas

@@ -29,17 +29,23 @@
 
 unit Quick.AppService;
 
+{$i QuickLib.inc}
+
 interface
 
-{$IF CompilerVersion > 20}
+{$IFNDEF FPC}
+{$IFDEF DELPHI2010_UP}
   {$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
   {$WEAKLINKRTTI ON}
 {$ENDIF}
+{$ENDIF}
 
 uses
   Windows,
-  System.SysUtils,
+  SysUtils,
+  {$IFNDEF FPC}
   WinSvc,
+  {$ENDIF}
   Quick.Commons;
 
 const
@@ -56,7 +62,11 @@ type
                 ssPaused = SERVICE_PAUSED);
 
   TSvcInitializeEvent = procedure of object;
+  {$IFDEF FPC}
+  TSvcAnonMethod = procedure of object;
+  {$ELSE}
   TSvcAnonMethod = reference to procedure;
+  {$ENDIF}
   TSvcRemoveEvent = procedure of object;
 
   TAppService = class
@@ -348,7 +358,11 @@ begin
     ServiceTable[0].lpServiceProc := @RegisterService;
     ServiceTable[1].lpServiceName := nil;
     ServiceTable[1].lpServiceProc := nil;
+    {$IFDEF FPC}
+    StartServiceCtrlDispatcher(@ServiceTable[0]);
+    {$ELSE}
     StartServiceCtrlDispatcher(ServiceTable[0]);
+    {$ENDIF}
   end;
 end;
 

+ 4 - 2
Quick.Base64.pas

@@ -5,9 +5,9 @@
   Unit        : Quick.Base64
   Description : Log Api Redis Provider
   Author      : Kike Pérez
-  Version     : 1.0
+  Version     : 1.1
   Created     : 08/11/2017
-  Modified    : 08/11/2017
+  Modified    : 07/05/2018
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -30,6 +30,8 @@ unit Quick.Base64;
 
 interface
 
+{$i QuickLib.inc}
+
 uses
   IdCoderMIME,
   IdGlobal;

+ 18 - 2
Quick.Chrono.pas

@@ -5,9 +5,9 @@
   Unit        : Quick.Chrono
   Description : Chronometers time elapsed and estimated time to do a task
   Author      : Kike Pérez
-  Version     : 1.2
+  Version     : 1.4
   Created     : 27/08/2015
-  Modified    : 20/03/2018
+  Modified    : 07/04/2018
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -31,8 +31,16 @@ unit Quick.Chrono;
 
 interface
 
+{$i QuickLib.inc}
+
 uses
+  {$IF defined(MSWINDOWS)}
   Windows,
+  {$ELSEIF defined(MACOS)}
+  Macapi.Mach,
+  {$ELSEIF defined(POSIX)}
+  Posix.Time,
+  {$ENDIF}
   SysUtils,
   DateUtils;
 
@@ -52,6 +60,10 @@ resourcestring
 
 type
 
+  {$IFDEF ANDROID}
+  TLargeInteger = Int64;
+  {$ENDIF}
+
   TTimeValue = (utDay, utHour, utMinute, utSecond, utMillisecond,utMicrosecond,utNanosecond);
   TTimeFmt = (tfHoursAndMinutes, tfMinutesAndSeconds);
   TPrecissionFormat = (pfFloat, pfRound, pfTruncate);
@@ -62,6 +74,10 @@ const
   FmtShortTime : array[tfHoursAndMinutes..tfMinutesAndSeconds] of string = (strFMTSHORT_HOURS_MINUTES,strFMTSHORT_MINUTES_SECONDS);
   FmtLongTime : array[tfHoursAndMinutes..tfMinutesAndSeconds] of string = (strFMTLONG_HOURS_MINUTES,strFMTLONG_MINUTES_SECONDS);
 
+  {$IFDEF FPC}
+  SecsPerHour = 3600;
+  {$ENDIF}
+
 type
 
   TChronometer = class

+ 112 - 17
Quick.Commons.pas

@@ -29,18 +29,25 @@
 
 unit Quick.Commons;
 
+{$i QuickLib.inc}
+
 interface
+
   uses
     Classes,
-    System.SysUtils,
-    System.Types,
+    SysUtils,
+    Types,
     {$IFDEF MSWINDOWS}
       Windows,
-      Winapi.ShlObj,
-      System.Win.Registry,
+      ShlObj,
+      Registry,
     {$ENDIF MSWINDOWS}
-    System.IOUtils,
-    System.DateUtils;
+    {$IFDEF FPC}
+    Quick.Files,
+    {$ELSE}
+    IOUtils,
+    {$ENDIF}
+    DateUtils;
 
 type
 
@@ -53,7 +60,7 @@ const
   LOG_TRACE = [etInfo,etError,etWarning,etTrace];
   LOG_ALL = [etInfo,etSuccess,etWarning,etError,etTrace];
   LOG_DEBUG = [etInfo,etSuccess,etWarning,etError,etDebug];
-  {$IF CompilerVersion > 27}
+  {$IFDEF DELPHIXE7_UP}
   EventStr : array of string = ['INFO','SUCC','WARN','ERROR','DEBUG','TRACE'];
   {$ELSE}
   EventStr : array[0..5] of string = ('INFO','SUCC','WARN','ERROR','DEBUG','TRACE');
@@ -83,6 +90,7 @@ type
   end;
   {$ENDIF MSWINDOWS}
 
+  {$IFNDEF FPC}
   TFileHelper = record helper for TFile
     {$IFDEF MSWINDOWS}
     class function IsInUse(const FileName : string) : Boolean; static;
@@ -93,6 +101,21 @@ type
   TDirectoryHelper = record helper for TDirectory
     class function GetSize(const Path: String): Int64; static;
   end;
+  {$ENDIF}
+
+  {$IFDEF FPC}
+  PLASTINPUTINFO = ^LASTINPUTINFO;
+  tagLASTINPUTINFO = record
+    cbSize: UINT;
+    dwTime: DWORD;
+  end;
+  LASTINPUTINFO = tagLASTINPUTINFO;
+  TLastInputInfo = LASTINPUTINFO;
+
+  type
+  TCmdLineSwitchType = (clstValueNextParam, clstValueAppended);
+  TCmdLineSwitchTypes = set of TCmdLineSwitchType;
+  {$ENDIF}
 
   TCounter = record
   private
@@ -152,6 +175,9 @@ type
   {$ENDIF MSWINDOWS}
   //returns last day of current month
   function LastDayCurrentMonth: TDateTime;
+  {$IFDEF FPC}
+  function DateTimeInRange(ADateTime: TDateTime; AStartDateTime, AEndDateTime: TDateTime; aInclusive: Boolean = True): Boolean;
+  {$ENDIF}
   //checks if two datetimes are in same day
   function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
   //returns n times a char
@@ -205,6 +231,9 @@ type
   //get last error message
   function GetLastOSError : String;
   {$ENDIF}
+  {$IFDEF FPC}
+  function GetLastInputInfo(var plii: TLastInputInfo): BOOL;stdcall; external 'user32' name 'GetLastInputInfo';
+  {$ENDIF}
 
 {$IFDEF MSWINDOWS}
 var
@@ -215,6 +244,7 @@ implementation
 
 {TFileHelper}
 
+{$IFNDEF FPC}
 {$IFDEF MSWINDOWS}
 class function TFileHelper.IsInUse(const FileName : string) : Boolean;
 var
@@ -273,6 +303,7 @@ begin
     Result := Result + TFile.GetSize(filename);
   end;
 end;
+{$ENDIF}
 
 {other functions}
 
@@ -347,15 +378,15 @@ procedure GetEnvironmentPaths;
 begin
   //gets path
   path.EXEPATH := TPath.GetDirectoryName(ParamStr(0));
-  path.WINDOWS := GetEnvironmentVariable('windir');
-  path.PROGRAMFILES := GetEnvironmentVariable('ProgramFiles');
-  path.COMMONFILES := GetEnvironmentVariable('CommonProgramFiles(x86)');
-  path.HOMEDRIVE := GetEnvironmentVariable('SystemDrive');
-  path.USERPROFILE := GetEnvironmentVariable('USERPROFILE');
-  path.PROGRAMDATA := GetEnvironmentVariable('ProgramData');
-  path.ALLUSERSPROFILE := GetEnvironmentVariable('AllUsersProfile');
+  path.WINDOWS := SysUtils.GetEnvironmentVariable('windir');
+  path.PROGRAMFILES := SysUtils.GetEnvironmentVariable('ProgramFiles');
+  path.COMMONFILES := SysUtils.GetEnvironmentVariable('CommonProgramFiles(x86)');
+  path.HOMEDRIVE := SysUtils.GetEnvironmentVariable('SystemDrive');
+  path.USERPROFILE := SysUtils.GetEnvironmentVariable('USERPROFILE');
+  path.PROGRAMDATA := SysUtils.GetEnvironmentVariable('ProgramData');
+  path.ALLUSERSPROFILE := SysUtils.GetEnvironmentVariable('AllUsersProfile');
   path.INSTDRIVE := path.HOMEDRIVE;
-  path.TEMP := GetEnvironmentVariable('TEMP');
+  path.TEMP := SysUtils.GetEnvironmentVariable('TEMP');
   path.SYSTEM := GetSpecialFolderPath(CSIDL_SYSTEM);
   path.APPDATA:=GetSpecialFolderPath(CSIDL_APPDATA);
   //these paths fail if user is SYSTEM
@@ -377,11 +408,11 @@ var
 begin
   SHGetSpecialFolderLocation(0, folderID, ppidl);
   SetLength(Result, MAX_PATH);
-  if not SHGetPathFromIDList(ppidl, PChar(Result)) then
+  if not SHGetPathFromIDList(ppidl,{$IFDEF FPC}PAnsiChar(Result){$ELSE}PChar(Result){$ENDIF}) then
   begin
     raise EShellError.create(Format('GetSpecialFolderPath: Invalid PIPL (%d)',[folderID]));
   end;
-  SetLength(Result, lStrLen(PChar(Result)));
+  SetLength(Result, lStrLen({$IFDEF FPC}PAnsiChar(Result){$ELSE}PChar(Result){$ENDIF}));
 end;
 
 function Is64bitOS : Boolean;
@@ -455,6 +486,16 @@ begin
   Result := EncodeDate(YearOf(Now),MonthOf(Now), DaysInMonth(Now));
 end;
 
+{$IFDEF FPC}
+function DateTimeInRange(ADateTime: TDateTime; AStartDateTime, AEndDateTime: TDateTime; aInclusive: Boolean = True): Boolean;
+begin
+  if aInclusive then
+    Result := (AStartDateTime <= ADateTime) and (ADateTime <= AEndDateTime)
+  else
+    Result := (AStartDateTime < ADateTime) and (ADateTime < AEndDateTime);
+end;
+{$ENDIF}
+
 function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
 begin
   //Test: Result := MinutesBetween(cBefore,cNow) < 1;
@@ -636,6 +677,52 @@ begin
   Result := FindCmdLineSwitch(Switch,['-', '/'],True);
 end;
 
+{$IFDEF FPC}
+function FindCmdLineSwitch(const Switch: string; var Value: string; IgnoreCase: Boolean = True;
+  const SwitchTypes: TCmdLineSwitchTypes = [clstValueNextParam, clstValueAppended]): Boolean; overload;
+type
+  TCompareProc = function(const S1, S2: string): Boolean;
+var
+  Param: string;
+  I, ValueOfs,
+  SwitchLen, ParamLen: Integer;
+  SameSwitch: TCompareProc;
+begin
+  Result := False;
+  Value := '';
+  if IgnoreCase then
+    SameSwitch := SameText else
+    SameSwitch := SameStr;
+  SwitchLen := Switch.Length;
+
+  for I := 1 to ParamCount do
+  begin
+    Param := ParamStr(I);
+    if CharInSet(Param.Chars[0], SwitchChars) and SameSwitch(Param.SubString(1,SwitchLen), Switch) then
+    begin
+      ParamLen := Param.Length;
+      // Look for an appended value if the param is longer than the switch
+      if (ParamLen > SwitchLen + 1) then
+      begin
+        // If not looking for appended value switches then this is not a matching switch
+        if not (clstValueAppended in SwitchTypes) then
+          Continue;
+        ValueOfs := SwitchLen + 1;
+        if Param.Chars[ValueOfs] = ':' then
+          Inc(ValueOfs);
+        Value := Param.SubString(ValueOfs, MaxInt);
+      end
+      // If the next param is not a switch, then treat it as the value
+      else if (clstValueNextParam in SwitchTypes) and (I < ParamCount) and
+              not CharInSet(ParamStr(I+1).Chars[0], SwitchChars) then
+        Value := ParamStr(I+1);
+      Result := True;
+      Break;
+    end;
+  end;
+end;
+{$ENDIF}
+
 function ParamGetSwitch(const Switch : string; var cvalue : string) : Boolean;
 begin
   Result := FindCmdLineSwitch(Switch,cvalue,True,[clstValueAppended]);
@@ -704,12 +791,20 @@ end;
 
 function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
 begin
+  {$IFDEF FPC}
+  Result := LocalTimeToUniversal(GMTTime);
+  {$ELSE}
   Result :=  TTimeZone.Local.ToLocalTime(GMTTime);
+  {$ENDIF}
 end;
 
 function LocalTimeToUTC(LocalTime : TDateTime): TDateTime;
 begin
+  {$IFDEF FPC}
+  Result := UniversalTimeToLocal(Localtime);
+  {$ELSE}
   Result := TTimeZone.Local.ToUniversalTime(LocalTime);
+  {$ENDIF}
 end;
 
 function CountDigits(anInt: Cardinal): Cardinal; inline;

+ 55 - 12
Quick.Config.Provider.Json.pas

@@ -5,9 +5,9 @@
   Unit        : Quick.Config.Provider.Json
   Description : Save config to JSON file
   Author      : Kike Pérez
-  Version     : 1.1
+  Version     : 1.2
   Created     : 21/10/2017
-  Modified    : 12/02/2018
+  Modified    : 07/04/2018
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -28,20 +28,31 @@
  *************************************************************************** }
 unit Quick.Config.Provider.Json;
 
+{$i QuickLib.inc}
+
 interface
 
 uses
   Classes,
-  System.SysUtils,
-  System.IOUtils,
-  System.Rtti,
-  {$IF CompilerVersion >= 32.0}
+  SysUtils,
+  {$IFDEF DELPHIXE_UP}
+  IOUtils,
+  {$ELSE}
+  Quick.Files,
+  {$ENDIF}
+  Rtti,
+  {$IFDEF DELPHIRX102_UP}
     System.JSON.Types,
     System.JSON.Serializers,
   {$ELSE}
+    {$IFDEF FPC}
+    fpjson,
+    fpjsonrtti,
+    {$ELSE}
     Rest.Json.Types,
     System.JSON,
     Rest.Json,
+    {$ENDIF}
   {$ENDIF}
   Quick.Config;
 
@@ -70,9 +81,12 @@ end;
 procedure TAppConfigJsonProvider<T>.Load(var cConfig : T);
 var
   json : TStrings;
-  {$IF CompilerVersion >= 32.0}
+  {$IFDEF DELPHIRX102_UP}
     Serializer : TJsonSerializer;
   {$ENDIF}
+  {$IFDEF FPC}
+    streamer : TJSONDeStreamer;
+  {$ENDIF}
   NewObj : T;
 begin
   //create object with rtti if nil
@@ -88,7 +102,7 @@ begin
     json := TStringList.Create;
     try
       json.LoadFromFile(fFilename);
-      {$IF CompilerVersion >= 32.0}
+      {$IFDEF DELPHIRX102_UP}
         Serializer := TJsonSerializer.Create;
         try
           if TAppConfig(cConfig).DateTimeZone = TDateTimeZone.tzLocal then
@@ -102,7 +116,18 @@ begin
           Serializer.Free;
         end;
       {$ELSE}
-        TJson.JsonToObject(cConfig,TJSONObject(TJSONObject.ParseJSONValue(json.Text)));
+        {$IFDEF FPC}
+        streamer := TJSONDeStreamer.Create(nil);
+        try
+          //Streamer.Options := Streamer. .Options + [jsoDateTimeAsString ,jsoUseFormatString];
+          Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
+          Streamer.JsonToObject(json.Text,NewObj);
+        finally
+          Streamer.Free;
+        end;
+        {$ELSE}
+        TJson.JsonToObject(Self,TJSONObject(TJSONObject.ParseJSONValue(json)));
+        {$ENDIF}
       {$ENDIF}
       if Assigned(cConfig) then cConfig.Free;
       cConfig := NewObj;
@@ -117,9 +142,12 @@ end;
 procedure TAppConfigJsonProvider<T>.Save(var cConfig : T);
 var
   json : TStrings;
-  {$IF CompilerVersion >= 32.0}
+  {$IFDEF DELPHIRX102_UP}
     Serializer : TJsonSerializer;
   {$ENDIF}
+  {$IFDEF FPC}
+  streamer : TJsonStreamer;
+  {$ENDIF}
   ctx : TRttiContext;
   rprop : TRttiProperty;
 begin
@@ -129,7 +157,7 @@ begin
   try
     json := TStringList.Create;
     try
-      {$IF CompilerVersion >= 32.0}
+      {$IFDEF DELPHIRX102_UP}
         Serializer := TJsonSerializer.Create;
         try
           if TAppConfig(cConfig).JsonIndent then Serializer.Formatting := TJsonFormatting.Indented;
@@ -144,9 +172,23 @@ begin
           Serializer.Free;
         end;
       {$ELSE}
-        json.Text := TJson.ObjectToJsonString(cConfig);
+        {$IFDEF FPC}
+        streamer := TJsonStreamer.Create(nil);
+        try
+          Streamer.Options := Streamer.Options + [jsoDateTimeAsString ,jsoUseFormatString];
+          Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
+          json.Text := streamer.ObjectToJSONString(cConfig);
+        finally
+          streamer.Free;
+        end;
+        {$ELSE}
+          json.Text := TJson.ObjectToJsonString(cConfig);
+        {$ENDIF}
       {$ENDIF}
       json.SaveToFile(fFilename);
+      {$IFDEF FPC}
+      //TAppConfig(cConfig).LastSaved := Now;
+      {$ELSE}
       ctx := TRttiContext.Create;
       try
         rprop := ctx.GetType(TypeInfo(T)).GetProperty('LastSaved');
@@ -154,6 +196,7 @@ begin
       finally
         ctx.Free;
       end;
+      {$ENDIF}
     finally
       json.Free;
     end;

+ 32 - 9
Quick.Config.Provider.Registry.pas

@@ -1,13 +1,13 @@
 { ***************************************************************************
 
-  Copyright (c) 2015-2017 Kike Pérez
+  Copyright (c) 2015-2018 Kike Pérez
 
   Unit        : Quick.Config.Provider.Registry
   Description : Save config to Windows Registry
   Author      : Kike Pérez
-  Version     : 1.1
+  Version     : 1.2
   Created     : 21/10/2017
-  Modified    : 11/11/2017
+  Modified    : 07/04/2018
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -28,27 +28,36 @@
  *************************************************************************** }
 unit Quick.Config.Provider.Registry;
 
+{$i QuickLib.inc}
+
 interface
 
 uses
   Classes,
   Windows,
-  System.SysUtils,
-  System.Win.Registry,
-  {$IF CompilerVersion >= 32.0}
+  SysUtils,
+  Registry,
+  {$IFDEF DELPHIRX102_UP}
     System.Json,
     System.JSON.Types,
     System.JSON.Serializers,
   {$ELSE}
+    {$IFDEF FPC}
+    fpjson,   jsonparser,
+    fpjsonrtti,
+    {$ELSE}
     Rest.Json.Types,
     System.JSON,
     Rest.Json,
+    {$ENDIF}
   {$ENDIF}
   Quick.Commons,
   Quick.Config;
 
 type
 
+  TJSONValue = TJSONData;
+
   TAppConfigRegistryProvider<T : class> = class(TAppConfigProviderBase<T>)
   private
     fRootKey : HKEY;
@@ -99,9 +108,12 @@ end;
 
 procedure TAppConfigRegistryProvider<T>.Load(var cConfig : T);
 var
-  {$IF CompilerVersion >= 32.0}
+  {$IFDEF DELPHIRX102_UP}
     Serializer: TJsonSerializer;
   {$ENDIF}
+  {$IFDEF FPC}
+    streamer : TJSONDeStreamer;
+  {$ENDIF}
   json : string;
   newObj : T;
 begin
@@ -113,7 +125,7 @@ begin
     Save(cConfig);
   end;
   RegistryToJson(json);
-  {$IF CompilerVersion >= 32.0}
+  {$IFDEF DELPHIRX102_UP}
     Serializer := TJsonSerializer.Create;
     try
       Serializer.Formatting := TJsonFormatting.Indented;
@@ -128,7 +140,18 @@ begin
       Serializer.Free;
     end;
   {$ELSE}
-    TJson.JsonToObject(cConfig,TJSONObject(TJSONObject.ParseJSONValue(json)));
+    {$IFDEF FPC}
+    streamer := TJSONDeStreamer.Create(nil);
+    try
+      //Streamer.Options := Streamer. .Options + [jsoDateTimeAsString ,jsoUseFormatString];
+      Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
+      Streamer.JsonToObject(json,NewObj);
+    finally
+      Streamer.Free;
+    end;
+    {$ELSE}
+    TJson.JsonToObject(newObj,TJSONObject(TJSONObject.ParseJSONValue(json)));
+    {$ENDIF}
   {$ENDIF}
   if Assigned(cConfig) then cConfig.Free;
   cConfig := newObj;

+ 73 - 24
Quick.Config.pas

@@ -5,9 +5,9 @@
   Unit        : Quick.Config
   Description : Load/Save config from/to JSON file
   Author      : Kike Pérez
-  Version     : 1.2
+  Version     : 1.4
   Created     : 26/01/2017
-  Modified    : 12/02/2018
+  Modified    : 07/04/2018
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -31,16 +31,25 @@ unit Quick.Config;
 
 interface
 
+{$i QuickLib.inc}
+
 uses
-  System.Classes,
-  System.SysUtils,
-  System.Rtti,
-  {$IF CompilerVersion >= 32.0}
+  Classes,
+  SysUtils,
+  Rtti,
+  {$IFDEF DELPHIRX102_UP}
+    DBXJSON,
     JSON.Types,
     JSON.Serializers;
   {$ELSE}
+    {$IFDEF FPC}
+    fpjson,
+    fpjsonrtti;
+    {$ELSE}
+    DBXJSON,
     Rest.Json.Types,
     Rest.Json;
+    {$ENDIF}
   {$ENDIF}
 
 type
@@ -66,9 +75,15 @@ type
 
   TApplyConfigEvent = procedure of object;
 
-  [JsonSerialize(TJsonMemberSerialization.&Public)]
-  TAppConfig = class
+  {$IFDEF DELPHIXE2_UP}[JsonSerialize(TJsonMemberSerialization.&Public)]{$ENDIF}
+  TAppConfig = class{$IFDEF FPC}(TPersistent){$ENDIF}
   private
+    {$IFDEF FPC}
+    fOnApplyConfig : TApplyConfigEvent;
+    fDateTimeZone: TDateTimeZone;
+    fJsonIndent: Boolean;
+    fLastSaved : TDateTime;
+    {$ELSE}
     {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
     fOnApplyConfig : TApplyConfigEvent;
     {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
@@ -77,15 +92,16 @@ type
     fJsonIndent: Boolean;
     {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
     fLastSaved : TDateTime;
+    {$ENDIF}
   public
     constructor Create; virtual;
-    {$IF CompilerVersion >= 32.0}[JsonIgnoreAttribute]{$ENDIF}
+    {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
     property OnApplyConfig : TApplyConfigEvent read fOnApplyConfig write fOnApplyConfig;
-    {$IF CompilerVersion >= 32.0}[JsonIgnoreAttribute]{$ENDIF}
+    {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
     property DateTimeZone : TDateTimeZone read fDateTimeZone write fDateTimeZone;
-    {$IF CompilerVersion >= 32.0}[JsonIgnoreAttribute]{$ENDIF}
+    {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
     property JsonIndent : Boolean read fJsonIndent write fJsonIndent;
-    {$IF CompilerVersion >= 32.0}[JsonIgnoreAttribute]{$ENDIF}
+    {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
     property LastSaved : TDateTime read fLastSaved write fLastSaved;
     procedure Apply;
     procedure DefaultValues; virtual;
@@ -127,7 +143,6 @@ function TAppConfigProviderBase<T>.InitObject : T;
 var
   AValue: TValue;
   ctx: TRttiContext;
-  f : TRttiField;
   rType: TRttiType;
   AMethCreate: TRttiMethod;
 begin
@@ -138,8 +153,12 @@ begin
     begin
       if (AMethCreate.IsConstructor) and (Length(AMethCreate.GetParameters) = 0) then
       begin
+        {$IFDEF FPC}
+        Result := T(GetClass(T.ClassName).Create);
+        {$ELSE}
         AValue := AMethCreate.Invoke(rType.AsInstance.AsInstance.MetaclassType,[]);
         Result := AValue.AsType<T>;
+        {$ENDIF}
         Break;
       end;
     end;
@@ -169,14 +188,18 @@ end;
 
 
 function TAppConfig.ToJSON : string;
-{$IF CompilerVersion >= 32.0}
-  var
-    Serializer : TJsonSerializer;
-  {$ENDIF}
+{$IFDEF DELPHIRX102_UP}
+var
+  Serializer : TJsonSerializer;
+{$ENDIF}
+{$IFDEF FPC}
+var
+  streamer : TJsonStreamer;
+{$ENDIF}
 begin
   Result := '';
   try
-    {$IF CompilerVersion >= 32.0}
+    {$IFDEF DELPHIRX102_UP}
       Serializer := TJsonSerializer.Create;
       try
         Serializer.Formatting := TJsonFormatting.Indented;
@@ -192,7 +215,18 @@ begin
         Serializer.Free;
       end;
     {$ELSE}
+      {$IFDEF FPC}
+      streamer := TJsonStreamer.Create(nil);
+      try
+        Streamer.Options := Streamer.Options + [jsoDateTimeAsString ,jsoUseFormatString];
+        Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
+        Result := streamer.ObjectToJSON(Self).ToString;
+      finally
+        streamer.Free;
+      end;
+      {$ELSE}
       Result := TJson.ObjectToJsonString(Self);
+      {$ENDIF}
     {$ENDIF}
   except
     on e : Exception do raise Exception.Create(e.Message);
@@ -200,13 +234,17 @@ begin
 end;
 
 procedure TAppConfig.FromJSON(const json : string);
-{$IF CompilerVersion >= 32.0}
-  var
-    Serializer : TJsonSerializer;
-  {$ENDIF}
+{$IFDEF DELPHIRX102_UP}
+var
+  Serializer : TJsonSerializer;
+{$ENDIF}
+{$IFDEF FPC}
+var
+  streamer : TJSONDeStreamer;
+{$ENDIF}
 begin
   try
-    {$IF CompilerVersion >= 32.0}
+    {$IFDEF DELPHIRX102_UP}
       Serializer := TJsonSerializer.Create;
       try
         Serializer.Formatting := TJsonFormatting.Indented;
@@ -222,7 +260,18 @@ begin
         Serializer.Free;
       end;
     {$ELSE}
-      TJson.JsonToObject(Self,TJSONObject(TJSONObject.ParseJSONValue(json.Text)));
+      {$IFDEF FPC}
+      streamer := TJSONDeStreamer.Create(nil);
+      try
+        //Streamer.Options := Streamer. .Options + [jsoDateTimeAsString ,jsoUseFormatString];
+        Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
+        Streamer.JsonToObject(json,Self);
+      finally
+        Streamer.Free;
+      end;
+      {$ELSE}
+      TJson.JsonToObject(Self,TJSONObject(TJSONObject.ParseJSONValue(json)));
+      {$ENDIF}
     {$ENDIF}
   except
     on e : Exception do raise Exception.Create(e.Message);

+ 35 - 6
Quick.Console.pas

@@ -29,13 +29,15 @@
 
 unit Quick.Console;
 
+{$i QuickLib.inc}
+
 {$IFDEF CONDITIONALEXPRESSIONS}
   {$ifndef VER140}
     {$ifndef LINUX}
       {$define WITHUXTHEME}
     {$endif}
   {$endif}
-  {$IF CompilerVersion >= 17.0}
+  {$IFDEF DELPHI2005_UP}
     {$DEFINE INLINES}
   {$ENDIF}
   {$IF RTLVersion >= 14.0}
@@ -48,8 +50,8 @@ interface
 uses
   Classes,
   Windows,
-  Winapi.Messages,
-  System.SysUtils,
+  Messages,
+  SysUtils,
   Quick.Commons,
   Quick.Log;
 
@@ -79,8 +81,13 @@ type
     Log : TQuickLog;
   end;
 
+  {$IFNDEF FPC}
   TOutputProc<T> = reference to procedure(const aLine : T);
   TExecuteProc = reference to procedure;
+  {$ELSE}
+  TOutputProc<T> = procedure(const aLine : T) of object;
+  TExecuteProc = procedure of object;
+  {$ENDIF}
 
   TConsoleMenuOption = record
   private
@@ -165,7 +172,9 @@ var
   FmtSets : TFormatSettings;
 begin
   try
+    {$IFNDEF FPC}
     FmtSets := TFormatSettings.Create;
+    {$ENDIF}
     FmtSets.ThousandSeparator := '.';
     FmtSets.DecimalSeparator := ',';
     cout(FormatFloat('0,',cMsg,FmtSets),cEventType);
@@ -179,7 +188,9 @@ var
   FmtSets : TFormatSettings;
 begin
   try
+    {$IFNDEF FPC}
     FmtSets := TFormatSettings.Create;
+    {$ENDIF}
     FmtSets.ThousandSeparator := '.';
     FmtSets.DecimalSeparator := ',';
     cout(FormatFloat('.0###,',cMsg,FmtSets),cEventType);
@@ -499,6 +510,7 @@ begin
   end;
 end;
 
+{$IFDEF MSWINDOWS}
 procedure ConsoleWaitForEnterKey;
 var
   msg: TMsg;
@@ -506,7 +518,16 @@ begin
   while not ConsoleKeyPressed(VK_RETURN) do
   begin
     {$ifndef LVCL}
-    if GetCurrentThreadID=MainThreadID then CheckSynchronize{$ifdef WITHUXTHEME}(1000){$endif}  else
+      {$IFDEF FPC}
+      if GetCurrentThreadID = MainThreadID then
+      begin
+        CheckSynchronize;
+        Sleep(1);
+      end
+      else
+      {$ELSE}
+      if GetCurrentThreadID = MainThreadID then CheckSynchronize{$IFDEF DELPHI7_UP}(1000){$ENDIF}  else
+      {$ENDIF}
     {$endif}
     WaitMessage;
     while PeekMessage(msg,0,0,0,PM_REMOVE) do
@@ -520,6 +541,12 @@ begin
     end;
   end;
 end;
+{$ELSE}
+procedure ConsoleWaitForEnterKey;
+begin
+  ReadLn;
+end;
+{$ENDIF}
 
 procedure RunConsoleCommand(const aCommand, aParameters : String; CallBack : TOutputProc<PAnsiChar> = nil; OutputLines : TStrings = nil);
 const
@@ -604,7 +631,9 @@ begin
   {$ENDIF}
   if not GetConsoleScreenBufferInfo(hStdOut, BufferInfo) then
   begin
+    {$IFNDEF FPC}
     SetInOutRes(GetLastError);
+    {$ENDIF}
     Exit;
   end;
   ConsoleRect.Left := 0;
@@ -625,7 +654,7 @@ begin
   conmenu.Caption := cMenuCaption;
   conmenu.Key := cMenuKey;
   conmenu.OnKeyPressed := MenuAction;
-  {$IF CompilerVersion > 27}
+  {$IFDEF DELPHIXE7_UP}
   fConsoleMenu := fConsoleMenu + [conmenu];
   {$ELSE}
   SetLength(fConsoleMenu,High(fConsoleMenu)+1);
@@ -635,7 +664,7 @@ end;
 
 procedure TConsoleMenu.AddMenu(MenuOption: TConsoleMenuOption);
 begin
-  {$IF CompilerVersion > 27}
+  {$IFDEF DELPHIXE7_UP}
   fConsoleMenu := fConsoleMenu + [MenuOption];
   {$ELSE}
   SetLength(fConsoleMenu,High(fConsoleMenu)+1);

+ 10 - 4
Quick.FileMonitor.pas

@@ -1,13 +1,13 @@
 { ***************************************************************************
 
-  Copyright (c) 2015-2017 Kike Pérez
+  Copyright (c) 2015-2018 Kike Pérez
 
   Unit        : Quick.FileMonitor
   Description : Watch for single file changes
   Author      : Kike Pérez
-  Version     : 1.0
+  Version     : 1.1
   Created     : 11/09/2017
-  Modified    : 16/09/2017
+  Modified    : 07/04/2018
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -31,11 +31,17 @@ unit Quick.FileMonitor;
 
 interface
 
+{$i QuickLib.inc}
+
 uses
   Classes,
   Windows,
-  System.SysUtils,
+  SysUtils,
+  {$IFDEF FPC}
+  Quick.Files;
+  {$ELSE}
   System.IOUtils;
+  {$ENDIF}
 
 type
 

+ 711 - 23
Quick.Files.pas

@@ -5,9 +5,9 @@
   Unit        : Quick.Files
   Description : Files functions
   Author      : Kike Pérez
-  Version     : 1.0
+  Version     : 1.1
   Created     : 09/03/2018
-  Modified    : 15/03/2018
+  Modified    : 07/04/2018
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -29,18 +29,46 @@
 
 unit Quick.Files;
 
+{$i QuickLib.inc}
+
 interface
 
 uses
   Classes,
-  System.SysUtils,
-  Winapi.Windows;
+  SysUtils,
+  {$IFDEF FPC}
+  strutils,
+  DateUtils,
+  {$ENDIF}
+  Windows;
+
+{$IFDEF FPC}
+resourcestring
+
+  SPathTooLong = 'The specified path is too long';
+  SPathNotFound = 'The specified path was not found';
+  SPathFormatNotSupported = 'The path format is not supported';
+  SDirectoryNotEmpty = 'The specified directory is not empty';
+  SDirectoryAlreadyExists = 'The specified directory already exists';
+  SDirectoryInvalid = 'The specified directory name is invalid';
+  SSourceDirIsDestDir = 'The source directory is the same as the destination directory';
+  SSourceFileIsDestFile = 'The source file is the same as the destination file';
+  SPathToFileNeeded = 'The path must specify a file';
+  SSameRootDrive = 'The source and destination paths must contain the same root drive';
+  SDriveNotFound = 'The drive cannot be found';
+  SFileNotFound = 'The specified file was not found';
+  SFileAlreadyExists = 'The specified file already exists';
+  SInvalidCharsInPath = 'Invalid characters in path';
+  SInvalidCharsInFileName = 'Invalid characters in file name';
+{$ENDIF}
 
 type
 
+
+  {$IFNDEF FPC}
   TTextFileOperation = (tfOpenRead,tfOpenOverwrite,tfOpenAppend);
 
-	TTextStreamFile = class
+  TTextStreamFile = class
     private
       fReadStream : TStreamReader;
       fWriteStream : TStreamWriter;
@@ -54,6 +82,125 @@ type
       procedure Close;
       property EOF: Boolean read GetEOF;
   end;
+  {$ENDIF}
+
+  {$IFDEF FPC}
+  EStreamError = class(Exception);
+  EFileStreamError = class(EStreamError)
+    constructor Create(ResStringRec: PResStringRec; const FileName: string);
+  end;
+
+  TPathPrefixType = (pptNoPrefix, pptExtended, pptExtendedUNC);
+
+  TPath = class
+  private
+    const
+      FCCurrentDir: string = '.';
+      FCParentDir: string = '..';
+      FCExtendedPrefix: string = '\\?\';
+      FCExtendedUNCPrefix: string = '\\?\UNC\';
+    class procedure CheckPathLength(const Path: string; const MaxLength: Integer);
+  public
+    class function GetFileNameWithoutExtension(const FileName : string) : string;
+    class function GetDirectoryName(const FileName : string) : string;
+    class function GetExtension(const Path : string) : string;
+    class function ChangeExtension(const Path, NewExtension : string) : string;
+  end;
+
+  TDirectory = class
+  public
+    class function Exists(const Path: string; FollowLink: Boolean = True): Boolean;
+  end;
+
+  TFile = class
+  public
+    class function Exists(const Path : string) : Boolean;
+    class function IsInUse(const Path : string) : Boolean;
+    class function GetSize(const Path : string) : Int64;
+    class function Create(const Path: string; const BufferSize: Integer): TFileStream; overload;
+    class function Create(const Path: string): TFileStream; overload;
+    class function GetExtension(const Path : string) : string;
+    class function GetCreationTime(const Path : string): TDateTime;
+    class function GetLastAccessTime(const Path : string): TDateTime;
+    class function GetLastWriteTime(const Path : string): TDateTime;
+    class procedure SetCreationTime(const Path: string; const CreationTime: TDateTime);
+    class procedure SetLastAccessTime(const Path: string; const LastAccessTime: TDateTime);
+    class procedure SetLastWriteTime(const Path: string; const LastWriteTime: TDateTime);
+    class function IsReadOnly(const Path : string) : Boolean;
+    class function Delete(const Path : string) : Boolean;
+    class function Move(const SourceFileName, DestFileName: string) : Boolean;
+  end;
+
+  TTextWriter = class
+  public
+    procedure Close; virtual; abstract;
+    procedure Flush; virtual; abstract;
+    procedure Write(Value: Boolean); overload; virtual; abstract;
+    procedure Write(Value: Char); overload; virtual; abstract;
+    procedure Write(Value: Double); overload; virtual; abstract;
+    procedure Write(Value: Integer); overload; virtual; abstract;
+    procedure Write(Value: Int64); overload; virtual; abstract;
+    procedure Write(Value: TObject); overload; virtual; abstract;
+    procedure Write(Value: Single); overload; virtual; abstract;
+    procedure Write(const Value: string); overload; virtual; abstract;
+    procedure Write(const aFormat: string; Args: array of const); overload; virtual; abstract;
+    procedure WriteLine; overload; virtual; abstract;
+    procedure WriteLine(Value: Boolean); overload; virtual; abstract;
+    procedure WriteLine(Value: Char); overload; virtual; abstract;
+    procedure WriteLine(Value: Double); overload; virtual; abstract;
+    procedure WriteLine(Value: Integer); overload; virtual; abstract;
+    procedure WriteLine(Value: Int64); overload; virtual; abstract;
+    procedure WriteLine(Value: TObject); overload; virtual; abstract;
+    procedure WriteLine(Value: Single); overload; virtual; abstract;
+    procedure WriteLine(const Value: string); overload; virtual; abstract;
+    procedure WriteLine(const aFormat: string; Args: array of const); overload; virtual; abstract;
+    procedure WriteLine(const Value: TCharArray; Index, Count: Integer); overload; virtual; abstract;
+  end;
+
+  TStreamWriter = class(TTextWriter)
+  private
+    FStream: TStream;
+    FEncoding: TEncoding;
+    FNewLine: string;
+    FAutoFlush: Boolean;
+    FOwnsStream: Boolean;
+    FBufferIndex: Integer;
+    FBuffer: TBytes;
+    procedure WriteBytes(Bytes: TBytes);
+  public
+    constructor Create(Stream: TStream); overload;
+    constructor Create(Stream: TStream; Encoding: TEncoding; BufferSize: Integer = 4096); overload;
+    constructor Create(const Filename: string; Append: Boolean = False); overload;
+    constructor Create(const Filename: string; Append: Boolean; Encoding: TEncoding; BufferSize: Integer = 4096); overload;
+    destructor Destroy; override;
+    procedure Close; override;
+    procedure Flush; override;
+    procedure OwnStream; inline;
+    procedure Write(Value: Boolean); override;
+    procedure Write(Value: Char); override;
+    procedure Write(Value: Double); override;
+    procedure Write(Value: Integer); override;
+    procedure Write(Value: Int64); override;
+    procedure Write(Value: TObject); override;
+    procedure Write(Value: Single); override;
+    procedure Write(const Value: string); override;
+    procedure Write(const aFormat: string; Args: array of const); override;
+    procedure WriteLine; override;
+    procedure WriteLine(Value: Boolean); override;
+    procedure WriteLine(Value: Char); override;
+    procedure WriteLine(Value: Double); override;
+    procedure WriteLine(Value: Integer); override;
+    procedure WriteLine(Value: Int64); override;
+    procedure WriteLine(Value: TObject); override;
+    procedure WriteLine(Value: Single); override;
+    procedure WriteLine(const Value: string); override;
+    procedure WriteLine(const aFormat: string; Args: array of const); override;
+    property AutoFlush: Boolean read FAutoFlush write FAutoFlush;
+    property NewLine: string read FNewLine write FNewLine;
+    property Encoding: TEncoding read FEncoding;
+    property BaseStream: TStream read FStream;
+  end;
+  {$ENDIF FPC}
 
   function CreateDummyFile(const aFilename : string; const aSize : Int64) : Boolean;
   procedure SplitFile(const aFileName : string; aSplitByteSize : Int64);
@@ -62,14 +209,20 @@ type
   function IsFileInUse(const aFileName : string) : Boolean;
   procedure FileReplaceText(const aFileName, aSearchText, AReplaceText : string);
   function FileSearchText(const aFileName, SearchText: string; caseSensitive : Boolean): Longint;
-  function GetLastAccessTime(const aFileName: string): TDateTime;
   function GetCreationTime(const aFilename : string): TDateTime;
-  function GetLastModificationTime(const aFileName : string): TDateTime;
+  function GetLastAccessTime(const aFileName: string): TDateTime;
+  function GetLastWriteTime(const aFileName : string): TDateTime;
+  {$IFDEF FPC}
+  function FindDelimiter(const Delimiters, S: string; StartIdx: Integer = 1): Integer;
+  {$ENDIF}
+  function ConvertDateTimeToFileTime(const DateTime: TDateTime; const UseLocalTimeZone: Boolean): TFileTime;
+  procedure SetDateTimeInfo(const Path: string; const CreationTime, LastAccessTime, LastWriteTime: PDateTime; const UseLocalTimeZone: Boolean);
 
 implementation
 
 { TTextStreamFile }
 
+{$IFNDEF FPC}
 constructor TTextStreamFile.Create(const aFileName : string; aOpenMode : TTextFileOperation);
 var
   Append : Boolean;
@@ -117,6 +270,367 @@ begin
   if Assigned(fWriteStream) then fWriteStream.Close;
 end;
 
+{$ENDIF NFPC}
+
+{$IFDEF FPC}
+
+{ EFileStreamError }
+
+constructor EFileStreamError.Create(ResStringRec: PResStringRec;
+  const FileName: string);
+begin
+  inherited CreateResFmt(ResStringRec, [ExpandFileName(FileName), SysErrorMessage(GetLastError)]);
+end;
+
+{ TPath }
+
+class function TPath.GetFileNameWithoutExtension(const FileName: String): String;
+var
+  fname : string;
+begin
+  fname := ExtractFileName(FileName);
+  Result := Copy(fname, 1, Length(fname) - Length(ExtractFileExt(fname)));
+end;
+
+class function TPath.ChangeExtension(const Path, NewExtension : string) : string;
+var
+  dot : string;
+begin
+  if NewExtension.Contains('.') then dot := ''
+    else dot := '.';
+  Result := TPath.GetFileNameWithoutExtension(Path) + dot + NewExtension;
+end;
+
+class function TPath.GetDirectoryName(const FileName : string) : string;
+begin
+  Result := ExtractFileDir(Filename);
+end;
+
+class procedure TPath.CheckPathLength(const Path: string; const MaxLength: Integer);
+begin
+{$IFDEF MSWINDOWS}
+  if (Length(Path) >= MaxLength) then
+{$ENDIF MSWINDOWS}
+{$IFDEF POSIX}
+  if (Length(UTF8Encode(Path)) >= MaxLength) then
+{$ENDIF POSIX}
+    raise EPathTooLongException.CreateRes(@SPathTooLong);
+end;
+
+class function TPath.GetExtension(const Path : string) : string;
+begin
+  Result := ExtractFileExt(Path);
+end;
+
+{ TDirectory }
+
+class function TDirectory.Exists(const Path: string; FollowLink: Boolean = True): Boolean;
+begin
+  Result := DirectoryExists(Path);
+end;
+
+{ TFile }
+
+class function TFile.Exists(const Path : string) : Boolean;
+begin
+  Result := FileExists(Path);
+end;
+
+class procedure TFile.SetCreationTime(const Path: string; const CreationTime: TDateTime);
+begin
+  SetDateTimeInfo(Path,@CreationTime,nil,nil,True);
+end;
+
+class procedure TFile.SetLastAccessTime(const Path: string; const LastAccessTime: TDateTime);
+begin
+  SetDateTimeInfo(Path,nil,@LastAccessTime,nil,True);
+end;
+
+class procedure TFile.SetLastWriteTime(const Path: string; const LastWriteTime: TDateTime);
+begin
+  SetDateTimeInfo(Path,nil,nil,@LastWriteTime,True);
+end;
+
+class function TFile.IsReadOnly(const Path : string) : Boolean;
+begin
+  Result := FileIsReadOnly(Path);
+end;
+
+class function TFile.Delete(const Path : string) : Boolean;
+begin
+  Result := DeleteFile(PChar(Path));
+end;
+
+class function TFile.Move(const SourceFileName, DestFileName: string) : Boolean;
+begin
+  Result := MoveFile(PChar(SourceFileName),PChar(DestFileName));
+end;
+
+class function TFile.IsInUse(const Path : string) : Boolean;
+begin
+  Result := IsFileInUse(Path);
+end;
+
+class function TFile.GetSize(const Path : string) : Int64;
+var
+  f : File of Byte;
+begin
+  Assign(f,Path);
+  try
+    Reset (f);
+    Result := FileSize(f);
+  finally
+    CloseFile(f);
+  end;
+end;
+
+class function TFile.GetExtension(const Path : string) : string;
+begin
+  Result := ExtractFileExt(Path);
+end;
+
+class function TFile.GetCreationTime(const Path : string) : TDateTime;
+begin
+  Result := Quick.Files.GetCreationTime(Path);
+end;
+
+class function TFile.GetLastAccessTime(const Path : string) : TDateTime;
+begin
+  Result := Quick.Files.GetLastAccessTime(Path);
+end;
+
+class function TFile.GetLastWriteTime(const Path : string) : TDateTime;
+begin
+  Result := Quick.Files.GetLastWriteTime(Path);
+end;
+
+class function TFile.Create(const Path: string; const BufferSize: Integer): TFileStream;
+begin
+  try
+    Result := TFileStream.Create(Path,fmCreate);
+  except
+    on E: EFileStreamError do
+      raise EInOutError.Create(E.Message);
+  end;
+end;
+
+class function TFile.Create(const Path: string): TFileStream;
+begin
+  Result := Create(Path, 0);
+end;
+
+{ TStreamWriter }
+
+procedure TStreamWriter.Close;
+begin
+  Flush;
+  if FOwnsStream  then
+    FreeAndNil(FStream);
+end;
+
+constructor TStreamWriter.Create(Stream: TStream);
+begin
+  inherited Create;
+  FOwnsStream := False;
+  FStream := Stream;
+  FEncoding := TEncoding.UTF8;
+  SetLength(FBuffer, 1024);
+  FBufferIndex := 0;
+  FNewLine := sLineBreak;
+  FAutoFlush := True;
+end;
+
+constructor TStreamWriter.Create(Stream: TStream; Encoding: TEncoding; BufferSize: Integer);
+begin
+  inherited Create;
+  FOwnsStream := False;
+  FStream := Stream;
+  FEncoding := Encoding;
+  if BufferSize >= 128 then
+    SetLength(FBuffer, BufferSize)
+  else
+    SetLength(FBuffer, 128);
+  FBufferIndex := 0;
+  FNewLine := sLineBreak;
+  FAutoFlush := True;
+  if Stream.Position = 0 then
+    WriteBytes(FEncoding.GetPreamble);
+end;
+
+constructor TStreamWriter.Create(const Filename: string; Append: Boolean);
+begin
+  if (not FileExists(Filename)) or (not Append) then
+    FStream := TFileStream.Create(Filename, fmCreate)
+  else
+  begin
+    FStream := TFileStream.Create(Filename, fmOpenWrite);
+    FStream.Seek(0, soEnd);
+  end;
+  Create(FStream);
+  FOwnsStream := True;
+end;
+
+constructor TStreamWriter.Create(const Filename: string; Append: Boolean;
+  Encoding: TEncoding; BufferSize: Integer);
+begin
+  if (not FileExists(Filename)) or (not Append) then
+    FStream := TFileStream.Create(Filename, fmCreate)
+  else
+  begin
+    FStream := TFileStream.Create(Filename, fmOpenWrite);
+    FStream.Seek(0, soEnd);
+  end;
+  Create(FStream, Encoding, BufferSize);
+  FOwnsStream := True;
+end;
+
+destructor TStreamWriter.Destroy;
+begin
+  Close;
+  SetLength(FBuffer, 0);
+  inherited;
+end;
+
+procedure TStreamWriter.Flush;
+begin
+  if FBufferIndex = 0 then
+    Exit;
+  if FStream = nil then
+    Exit;
+
+  FStream.Write(FBuffer[0], FBufferIndex);
+  FBufferIndex := 0;
+end;
+
+procedure TStreamWriter.OwnStream;
+begin
+  FOwnsStream := True;
+end;
+
+procedure TStreamWriter.Write(const Value: string);
+begin
+  WriteBytes(FEncoding.GetBytes(Value));
+end;
+
+procedure TStreamWriter.WriteBytes(Bytes: TBytes);
+var
+  ByteIndex: Integer;
+  WriteLen: Integer;
+begin
+  ByteIndex := 0;
+
+  while ByteIndex < Length(Bytes) do
+  begin
+    WriteLen := Length(Bytes) - ByteIndex;
+    if WriteLen > Length(FBuffer) - FBufferIndex then
+      WriteLen := Length(FBuffer) - FBufferIndex;
+
+    Move(Bytes[ByteIndex], FBuffer[FBufferIndex], WriteLen);
+
+    Inc(FBufferIndex, WriteLen);
+    Inc(ByteIndex, WriteLen);
+
+    if FBufferIndex >= Length(FBuffer) then
+      Flush;
+  end;
+
+  if FAutoFlush then
+    Flush;
+end;
+
+procedure TStreamWriter.Write(const aFormat: string; Args: array of const);
+begin
+  WriteBytes(FEncoding.GetBytes(Format(aFormat, Args)));
+end;
+
+procedure TStreamWriter.Write(Value: Single);
+begin
+  WriteBytes(FEncoding.GetBytes(FloatToStr(Value)));
+end;
+
+procedure TStreamWriter.Write(Value: Double);
+begin
+  WriteBytes(FEncoding.GetBytes(FloatToStr(Value)));
+end;
+
+procedure TStreamWriter.Write(Value: Integer);
+begin
+  WriteBytes(FEncoding.GetBytes(IntToStr(Value)));
+end;
+
+procedure TStreamWriter.Write(Value: Char);
+begin
+  WriteBytes(FEncoding.GetBytes(Value));
+end;
+
+procedure TStreamWriter.Write(Value: TObject);
+begin
+  WriteBytes(FEncoding.GetBytes(Value.ToString));
+end;
+
+procedure TStreamWriter.Write(Value: Int64);
+begin
+  WriteBytes(FEncoding.GetBytes(IntToStr(Value)));
+end;
+
+procedure TStreamWriter.Write(Value: Boolean);
+begin
+  WriteBytes(FEncoding.GetBytes(BoolToStr(Value, True)));
+end;
+
+procedure TStreamWriter.WriteLine(Value: Double);
+begin
+  WriteBytes(FEncoding.GetBytes(FloatToStr(Value) + FNewLine));
+end;
+
+procedure TStreamWriter.WriteLine(Value: Integer);
+begin
+  WriteBytes(FEncoding.GetBytes(IntToStr(Value) + FNewLine));
+end;
+
+procedure TStreamWriter.WriteLine;
+begin
+  WriteBytes(FEncoding.GetBytes(FNewLine));
+end;
+
+procedure TStreamWriter.WriteLine(Value: Boolean);
+begin
+  WriteBytes(FEncoding.GetBytes(BoolToStr(Value, True) + FNewLine));
+end;
+
+procedure TStreamWriter.WriteLine(Value: Char);
+begin
+  WriteBytes(FEncoding.GetBytes(Value));
+  WriteBytes(FEncoding.GetBytes(FNewLine));
+end;
+
+procedure TStreamWriter.WriteLine(Value: Int64);
+begin
+  WriteBytes(FEncoding.GetBytes(IntToStr(Value) + FNewLine));
+end;
+
+procedure TStreamWriter.WriteLine(const aFormat: string; Args: array of const);
+begin
+  WriteBytes(FEncoding.GetBytes(Format(aFormat, Args) + FNewLine));
+end;
+
+procedure TStreamWriter.WriteLine(Value: TObject);
+begin
+  WriteBytes(FEncoding.GetBytes(Value.ToString + FNewLine));
+end;
+
+procedure TStreamWriter.WriteLine(Value: Single);
+begin
+  WriteBytes(FEncoding.GetBytes(FloatToStr(Value) + FNewLine));
+end;
+
+procedure TStreamWriter.WriteLine(const Value: string);
+begin
+  WriteBytes(FEncoding.GetBytes(Value + FNewLine));
+end;
+
+{$ENDIF FPC}
+
 {other functions}
 
 function CreateDummyFile(const aFilename : string; const aSize : Int64 ) : Boolean;
@@ -261,20 +775,12 @@ function FileSearchText(const aFileName, SearchText: string; caseSensitive : Boo
 const
   BufferSize = $8001;
 var
-  {$IF CompilerVersion < 20}
-    pBuf, pEnd, pScan, pPos: PChar;
-  {$ELSE}
-    pBuf, pEnd, pScan, pPos: PAnsiChar;
-  {$ENDIF}
+  pBuf, pEnd, pScan, pPos: PAnsiChar;
   filesize: LongInt;
   bytesRemaining: LongInt;
   bytesToRead: Integer;
   F: file;
-  {$IF CompilerVersion < 20}
-    SearchFor: PChar;
-  {$ELSE}
-    SearchFor: PAnsiChar;
-  {$ENDIF}
+  SearchFor: PAnsiChar;
   oldMode: Word;
 begin
   Result := -1;
@@ -287,13 +793,21 @@ begin
   Reset(F, 1);
   FileMode := oldMode;
   try
-    {$IF CompilerVersion < 20}
-      SearchFor := StrAlloc(Length(SearchText) + 1);
+    {$IFDEF FPC}
+    SearchFor := PChar(StrAlloc(Length(SearchText) + 1));
+    {$ELSE}
+    {$IFDEF DELPHI2010_UP}
+    SearchFor := PAnsiChar(StrAlloc(Length(SearchText) + 1));
     {$ELSE}
-      SearchFor := PAnsiChar(StrAlloc(Length(SearchText) + 1));
+      SearchFor := StrAlloc(Length(SearchText) + 1);
     {$ENDIF}
+    {$ENDIF FPC}
     StrPCopy(SearchFor, SearchText);
+    {$IFDEF FPC}
+    if not caseSensitive then UpperCase(SearchFor);
+    {$ELSE}
     if not caseSensitive then AnsiUpper(SearchFor);
+    {$ENDIF}
     GetMem(pBuf, BufferSize);
     filesize := System.Filesize(F);
     bytesRemaining := filesize;
@@ -308,7 +822,11 @@ begin
       pScan := pBuf;
       while pScan < pEnd do
       begin
+        {$IFDEF FPC}
+        if not caseSensitive then UpperCase(pScan);
+        {$ELSE}
         if not caseSensitive then AnsiUpper(pScan);
+        {$ENDIF}
         pPos := StrPos(pScan, SearchFor);
         if pPos <> nil then
         begin
@@ -341,7 +859,11 @@ var
   lft: TFileTime;
   h:   THandle;
 begin
+  {$IFDEF FPC}
+  h := FindFirstFile(PAnsiChar(aFileName), ffd);
+  {$ELSE}
   h := FindFirstFile(PChar(aFileName), ffd);
+  {$ENDIF}
   if (INVALID_HANDLE_VALUE <> h) then
   begin
     FindClose(h);
@@ -358,7 +880,11 @@ var
   lft: TFileTime;
   h:   THandle;
 begin
-  h := FindFirstFile(PChar(aFilename), ffd);
+  {$IFDEF FPC}
+  h := FindFirstFile(PAnsiChar(aFileName), ffd);
+  {$ELSE}
+  h := FindFirstFile(PChar(aFileName), ffd);
+  {$ENDIF}
   if (INVALID_HANDLE_VALUE <> h) then
   begin
     FindClose(h);
@@ -368,14 +894,18 @@ begin
   end;
 end;
 
-function GetLastModificationTime(const aFileName : string): TDateTime;
+function GetLastWriteTime(const aFileName : string): TDateTime;
 var
   ffd: TWin32FindData;
   dft: DWORD;
   lft: TFileTime;
   h:   THandle;
 begin
-  h := FindFirstFile(PChar(aFilename), ffd);
+  {$IFDEF FPC}
+  h := FindFirstFile(PAnsiChar(aFileName), ffd);
+  {$ELSE}
+  h := FindFirstFile(PChar(aFileName), ffd);
+  {$ENDIF}
   if (INVALID_HANDLE_VALUE <> h) then
   begin
     FindClose(h);
@@ -385,4 +915,162 @@ begin
   end;
 end;
 
+{$IFDEF FPC}
+function FindDelimiter(const Delimiters, S: string; StartIdx: Integer = 1): Integer;
+var
+  Stop: Boolean;
+  Len: Integer;
+begin
+  Result := 0;
+
+  Len := S.Length;
+  Stop := False;
+  while (not Stop) and (StartIdx <= Len) do
+    if IsDelimiter(Delimiters, S, StartIdx) then
+    begin
+      Result := StartIdx;
+      Stop := True;
+    end
+    else
+      Inc(StartIdx);
+end;
+{$ENDIF}
+
+{$IFDEF MSWINDOWS}
+function ConvertDateTimeToFileTime(const DateTime: TDateTime; const UseLocalTimeZone: Boolean): TFileTime;
+var
+  LFileTime: TFileTime;
+  SysTime: TSystemTime;
+begin
+  Result.dwLowDateTime := 0;
+  Result.dwLowDateTime := 0;
+  DecodeDateTime(DateTime, SysTime.wYear, SysTime.wMonth, SysTime.wDay,
+    SysTime.wHour, SysTime.wMinute, SysTime.wSecond, SysTime.wMilliseconds);
+
+  if SystemTimeToFileTime(SysTime, LFileTime) then
+    if UseLocalTimeZone then
+      LocalFileTimeToFileTime(LFileTime, Result)
+    else
+      Result := LFileTime;
+end;
+{$ENDIF}
+{$IFDEF POSIX}
+class function TDirectory.ConvertDateTimeToFileTime(const DateTime: TDateTime;
+  const UseLocalTimeZone: Boolean): time_t;
+begin
+  { Use the time zone if necessary }
+  if not UseLocalTimeZone then
+    Result := DateTimeToFileDate(TTimeZone.Local.ToLocalTime(DateTime))
+  else
+    Result := DateTimeToFileDate(DateTime);
+end;
+{$ENDIF}
+
+procedure SetDateTimeInfo(const Path: string; const CreationTime, LastAccessTime, LastWriteTime: PDateTime; const UseLocalTimeZone: Boolean);
+{$IFDEF MSWINDOWS}
+var
+  LFileHnd: THandle;
+  LFileAttr: Cardinal;
+  LFileCreationTime: PFileTime;
+  LFileLastAccessTime: PFileTime;
+  LFileLastWriteTime: PFileTime;
+begin
+  // establish what date-times must be set to the directory
+  LFileHnd := 0;
+  LFileCreationTime := nil;
+  LFileLastAccessTime := nil;
+  LFileLastWriteTime := nil;
+
+  try
+    try
+      if Assigned(CreationTime) then
+      begin
+        New(LFileCreationTime);
+        LFileCreationTime^ := ConvertDateTimeToFileTime(CreationTime^, UseLocalTimeZone);
+      end;
+      if Assigned(LastAccessTime) then
+      begin
+        New(LFileLastAccessTime);
+        LFileLastAccessTime^ := ConvertDateTimeToFileTime(LastAccessTime^, UseLocalTimeZone);
+      end;
+      if Assigned(LastWriteTime) then
+      begin
+        New(LFileLastWriteTime);
+        LFileLastWriteTime^ := ConvertDateTimeToFileTime(LastWriteTime^, UseLocalTimeZone);
+      end;
+
+      // determine if Path points to a directory or a file
+      SetLastError(ERROR_SUCCESS);
+      LFileAttr := FileGetAttr(Path);
+      if LFileAttr and faDirectory <> 0 then
+        LFileAttr := FILE_FLAG_BACKUP_SEMANTICS
+      else
+        LFileAttr := FILE_ATTRIBUTE_NORMAL;
+
+      // set the new date-times to the directory or file
+      LFileHnd := CreateFile(PChar(Path), GENERIC_WRITE, FILE_SHARE_WRITE, nil,
+        OPEN_EXISTING, LFileAttr, 0);
+
+      if LFileHnd <> INVALID_HANDLE_VALUE then
+        SetFileTime(LFileHnd, LFileCreationTime, LFileLastAccessTime, LFileLastWriteTime);
+    except
+      on E: EConvertError do
+        raise EArgumentOutOfRangeException.Create(E.Message);
+    end;
+  finally
+    CloseHandle(LFileHnd);
+    SetLastError(ERROR_SUCCESS);
+
+    Dispose(LFileCreationTime);
+    Dispose(LFileLastAccessTime);
+    Dispose(LFileLastWriteTime);
+  end;
+end;
+{$ENDIF}
+{$IFDEF POSIX}
+var
+  LFileName: Pointer;
+  LStatBuf: _stat;
+  LBuf: utimbuf;
+  ErrCode: Integer;
+  M: TMarshaller;
+begin
+  { Do nothing if no date/time passed. Ignore CreationTime. Unixes do not support creation times for files. }
+  if (LastAccessTime = nil) and (LastWriteTime = nil) then
+    Exit;
+
+  LFileName := M.AsAnsi(Path, CP_UTF8).ToPointer;
+
+  { Obtain the file times. lstat may fail }
+  if ((LastAccessTime = nil) or (LastWriteTime = nil)) then
+  begin
+    ErrCode := stat(LFileName, LStatBuf);
+
+    { Fail if we can't access the file properly }
+    if ErrCode <> 0 then
+      Exit; // Fail here prematurely. Do not chnage file times if we failed to fetch the old ones.
+  end;
+
+  try
+    { Preserve of set the new value }
+    if LastAccessTime <> nil then
+      LBuf.actime := ConvertDateTimeToFileTime(LastAccessTime^, UseLocalTimeZone)
+    else
+      LBuf.actime := LStatBuf.st_atime;
+
+    { Preserve of set the new value }
+    if LastWriteTime <> nil then
+      LBuf.modtime := ConvertDateTimeToFileTime(LastWriteTime^, UseLocalTimeZone)
+    else
+      LBuf.modtime := LStatBuf.st_mtime;
+
+    { Call utime to set the file times }
+    utime(LFileName, LBuf);
+  except
+    on E: EConvertError do // May rise in ConvertDateTimeToFileTime
+      raise EArgumentOutOfRangeException.Create(E.Message);
+  end;
+end;
+{$ENDIF}
+
 end.

+ 5 - 3
Quick.Format.pas

@@ -5,9 +5,9 @@
   Unit        : Quick.Format
   Description : String Format functions
   Author      : Kike Pérez
-  Version     : 1.2
+  Version     : 1.4
   Created     : 14/07/2017
-  Modified    : 14/03/2018
+  Modified    : 07/04/2018
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -29,10 +29,12 @@
 
 unit Quick.Format;
 
+{$i QuickLib.inc}
+
 interface
 
 uses
-  System.SysUtils,
+  SysUtils,
   Math;
 
   //converts a number to thousand delimeter string

+ 3 - 3
Quick.JSONUtils.pas

@@ -34,7 +34,7 @@ interface
 uses
   Classes,
   System.SysUtils,
-  {$IF CompilerVersion >= 32.0}
+  {$IFDEF DELPHIRX102_UP}
     JSON.Types,
     REST.Json,
     System.JSON,
@@ -62,14 +62,14 @@ type
 implementation
 
 function TObjectHelper.ToJSON : string;
-{$IF CompilerVersion >= 32.0}
+{$IFDEF DELPHIRX102_UP}
 var
     Serializer : TJsonSerializer;
   {$ENDIF}
 begin
   Result := '';
   try
-    {$IF CompilerVersion >= 32.0}
+    {$IFDEF DELPHIRX102_UP}
       Serializer := TJsonSerializer.Create;
       try
         Serializer.Formatting := TJsonFormatting.Indented;

+ 24 - 11
Quick.Log.pas

@@ -5,9 +5,9 @@
   Unit        : Quick.Log
   Description : Threadsafe Log
   Author      : Kike Pérez
-  Version     : 1.17
+  Version     : 1.18
   Created     : 10/04/2016
-  Modified    : 18/01/2018
+  Modified    : 08/04/2018
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -29,14 +29,20 @@
 
 unit Quick.Log;
 
+{$i QuickLib.inc}
+
 interface
 
 uses
   Windows,
   Classes,
   Quick.Commons,
-  System.SysUtils,
-  System.IOUtils;
+  {$ifndef FPC}
+  System.IOUtils,
+  {$else}
+  Quick.Files,
+  {$endif}
+  SysUtils;
 
 type
 
@@ -79,8 +85,8 @@ type
     constructor Create;
     destructor Destroy; override;
     function SetLog(logname : string; AddCurrentDateToFileName : Boolean; LimitSizeInMB : Integer = 0) : Boolean;
-    procedure Add(const cMsg : string; cEventType : TLogEventType = etInfo); overload;
-    procedure Add(const cFormat : string; cParams : array of TVarRec ; cEventType : TLogEventType = etInfo); overload;
+    procedure Add(const cMsg : string; cEventType : TLogEventType = TLogEventType.etInfo); overload;
+    procedure Add(const cFormat : string; cParams : array of TVarRec ; cEventType : TLogEventType = TLogEventType.etInfo); overload;
   end;
 
 var
@@ -145,6 +151,13 @@ begin
   else Result := fLogFileName;
 end;
 
+{$IFDEF FPC}
+function OSVersion: String;
+begin
+  Result:={$I %FPCTARGETOS%}+'-'+{$I %FPCTARGETCPU%};
+end;
+{$ENDIF}
+
 function TQuickLog.SetLog(logname : string; AddCurrentDateToFileName : Boolean; LimitSizeInMB : Integer = 0) : Boolean;
 begin
   if logname = '' then logname := TPath.GetDirectoryName(ParamStr(0)) + '\' + TPath.GetFileNameWithoutExtension(ParamStr(0)) + '.log';
@@ -154,7 +167,7 @@ begin
   fLogFileName := logname;
   //Checks if logfile is too big and deletes
   fLimitLogSize := LimitSizeInMB * 1024 * 1024;
-  if (fLimitLogSize > 0) and (TFile.Exists(logname,True)) then
+  if (fLimitLogSize > 0) and (TFile.Exists(logname)) then
   begin
     try
       fCurrentLogSize := TFile.GetSize(logname);
@@ -174,7 +187,7 @@ begin
       Self.WriteLog(Format('Application : %s %s',[ExtractFilenameWithoutExt(ParamStr(0)),GetAppVersionFullStr]));
       Self.WriteLog(Format('Path        : %s',[ExtractFilePath(ParamStr(0))]));
       Self.WriteLog(Format('CPU cores   : %d',[CPUCount]));
-      Self.WriteLog(Format('OS version  : %s',[TOSVersion.ToString]));
+      Self.WriteLog(Format('OS version  : %s',{$IFDEF FPC}[OSVersion]{$ELSE}[TOSVersion.ToString]{$ENDIF}));
       Self.WriteLog(Format('Host        : %s',[GetComputerName]));
       Self.WriteLog(Format('Username    : %s',[Trim(GetLoggedUserName)]));
       Self.WriteLog(Format('Started     : %s',[NowStr]));
@@ -190,7 +203,7 @@ begin
   Result := True;
 end;
 
-procedure TQuickLog.Add(const cMsg : string; cEventType : TLogEventType = etInfo);
+procedure TQuickLog.Add(const cMsg : string; cEventType : TLogEventType = TLogEventType.etInfo);
 begin
   //Check Log Verbose level
   if cEventType in fVerbose then
@@ -222,7 +235,7 @@ begin
     LBuffer := LEncoding.Convert(LEncoding, DestEncoding, LBuffer,
                                   LOffset, Length(LBuffer) - LOffset);
 
-    if TFile.Exists(logname,True) then
+    if TFile.Exists(logname) then
     begin
       stream := TFileStream.Create(logname, fmOpenReadWrite or fmShareDenyWrite);
       stream.Position := stream.Size;
@@ -261,7 +274,7 @@ begin
   end;
 end;
 
-procedure TQuickLog.Add(const cFormat : string; cParams : array of TVarRec ; cEventType : TLogEventType = etInfo);
+procedure TQuickLog.Add(const cFormat : string; cParams : array of TVarRec ; cEventType : TLogEventType = TLogEventType.etInfo);
 begin
   Self.Add(Format(cFormat,cParams),cEventType);
 end;

+ 4 - 3
Quick.Network.pas

@@ -1,13 +1,13 @@
 { ***************************************************************************
 
-  Copyright (c) 2015-2017 Kike Pérez
+  Copyright (c) 2015-2018 Kike Pérez
 
   Unit        : Quick.Network
   Description : Network related functions
   Author      : Kike Pérez
-  Version     : 1.2
+  Version     : 1.4
   Created     : 11/07/2017
-  Modified    : 09/10/2017
+  Modified    : 07/04/2018
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -29,6 +29,7 @@
 
 unit Quick.Network;
 
+{$i QuickLib.inc}
 
 interface
 

+ 48 - 9
Quick.Process.pas

@@ -5,9 +5,9 @@
   Unit        : Quick.Process
   Description : Process functions
   Author      : Kike Pérez
-  Version     : 1.2
+  Version     : 1.4
   Created     : 14/07/2017
-  Modified    : 22/01/2018
+  Modified    : 07/04/2018
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -29,6 +29,8 @@
 
 unit Quick.Process;
 
+{$i QuickLib.inc}
+
 interface
 
 uses
@@ -38,11 +40,16 @@ uses
   Vcl.Forms,
   VCL.Controls,
   {$ENDIF}
-  System.DateUtils,
+  DateUtils,
+  {$IFNDEF FPC}
   TlHelp32,
   psapi,
-  System.SysUtils,
-  Winapi.ShellAPI,
+  {$ELSE}
+  JwaTlHelp32,
+  Process,
+  {$ENDIF}
+  SysUtils,
+  ShellAPI,
   Quick.Commons;
 
 
@@ -65,12 +72,14 @@ uses
   //executes an aplication and wait for terminate
   function ExecuteAndWait(const aFilename, aCommandLine: string): Boolean;
   function ShellExecuteAndWait(const aOperation, aFileName, aParameter, aDirectory : string; aShowMode : Word; aWaitForTerminate: Boolean) : LongInt;
+  {$IFNDEF FPC}
   //execute an application and return handle
   function ShellExecuteReturnHandle(const aOperation, aFileName, aParameters, aWorkingDir : string; aShowMode: Integer) : THandle;
+  {$ENDIF}
   //find an open main window handle
   function FindMainWindow(PID: DWord): DWord;
   //wait for a time period to find an opened main window handle
-  function FindMainWindowTimeout(ProcHND : THandle; TimeoutSecs : Integer = 20) : THandle; overload
+  function FindMainWindowTimeout(ProcHND : THandle; TimeoutSecs : Integer = 20) : THandle; overload;
   //wait for a time period to find an opened window handle
   function FindWindowTimeout(const aWindowsName : string; TimeoutMSecs : Integer = 1000) : THandle;
   {$IFNDEF CONSOLE}
@@ -106,6 +115,7 @@ begin
   if not Result then einfo.HWND := hwnd;
 end;
 
+{$IFNDEF FPC}
 function CreateWin9xProcessList : TStringList;
 var
   hSnapShot: THandle;
@@ -166,6 +176,25 @@ begin
     VER_PLATFORM_WIN32_NT : Result := CreateWinNTProcessList;
   end
 end;
+{$ELSE}
+function GetProcessList : TStringList;
+var
+  pr : THandle;
+  pe: TProcessEntry32;
+begin
+  Result := TStringList.Create;
+  pr := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
+  try
+    pe.dwSize := SizeOf(pe);
+    if Process32First(pr,pe) then
+    begin
+      while Process32Next(pr,pe) do Result.Add(pe.szExeFile);
+    end;
+  finally
+    CloseHandle(pr);
+  end;
+end;
+{$ENDIF}
 
 function KillProcess(const aFileName: string): Integer;
 const
@@ -221,7 +250,11 @@ begin
   shinfo.lpFile := PChar(aFilename);
   if aParameters <> '' then shinfo.lpParameters := PChar(aParameters);
   shinfo.nShow := SW_SHOWNORMAL;
+  {$IFDEF FPC}
+  Result := ShellExecuteExW(@shinfo);
+  {$ELSE}
   Result := ShellExecuteEx(@shinfo);
+  {$ENDIF}
 end;
 
 procedure RemoveDeadIcons;
@@ -393,7 +426,11 @@ begin
   shinfo.lpParameters := PChar(aParameter);
   shinfo.lpDirectory := PChar(aDirectory);
   shinfo.nShow := aShowMode;
+  {$IFDEF FPC}
+  done := Boolean(ShellExecuteExW(@shinfo));
+  {$ELSE}
   done := Boolean(ShellExecuteEx(@shinfo));
+  {$ENDIF}
   if done then
   begin
     if aWaitForTerminate then
@@ -413,6 +450,7 @@ begin
   if not done then Result := -1;
 end;
 
+{$IFNDEF FPC}
 function ShellExecuteReturnHandle(const aOperation, aFileName, aParameters, aWorkingDir : string; aShowMode: Integer) : THandle;
 var
   exInfo: TShellExecuteInfo;
@@ -432,8 +470,9 @@ begin
     nShow := aShowMode;
   end;
   if ShellExecuteEx(@exInfo) then Ph := exInfo.hProcess;
-  Result := Winapi.Windows.GetProcessId(exInfo.hProcess);
+  Result := Windows.GetProcessId(exInfo.hProcess);
 End;
+{$ENDIF}
 
 function FindMainWindow(PID : DWord): DWORD;
 var
@@ -468,7 +507,7 @@ var
 begin
   startime := Now();
   repeat
-    Result := FindWindow(0,PWideChar(aWindowsName));
+    Result := FindWindow(0,{$IFDEF FPC}PChar{$ELSE}PWideChar{$ENDIF}(aWindowsName));
     {$IFDEF CONSOLE}
     ProcessMessages;
     {$ELSE}
@@ -501,4 +540,4 @@ begin
 end;
 {$ENDIF}
 
-end.
+end.

+ 3 - 1
Quick.SMTP.pas

@@ -31,9 +31,11 @@ unit Quick.SMTP;
 
 interface
 
+{$i QuickLib.inc}
+
 uses
   Classes,
-  System.SysUtils,
+  SysUtils,
   IdGlobal,
   IdSMTP,
   IdMessage,

+ 21 - 7
Quick.Service.pas

@@ -5,9 +5,9 @@
   Unit        : Quick.Service
   Description : Service functions
   Author      : Kike Pérez
-  Version     : 1.0
+  Version     : 1.1
   Created     : 14/07/2017
-  Modified    : 14/03/2018
+  Modified    : 07/04/2018
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -30,12 +30,18 @@ unit Quick.Service;
 
 interface
 
+{$i QuickLib.inc}
+
 uses
-  System.SysUtils,
-  Winapi.Windows,
-  Winapi.WinSvc,
-  Winapi.Messages,
+  SysUtils,
+  Windows,
+  {$IFNDEF FPC}
+  Messages,
+  WinSvc,
   System.IOUtils,
+  {$ELSE}
+  Quick.Files,
+  {$ENDIF}
   Quick.Commons,
   Quick.Process;
 
@@ -121,7 +127,11 @@ var
   smanHnd : SC_HANDLE;
   svcHnd : SC_HANDLE;
   svcStatus : TServiceStatus;
+  {$IFDEF FPC}
+  psTemp : LPPCSTR;
+  {$ELSE}
   psTemp : PChar;
+  {$ENDIF}
   dwChkP : DWord;
 begin
   svcStatus.dwCurrentState := 0;
@@ -208,7 +218,11 @@ begin
       if svchnd > 0 then
       begin
         try
-          Winapi.WinSVC.DeleteService(svchnd);
+          {$IFDEF FPC}
+          DeleteServiceEx(aServiceName);
+          {$ELSE}
+          WinSVC.DeleteService(svchnd);
+          {$ENDIF}
           Result := True;
         finally
           CloseServiceHandle(svchnd);

+ 150 - 15
Quick.Threads.pas

@@ -5,9 +5,9 @@
   Unit        : Quick.Threads
   Description : Thread safe collections
   Author      : Kike Pérez
-  Version     : 1.0
+  Version     : 1.2
   Created     : 09/03/2018
-  Modified    : 12/03/2018
+  Modified    : 07/04/2018
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -29,14 +29,24 @@
 
 unit Quick.Threads;
 
+{$i QuickLib.inc}
+
 interface
 
 uses
   Classes,
   Types,
+  //Quick.Chrono,
+  {$IFNDEF FPC}
   System.RTLConsts,
   System.Generics.Collections,
   System.SyncObjs;
+  {$ELSE}
+  RtlConsts,
+  Generics.Collections,
+  syncobjs,
+  SysUtils;
+  {$ENDIF}
 
 type
 
@@ -45,7 +55,11 @@ type
     FQueue: array of T;
     FQueueSize, FQueueOffset: Integer;
     FQueueLock: TCriticalSection;
+    {$IFDEF FPC}
+    FQueueCondVar : TEventObject;
+    {$ELSE}
     FQueueCondVar: TConditionVariableCS;
+    {$ENDIF}
     FShutDown: Boolean;
     FPushTimeout, FPopTimeout: Cardinal;
     FTotalItemsPushed, FTotalItemsPopped: Cardinal;
@@ -73,7 +87,11 @@ type
     fQueue : TQueue<T>;
     fQueueSize : Integer;
     fQueueLock : TCriticalSection;
-    fQueueCondVar: TConditionVariableCS;
+    {$IFDEF FPC}
+    FQueueCondVar : TSimpleEvent;
+    {$ELSE}
+    FQueueCondVar: TConditionVariableCS;
+    {$ENDIF}
     fShutDown : Boolean;
     fPushTimeout : Cardinal;
     fPopTimeout : Cardinal;
@@ -117,6 +135,7 @@ type
     procedure Start;
   end;
 
+  {$IFNDEF FPC}
   TThreadObjectList<T: class> = class(TList<T>)
     private
       fList: TObjectList<T>;
@@ -136,6 +155,7 @@ type
       procedure UnlockList; inline;
       property Duplicates: TDuplicates read fDuplicates write fDuplicates;
   end;
+  {$ENDIF}
 
 implementation
 
@@ -146,7 +166,11 @@ begin
   inherited Create;
   SetLength(FQueue, AQueueDepth);
   FQueueLock := TCriticalSection.Create;
+  {$IFDEF FPC}
+  FQueueCondVar := TEventObject.Create(nil, True, False, 'TQCS');
+  {$ELSE}
   FQueueCondVar := TConditionVariableCS.Create;
+  {$ENDIF}
   FPushTimeout := PushTimeout;
   FPopTimeout := PopTimeout;
 end;
@@ -167,7 +191,11 @@ begin
   finally
     FQueueLock.Leave;
   end;
+  {$IFDEF FPC}
+  FQueueCondVar.SetEvent;
+  {$ELSE}
   FQueueCondVar.ReleaseAll;
+  {$ENDIF}
 end;
 
 function TThreadedQueueCS<T>.PopItem: T;
@@ -185,7 +213,11 @@ begin
     Result := wrSignaled;
     while (Result = wrSignaled) and (FQueueSize = 0) and not FShutDown do
     begin
+      {$IFDEF FPC}
+      Result := FQueueCondVar.WaitFor(FPopTimeout);
+      {$ELSE}
       Result := FQueueCondVar.WaitFor(FQueueLock, FPopTimeout);
+      {$ENDIF}
     end;
 
     if (FShutDown and (FQueueSize = 0)) or (Result <> wrSignaled) then Exit;
@@ -194,7 +226,14 @@ begin
 
     FQueue[FQueueOffset] := Default(T);
 
-    if FQueueSize = Length(FQueue) then FQueueCondVar.ReleaseAll;
+    if FQueueSize = Length(FQueue) then
+    begin
+      {$IFDEF FPC}
+      FQueueCondVar.SetEvent;
+      {$ELSE}
+      FQueueCondVar.ReleaseAll;
+      {$ENDIF}
+    end;
 
     Dec(FQueueSize);
     Inc(FQueueOffset);
@@ -233,12 +272,23 @@ begin
     Result := wrSignaled;
     while (Result = wrSignaled) and (FQueueSize = Length(FQueue)) and not FShutDown do
     begin
+      {$IFDEF FPC}
+      Result := FQueueCondVar.WaitFor(FPushTimeout);
+      {$ELSE}
       Result := FQueueCondVar.WaitFor(FQueueLock, FPushTimeout);
+      {$ENDIF}
     end;
 
     if FShutDown or (Result <> wrSignaled) then Exit;
 
-    if FQueueSize = 0 then FQueueCondVar.ReleaseAll;
+    if FQueueSize = 0 then
+    begin
+      {$IFDEF FPC}
+      FQueueCondVar.SetEvent;
+      {$ELSE}
+      FQueueCondVar.ReleaseAll;
+      {$ENDIF}
+    end;
 
     FQueue[(FQueueOffset + FQueueSize) mod Length(FQueue)] := AItem;
     Inc(FQueueSize);
@@ -252,7 +302,11 @@ end;
 procedure TThreadedQueueCS<T>.DoShutDown;
 begin
   FShutDown := True;
+  {$IFDEF FPC}
+  FQueueCondVar.SetEvent;
+  {$ELSE}
   FQueueCondVar.ReleaseAll;
+  {$ENDIF}
 end;
 
 { TThreadedQueueList<T> }
@@ -264,7 +318,11 @@ begin
   fQueue.Capacity := AQueueDepth;
   fQueueSize := 0;
   fQueueLock := TCriticalSection.Create;
+  {$IFDEF FPC}
+  FQueueCondVar := TSimpleEvent.Create; //TEventObject.Create(nil, False, False, 'TQL');
+  {$ELSE}
   fQueueCondVar := TConditionVariableCS.Create;
+  {$ENDIF}
   fPushTimeout := PushTimeout;
   fPopTimeout := PopTimeout;
 end;
@@ -286,7 +344,11 @@ begin
   finally
     fQueueLock.Leave;
   end;
-  fQueueCondVar.ReleaseAll;
+  {$IFDEF FPC}
+  FQueueCondVar.SetEvent;
+  {$ELSE}
+  FQueueCondVar.ReleaseAll;
+  {$ENDIF}
 end;
 
 function TThreadedQueueList<T>.PopItem: T;
@@ -296,6 +358,42 @@ begin
   PopItem(LQueueSize, Result);
 end;
 
+{$IFDEF FPC}
+function TThreadedQueueList<T>.PopItem(var AQueueSize: Integer; var AItem: T): TWaitResult;
+//var
+  //crono : TChronometer;
+begin
+  AItem := Default(T);
+  //crono := TChronometer.Create(False);
+  try
+    Result := wrSignaled;
+    //writeln('popitem');
+    //crono.Start;
+    while (Result = wrSignaled) and (fQueueSize = 0) and not fShutDown do
+    begin
+      //crono.Start;
+      Result := FQueueCondVar.WaitFor(FPopTimeout);
+      //crono.Stop;
+      //writeln('in: '  + crono.ElapsedTime);
+      //if result = twaitresult.wrError then result := twaitresult.wrError;
+    end;
+    //crono.Stop;
+    //writeln('out: ' + crono.ElapsedTime);
+
+    fQueueLock.Enter;
+    try
+      if (FShutDown and (fQueueSize = 0)) or (Result <> wrSignaled) then Exit;
+      AItem := fQueue.Extract;
+      Dec(FQueueSize);
+      Inc(fTotalItemsPopped);
+    finally
+      fQueueLock.Leave;
+    end;
+  finally
+    AQueueSize := fQueueSize;
+  end;
+end;
+{$ELSE}
 function TThreadedQueueList<T>.PopItem(var AQueueSize: Integer; var AItem: T): TWaitResult;
 begin
   AItem := Default(T);
@@ -304,14 +402,17 @@ begin
     Result := wrSignaled;
     while (Result = wrSignaled) and (fQueueSize = 0) and not fShutDown do
     begin
-      Result := fQueueCondVar.WaitFor(fQueueLock, fPopTimeout);
+      Result := FQueueCondVar.WaitFor(FQueueLock, FPopTimeout);
     end;
 
     if (FShutDown and (fQueueSize = 0)) or (Result <> wrSignaled) then Exit;
 
     AItem := fQueue.Extract;
 
-    if fQueueSize = fQueue.Count then fQueueCondVar.ReleaseAll;
+    if fQueueSize = fQueue.Count then
+    begin
+      FQueueCondVar.ReleaseAll;
+    end;
 
     Dec(FQueueSize);
     Inc(fTotalItemsPopped);
@@ -320,6 +421,7 @@ begin
     fQueueLock.Leave;
   end;
 end;
+{$ENDIF}
 
 function TThreadedQueueList<T>.PopItem(var AItem: T): TWaitResult;
 var
@@ -340,6 +442,34 @@ begin
   Result := PushItem(AItem, LQueueSize);
 end;
 
+{$IFDEF FPC}
+function TThreadedQueueList<T>.PushItem(const AItem: T; var AQueueSize: Integer): TWaitResult;
+begin
+  FQueueLock.Enter;
+  try
+    Result := wrSignaled;
+    //while (Result = wrSignaled) and (fQueueSize = fQueue.Count) and not fShutDown do
+    //begin
+    //  Result := fQueueCondVar.WaitFor(fQueueLock, fPushTimeout);
+    //end;
+
+    if fShutDown or (Result <> wrSignaled) then Exit;
+
+    //if fQueueSize = 0 then
+    //begin
+    //  FQueueCondVar.SetEvent;
+    //end;
+
+    fQueue.Enqueue(AItem);
+    Inc(FQueueSize);
+    Inc(fTotalItemsPushed);
+  finally
+    AQueueSize := fQueueSize;
+    FQueueLock.Leave;
+    //FQueueCondVar.SetEvent;
+  end;
+end;
+{$ELSE}
 function TThreadedQueueList<T>.PushItem(const AItem: T; var AQueueSize: Integer): TWaitResult;
 begin
   FQueueLock.Enter;
@@ -352,7 +482,7 @@ begin
 
     if fShutDown or (Result <> wrSignaled) then Exit;
 
-    if fQueueSize = 0 then fQueueCondVar.ReleaseAll;
+    if fQueueSize = 0 then FQueueCondVar.ReleaseAll;
 
     fQueue.Enqueue(AItem);
     Inc(FQueueSize);
@@ -363,10 +493,16 @@ begin
   end;
 end;
 
+{$ENDIF}
+
 procedure TThreadedQueueList<T>.DoShutDown;
 begin
   fShutDown := True;
-  fQueueCondVar.ReleaseAll;
+  {$IFDEF FPC}
+  FQueueCondVar.SetEvent;
+  {$ELSE}
+  FQueueCondVar.ReleaseAll;
+  {$ENDIF}
 end;
 
 { TThreadTask<T> }
@@ -407,17 +543,15 @@ begin
   fTaskQueue := TThreadedQueueCS<T>.Create(fMaxQueue,fInsertTimeout,fExtractTimeout);
 end;
 
+{$IFNDEF FPC}
 { TThreadObjectList<T> }
 
 procedure TThreadObjectList<T>.Add(const Item: T);
 begin
   LockList;
   try
-    if (Duplicates = dupAccept) or
-       (fList.IndexOf(Item) = -1) then
-      fList.Add(Item)
-    else if Duplicates = dupError then
-      raise EListError.CreateFmt(SDuplicateItem, [fList.ItemValue(Item)]);
+    if (Duplicates = dupAccept) or (fList.IndexOf(Item) = -1) then fList.Add(Item)
+    else if Duplicates = dupError then raise EListError.CreateFmt(SDuplicateItem, [fList.ItemValue(Item)]);
   finally
     UnlockList;
   end;
@@ -498,5 +632,6 @@ procedure TThreadObjectList<T>.UnlockList;
 begin
   System.TMonitor.Exit(fLock);
 end;
+{$ENDIF}
 
 end.

+ 142 - 0
QuickLib.inc

@@ -0,0 +1,142 @@
+{
+    This file is part of QuickLib: https://github.com/exilon/QuickLib
+
+    QuickLibs. Copyright (C) 2018 Kike Pérez
+      Exilon - https://www.exilon.es
+
+     ***************************************************************************
+
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+
+     ***************************************************************************
+}
+
+{$ifdef FPC}
+  {$MODE DELPHI}
+
+  {$INLINE ON}
+  {$define HASINLINE}
+
+  {$ifdef ANDROID}
+    {$define LINUX}
+  {$endif}
+
+  {$ifdef VER2_7}
+    {$define ISFPC27}
+  {$endif}
+
+  {$ifdef VER3_0}
+    {$define ISFPC27}
+    {$define ISFPC30}
+  {$endif}
+
+  {$ifdef VER3_1}
+    {$define ISFPC27}
+    {$define ISFPC30}
+  {$endif}
+
+  {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+    {$define FPC_ENUMHASINNER}
+  {$endif}
+
+  {$ifdef FPC_HAS_MANAGEMENT_OPERATORS}
+    {$define ISDELPHI2006ANDUP}
+  {$endif FPC_HAS_MANAGEMENT_OPERATORS}
+
+{$else FPC}
+
+  {$ifdef CONDITIONALEXPRESSIONS} //Delphi 6 or newer
+    {$define HASINTERFACERTTI} //interface RTTI (not FPC)
+    {$ifndef LINUX}
+      {$ifdef VER140}
+        {$define DELPHI6_UP} //Delphi 6 or newer
+      {$else}
+        {$define DELPHI7_UP} //Delphi 7 or newer
+      {$endif}
+    {$endif LINUX}
+    {$if CompilerVersion >= 17}
+      {$define DELPHI2005_UP} //Delphi 2005 or newer
+    {$ifend}
+    {$if CompilerVersion >= 18}
+      {$define DELPHI2006_UP} //Delphi 2006 or newer
+      {$define HASINLINE}
+    {$ifend}
+    {$if CompilerVersion > 18}
+      {$define DELPHI2007_UP} //Delphi 2007 or newer
+    {$ifend}
+    {$if CompilerVersion = 20}
+      {$define DELPHI2009_UP} //Delphi 2009
+    {$ifend}
+    {$if CompilerVersion >= 21.0} //Delphi 2010
+      {$define DELPHI2010_UP}
+      {$define FPC_OR_UNICODE}
+    {$ifend}
+    {$if CompilerVersion >= 22.0} //Delphi XE
+      {$define DELPHIXE_UP}
+    {$ifend}
+    {$if CompilerVersion >= 23.0} //Delphi XE2
+      {$define DELPHIXE2_UP}
+    {$ifend}
+    {$if CompilerVersion >= 24.0} //Delphi XE3
+      {$define DELPHIXE3_UP}
+    {$ifend}
+    {$if CompilerVersion >= 25.0} //Delphi XE4
+      {$define DELPHIXE4_UP}
+    {$ifend}
+    {$if CompilerVersion >= 26.0} //Delphi XE5
+      {$define DELPHIXE5_UP}
+    {$ifend}
+    {$if CompilerVersion >= 27.0} //Delphi XE6
+      {$define DELPHIXE6_UP}
+    {$ifend}
+    {$if CompilerVersion >= 28.0} //Delphi XE7
+      {$define DELPHIXE7_UP}
+    {$ifend}
+    {$if CompilerVersion >= 29.0} //Delphi XE8
+      {$define DELPHIXE8_UP}
+    {$ifend}
+    {$if CompilerVersion >= 30.0} //Delphi XE10 Seattle
+      {$define DELPHIRX10_UP}
+	  {$define DELPHISEATTLE_UP}
+    {$ifend}
+    {$if CompilerVersion >= 31.0} //Delphi RX10.1 Berlin
+      {$define DELPHIRX101_UP}
+	  {$define DELPHIBERLIN_UP}
+    {$ifend}
+    {$if CompilerVersion >= 32.0} //Delphi RX10.2 Tokyo
+      {$define DELPHIRX102_UP}
+	  {$define DELPHITOKYO_UP}
+    {$ifend}
+  {$else}
+    //Delphi 5 or older
+    {$define DELPHI6OROLDER}
+    {$define DELPHI5OROLDER}
+    {$define DELPHI5ORFPC}
+    {$define MSWINDOWS}
+  {$endif}
+
+{$endif FPC}
+
+{$ifdef VER150}
+  {$WARN SYMBOL_DEPRECATED OFF}
+  {$WARN UNSAFE_TYPE OFF}
+  {$WARN UNSAFE_CODE OFF}
+  {$WARN UNSAFE_CAST OFF}
+{$ENDIF}
+
+{$ifdef CONDITIONALEXPRESSIONS}  //Delphi 6 or newer
+  {.$WARN SYMBOL_PLATFORM OFF}
+  {.$WARN UNIT_PLATFORM OFF}
+{$endif}
+
+

+ 1 - 2
README.md

@@ -6,8 +6,7 @@
 
 
 
-Small delphi library containing interesting and quick to implement functions, created to simplify application development.
-
+Small delphi/fpc library containing interesting and quick to implement functions, created to simplify application development.
 
 ----------
 **Quick.AppService:** Allow a console app to run as console mode or service mode with same code simplifying debug tasks.

+ 103 - 0
quicklib.lpk

@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <Package Version="4">
+    <PathDelim Value="\"/>
+    <Name Value="QuickLib"/>
+    <CompilerOptions>
+      <Version Value="11"/>
+      <PathDelim Value="\"/>
+      <SearchPaths>
+        <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+      </SearchPaths>
+      <Parsing>
+        <SyntaxOptions>
+          <SyntaxMode Value="DelphiUnicode"/>
+        </SyntaxOptions>
+      </Parsing>
+    </CompilerOptions>
+    <Version Major="1"/>
+    <Files Count="16">
+      <Item1>
+        <Filename Value="Quick.Console.pas"/>
+        <UnitName Value="Quick.Console"/>
+      </Item1>
+      <Item2>
+        <Filename Value="Quick.AppService.pas"/>
+        <UnitName Value="Quick.AppService"/>
+      </Item2>
+      <Item3>
+        <Filename Value="Quick.Base64.pas"/>
+        <UnitName Value="Quick.Base64"/>
+      </Item3>
+      <Item4>
+        <Filename Value="Quick.Chrono.pas"/>
+        <UnitName Value="Quick.Chrono"/>
+      </Item4>
+      <Item5>
+        <Filename Value="Quick.Commons.pas"/>
+        <UnitName Value="Quick.Commons"/>
+      </Item5>
+      <Item6>
+        <Filename Value="Quick.FileMonitor.pas"/>
+        <UnitName Value="Quick.FileMonitor"/>
+      </Item6>
+      <Item7>
+        <Filename Value="Quick.Files.pas"/>
+        <UnitName Value="Quick.Files"/>
+      </Item7>
+      <Item8>
+        <Filename Value="Quick.Format.pas"/>
+        <UnitName Value="Quick.Format"/>
+      </Item8>
+      <Item9>
+        <Filename Value="Quick.Log.pas"/>
+        <UnitName Value="Quick.Log"/>
+      </Item9>
+      <Item10>
+        <Filename Value="Quick.Network.pas"/>
+        <UnitName Value="Quick.Network"/>
+      </Item10>
+      <Item11>
+        <Filename Value="Quick.Process.pas"/>
+        <UnitName Value="Quick.Process"/>
+      </Item11>
+      <Item12>
+        <Filename Value="Quick.Service.pas"/>
+        <UnitName Value="Quick.Service"/>
+      </Item12>
+      <Item13>
+        <Filename Value="Quick.SMTP.pas"/>
+        <UnitName Value="Quick.SMTP"/>
+      </Item13>
+      <Item14>
+        <Filename Value="Quick.Threads.pas"/>
+        <UnitName Value="Quick.Threads"/>
+      </Item14>
+      <Item15>
+        <Filename Value="Quick.Config.pas"/>
+        <UnitName Value="Quick.Config"/>
+      </Item15>
+      <Item16>
+        <Filename Value="Quick.Config.Provider.Json.pas"/>
+        <UnitName Value="Quick.Config.Provider.Json"/>
+      </Item16>
+    </Files>
+    <RequiredPkgs Count="3">
+      <Item1>
+        <PackageName Value="jcl"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="indylaz"/>
+      </Item2>
+      <Item3>
+        <PackageName Value="FCL"/>
+      </Item3>
+    </RequiredPkgs>
+    <UsageOptions>
+      <UnitPath Value="$(PkgOutDir)"/>
+    </UsageOptions>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+  </Package>
+</CONFIG>

+ 18 - 0
quicklib.pas

@@ -0,0 +1,18 @@
+{ This file was automatically created by Lazarus. Do not edit!
+  This source is only used to compile and install the package.
+ }
+
+unit QuickLib;
+
+{$warn 5023 off : no warning about unused units}
+interface
+
+uses
+  Quick.Console, Quick.AppService, Quick.Base64, Quick.Chrono, Quick.Commons, 
+  Quick.FileMonitor, Quick.Files, Quick.Format, Quick.Log, Quick.Network, 
+  Quick.Process, Quick.Service, Quick.SMTP, Quick.Threads, Quick.Config, 
+  Quick.Config.Provider.Json;
+
+implementation
+
+end.

+ 0 - 1
samples/QuickConfig/Win32/Debug/prueba.json

@@ -1 +0,0 @@
-{"lastFilename":"notes.txt","windowPos":[100,0]}

+ 80 - 0
samples/delphi/QuickAppService/ConsoleAndService/MyServiceConsole.dpr

@@ -0,0 +1,80 @@
+program MyServiceConsole;
+
+{$APPTYPE CONSOLE}
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF}
+
+{$R *.res}
+
+uses
+  SysUtils,
+  Quick.Commons,
+  Quick.Console,
+  Quick.AppService;
+
+type
+
+  {$IFDEF FPC}
+  TSrvFactory = class
+    class procedure CreateMyService;
+  end;
+  {$ENDIF}
+
+  TMyService = class
+  public
+    procedure Execute;
+  end;
+
+  procedure TMyService.Execute;
+  begin
+    //your code
+  end;
+
+var
+
+  MyService : TMyService;
+
+{$IFDEF FPC}
+class procedure TSrvFactory.CreateMyService;
+begin
+ MyService := TMyService.Create;
+end;
+{$ENDIF}
+
+begin
+
+  try
+    if not AppService.IsRunningAsService then
+    begin
+      cout('Running in console mode',etInfo);
+      MyService := TMyService.Create;
+      MyService.Execute;
+      cout('Press [Enter] to exit',etInfo);
+      ConsoleWaitForEnterKey;
+      cout('Closing app...',etInfo);
+      MyService.Free;
+    end
+    else
+    begin
+        AppService.ServiceName := 'MyService';
+        AppService.DisplayName := 'MyServicesvc';
+        {$IFDEF FPC}
+        AppService.OnStart := TSrvFactory.CreateMyService;
+        {$ELSE}
+        //you can pass an anonymous method to events
+        AppService.OnStart := procedure
+                              begin
+                                MyService := TMyService.Create;
+                              end;
+        {$ENDIF}
+        AppService.OnExecute := MyService.Execute;
+        AppService.OnStop := MyService.Free;
+        AppService.CheckParams;
+    end;
+  except
+    on E: Exception do
+      Writeln(E.ClassName, ': ', E.Message);
+  end;
+end.

+ 589 - 0
samples/delphi/QuickAppService/ConsoleAndService/MyServiceConsole.dproj

@@ -0,0 +1,589 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <PropertyGroup>
+        <ProjectGuid>{1E7AA196-6865-4B02-9569-250A2B6BA91F}</ProjectGuid>
+        <MainSource>MyServiceConsole.dpr</MainSource>
+        <Base>True</Base>
+        <Config Condition="'$(Config)'==''">Debug</Config>
+        <TargetedPlatforms>1025</TargetedPlatforms>
+        <AppType>Console</AppType>
+        <FrameworkType>None</FrameworkType>
+        <ProjectVersion>18.4</ProjectVersion>
+        <Platform Condition="'$(Platform)'==''">Win32</Platform>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Android' and '$(Base)'=='true') or '$(Base_Android)'!=''">
+        <Base_Android>true</Base_Android>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='iOSDevice32' and '$(Base)'=='true') or '$(Base_iOSDevice32)'!=''">
+        <Base_iOSDevice32>true</Base_iOSDevice32>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='iOSSimulator' and '$(Base)'=='true') or '$(Base_iOSSimulator)'!=''">
+        <Base_iOSSimulator>true</Base_iOSSimulator>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
+        <Base_Win32>true</Base_Win32>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_1)'!=''">
+        <Cfg_1>true</Cfg_1>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_2)'!=''">
+        <Cfg_2>true</Cfg_2>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='iOSDevice32' and '$(Cfg_2)'=='true') or '$(Cfg_2_iOSDevice32)'!=''">
+        <Cfg_2_iOSDevice32>true</Cfg_2_iOSDevice32>
+        <CfgParent>Cfg_2</CfgParent>
+        <Cfg_2>true</Cfg_2>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='iOSDevice64' and '$(Cfg_2)'=='true') or '$(Cfg_2_iOSDevice64)'!=''">
+        <Cfg_2_iOSDevice64>true</Cfg_2_iOSDevice64>
+        <CfgParent>Cfg_2</CfgParent>
+        <Cfg_2>true</Cfg_2>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='iOSSimulator' and '$(Cfg_2)'=='true') or '$(Cfg_2_iOSSimulator)'!=''">
+        <Cfg_2_iOSSimulator>true</Cfg_2_iOSSimulator>
+        <CfgParent>Cfg_2</CfgParent>
+        <Cfg_2>true</Cfg_2>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base)'!=''">
+        <DCC_E>false</DCC_E>
+        <DCC_F>false</DCC_F>
+        <DCC_K>false</DCC_K>
+        <DCC_N>false</DCC_N>
+        <DCC_S>false</DCC_S>
+        <DCC_ImageBase>00400000</DCC_ImageBase>
+        <SanitizedProjectName>MyServiceConsole</SanitizedProjectName>
+        <VerInfo_Locale>3082</VerInfo_Locale>
+        <VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=</VerInfo_Keys>
+        <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
+        <Icon_MainIcon>$(BDS)\bin\delphi_PROJECTICON.ico</Icon_MainIcon>
+        <Icns_MainIcns>$(BDS)\bin\delphi_PROJECTICNS.icns</Icns_MainIcns>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_Android)'!=''">
+        <VerInfo_Keys>package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=</VerInfo_Keys>
+        <BT_BuildType>Debug</BT_BuildType>
+        <Android_LauncherIcon36>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png</Android_LauncherIcon36>
+        <Android_LauncherIcon48>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png</Android_LauncherIcon48>
+        <Android_LauncherIcon72>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png</Android_LauncherIcon72>
+        <Android_LauncherIcon96>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png</Android_LauncherIcon96>
+        <Android_LauncherIcon144>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png</Android_LauncherIcon144>
+        <Android_SplashImage426>$(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png</Android_SplashImage426>
+        <Android_SplashImage470>$(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png</Android_SplashImage470>
+        <Android_SplashImage640>$(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png</Android_SplashImage640>
+        <Android_SplashImage960>$(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png</Android_SplashImage960>
+        <AUP_ACCESS_COARSE_LOCATION>true</AUP_ACCESS_COARSE_LOCATION>
+        <AUP_ACCESS_FINE_LOCATION>true</AUP_ACCESS_FINE_LOCATION>
+        <AUP_CALL_PHONE>true</AUP_CALL_PHONE>
+        <AUP_CAMERA>true</AUP_CAMERA>
+        <AUP_INTERNET>true</AUP_INTERNET>
+        <AUP_READ_CALENDAR>true</AUP_READ_CALENDAR>
+        <AUP_READ_EXTERNAL_STORAGE>true</AUP_READ_EXTERNAL_STORAGE>
+        <AUP_WRITE_CALENDAR>true</AUP_WRITE_CALENDAR>
+        <AUP_WRITE_EXTERNAL_STORAGE>true</AUP_WRITE_EXTERNAL_STORAGE>
+        <AUP_READ_PHONE_STATE>true</AUP_READ_PHONE_STATE>
+        <EnabledSysJars>android-support-v4.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services-ads-7.0.0.dex.jar;google-play-services-analytics-7.0.0.dex.jar;google-play-services-base-7.0.0.dex.jar;google-play-services-identity-7.0.0.dex.jar;google-play-services-maps-7.0.0.dex.jar;google-play-services-panorama-7.0.0.dex.jar;google-play-services-plus-7.0.0.dex.jar;google-play-services-wallet-7.0.0.dex.jar</EnabledSysJars>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_iOSDevice32)'!=''">
+        <VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone &amp; iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera</VerInfo_Keys>
+        <VerInfo_UIDeviceFamily>iPhoneAndiPad</VerInfo_UIDeviceFamily>
+        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
+        <BT_BuildType>Debug</BT_BuildType>
+        <VerInfo_BundleId>$(MSBuildProjectName)</VerInfo_BundleId>
+        <iPhone_AppIcon60>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png</iPhone_AppIcon60>
+        <iPhone_AppIcon120>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png</iPhone_AppIcon120>
+        <iPhone_Spotlight40>$(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png</iPhone_Spotlight40>
+        <iPhone_Spotlight80>$(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png</iPhone_Spotlight80>
+        <iPad_SpotLight40>$(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png</iPad_SpotLight40>
+        <iPad_SpotLight80>$(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png</iPad_SpotLight80>
+        <iPad_AppIcon76>$(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png</iPad_AppIcon76>
+        <iPad_AppIcon152>$(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png</iPad_AppIcon152>
+        <iPad_Launch768x1024>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png</iPad_Launch768x1024>
+        <iPad_Launch1024x768>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png</iPad_Launch1024x768>
+        <iPad_Launch1536x2048>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png</iPad_Launch1536x2048>
+        <iPad_Launch2048x1536>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png</iPad_Launch2048x1536>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_iOSSimulator)'!=''">
+        <VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone &amp; iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera</VerInfo_Keys>
+        <VerInfo_UIDeviceFamily>iPhoneAndiPad</VerInfo_UIDeviceFamily>
+        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
+        <iPhone_AppIcon60>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png</iPhone_AppIcon60>
+        <iPhone_AppIcon120>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png</iPhone_AppIcon120>
+        <iPhone_Spotlight40>$(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png</iPhone_Spotlight40>
+        <iPhone_Spotlight80>$(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png</iPhone_Spotlight80>
+        <iPad_SpotLight40>$(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png</iPad_SpotLight40>
+        <iPad_SpotLight80>$(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png</iPad_SpotLight80>
+        <iPad_AppIcon76>$(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png</iPad_AppIcon76>
+        <iPad_AppIcon152>$(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png</iPad_AppIcon152>
+        <iPad_Launch768x1024>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png</iPad_Launch768x1024>
+        <iPad_Launch1024x768>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png</iPad_Launch1024x768>
+        <iPad_Launch1536x2048>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png</iPad_Launch1536x2048>
+        <iPad_Launch2048x1536>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png</iPad_Launch2048x1536>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_Win32)'!=''">
+        <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
+        <BT_BuildType>Debug</BT_BuildType>
+        <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)</VerInfo_Keys>
+        <VerInfo_Locale>1033</VerInfo_Locale>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_1)'!=''">
+        <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
+        <DCC_DebugInformation>0</DCC_DebugInformation>
+        <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
+        <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2)'!=''">
+        <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
+        <DCC_Optimize>false</DCC_Optimize>
+        <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2_iOSDevice32)'!=''">
+        <DCC_RemoteDebug>true</DCC_RemoteDebug>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2_iOSDevice64)'!=''">
+        <BT_BuildType>Debug</BT_BuildType>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2_iOSSimulator)'!=''">
+        <DCC_RemoteDebug>true</DCC_RemoteDebug>
+    </PropertyGroup>
+    <ItemGroup>
+        <DelphiCompile Include="$(MainSource)">
+            <MainSource>MainSource</MainSource>
+        </DelphiCompile>
+        <BuildConfiguration Include="Debug">
+            <Key>Cfg_2</Key>
+            <CfgParent>Base</CfgParent>
+        </BuildConfiguration>
+        <BuildConfiguration Include="Base">
+            <Key>Base</Key>
+        </BuildConfiguration>
+        <BuildConfiguration Include="Release">
+            <Key>Cfg_1</Key>
+            <CfgParent>Base</CfgParent>
+        </BuildConfiguration>
+    </ItemGroup>
+    <ProjectExtensions>
+        <Borland.Personality>Delphi.Personality.12</Borland.Personality>
+        <Borland.ProjectType/>
+        <BorlandProject>
+            <Delphi.Personality>
+                <Source>
+                    <Source Name="MainSource">MyServiceConsole.dpr</Source>
+                </Source>
+            </Delphi.Personality>
+            <Platforms>
+                <Platform value="Android">False</Platform>
+                <Platform value="iOSDevice32">False</Platform>
+                <Platform value="iOSDevice64">True</Platform>
+                <Platform value="iOSSimulator">False</Platform>
+                <Platform value="OSX32">False</Platform>
+                <Platform value="Win32">True</Platform>
+                <Platform value="Win64">False</Platform>
+            </Platforms>
+            <Deployment Version="3">
+                <DeployFile LocalName="MyServiceConsole.exe" Configuration="Debug" Class="ProjectOutput">
+                    <Platform Name="Win32">
+                        <RemoteName>MyServiceConsole.exe</RemoteName>
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
+                    <Platform Name="OSX32">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule">
+                    <Platform Name="iOSSimulator">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="$(BDS)\Redist\iossimulator\libPCRE.dylib" Class="DependencyModule">
+                    <Platform Name="iOSSimulator">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="$(BDS)\Redist\osx32\libcgsqlite3.dylib" Class="DependencyModule">
+                    <Platform Name="OSX32">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployClass Name="AdditionalDebugSymbols">
+                    <Platform Name="OSX32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidClassesDexFile">
+                    <Platform Name="Android">
+                        <RemoteDir>classes</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidGDBServer">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidLibnativeArmeabiFile">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidLibnativeMipsFile">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\mips</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidServiceOutput">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidSplashImageDef">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidSplashStyles">
+                    <Platform Name="Android">
+                        <RemoteDir>res\values</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_DefaultAppIcon">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon144">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xxhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon36">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-ldpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon48">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-mdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon72">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-hdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon96">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage426">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-small</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage470">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-normal</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage640">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-large</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage960">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xlarge</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="DebugSymbols">
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="DependencyFramework">
+                    <Platform Name="OSX32">
+                        <Operation>1</Operation>
+                        <Extensions>.framework</Extensions>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="DependencyModule">
+                    <Platform Name="OSX32">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                        <Extensions>.dll;.bpl</Extensions>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Required="true" Name="DependencyPackage">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                        <Extensions>.bpl</Extensions>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="File">
+                    <Platform Name="Android">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice32">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch1024">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch1536">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch2048">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch768">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Launch320">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Launch640">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Launch640x1136">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectAndroidManifest">
+                    <Platform Name="Android">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSDeviceDebug">
+                    <Platform Name="iOSDevice32">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSDeviceResourceRules"/>
+                <DeployClass Name="ProjectiOSEntitlements"/>
+                <DeployClass Name="ProjectiOSInfoPList"/>
+                <DeployClass Name="ProjectiOSResource">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXEntitlements"/>
+                <DeployClass Name="ProjectOSXInfoPList"/>
+                <DeployClass Name="ProjectOSXResource">
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\Resources</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Required="true" Name="ProjectOutput">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Linux64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectUWPManifest">
+                    <Platform Name="Win32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="UWP_DelphiLogo150">
+                    <Platform Name="Win32">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="UWP_DelphiLogo44">
+                    <Platform Name="Win32">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="OSX32" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
+            </Deployment>
+        </BorlandProject>
+        <ProjectFileVersion>12</ProjectFileVersion>
+    </ProjectExtensions>
+    <Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
+    <Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
+    <Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
+</Project>

二进制
samples/QuickChrono/ChronoDemo.res → samples/delphi/QuickAppService/ConsoleAndService/MyServiceConsole.res


+ 0 - 0
samples/QuickChrono/ChronoDemo.dpr → samples/delphi/QuickChrono/ChronoDemo.dpr


+ 0 - 0
samples/QuickChrono/ChronoDemo.dproj → samples/delphi/QuickChrono/ChronoDemo.dproj


二进制
samples/delphi/QuickChrono/ChronoDemo.ico


二进制
samples/delphi/QuickChrono/ChronoDemo.res


+ 0 - 0
samples/QuickChrono/Main.dfm → samples/delphi/QuickChrono/Main.dfm


+ 0 - 0
samples/QuickChrono/Main.pas → samples/delphi/QuickChrono/Main.pas


+ 0 - 0
samples/QuickConfig/Main.dfm → samples/delphi/QuickConfig/ConfigToFileAndRegistry/Main.dfm


+ 0 - 0
samples/QuickConfig/Main.pas → samples/delphi/QuickConfig/ConfigToFileAndRegistry/Main.pas


+ 0 - 0
samples/QuickConfig/QuickConfigDemo.dpr → samples/delphi/QuickConfig/ConfigToFileAndRegistry/QuickConfigDemo.dpr


+ 0 - 0
samples/QuickConfig/QuickConfigDemo.dproj → samples/delphi/QuickConfig/ConfigToFileAndRegistry/QuickConfigDemo.dproj


+ 0 - 0
samples/QuickConfig/QuickConfigDemo.res → samples/delphi/QuickConfig/ConfigToFileAndRegistry/QuickConfigDemo.res


+ 0 - 0
samples/QuickConfig/Win64/Debug/Config.json → samples/delphi/QuickConfig/ConfigToFileAndRegistry/Win64/Debug/Config.json


+ 23 - 12
samples/QuickConsole/QuickConsoleMenu.dpr → samples/delphi/QuickConsole/ConsoleMenu/QuickConsoleMenu.dpr

@@ -2,20 +2,25 @@ program QuickConsoleMenu;
 
 {$APPTYPE CONSOLE}
 
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF}
+
 {$R *.res}
 
 uses
-  System.SysUtils,
-  Winapi.Windows,
+  SysUtils,
+  Windows,
   Quick.Commons,
   Quick.Console;
 
 type
-  TTest = record
-    procedure Option1;
-    procedure Option2;
-    procedure Option3;
-    procedure Option4;
+  TTest = class
+    class procedure Option1;
+    class procedure Option2;
+    class procedure Option3;
+    class procedure Option4;
+    class procedure Option5;
   end;
 
 var
@@ -26,26 +31,31 @@ var
 
 { TTest }
 
-procedure TTest.Option1;
+class procedure TTest.Option1;
 begin
   coutXY(10,10,'Option 1 pressed',etInfo);
 end;
 
-procedure TTest.Option2;
+class procedure TTest.Option2;
 begin
   coutXY(10,10,'Option 2 pressed',etInfo);
 end;
 
-procedure TTest.Option3;
+class procedure TTest.Option3;
 begin
   coutXY(10,10,'Option 3 pressed',etInfo);
 end;
 
-procedure TTest.Option4;
+class procedure TTest.Option4;
 begin
   coutXY(10,10,'Option 4 pressed',etInfo);
 end;
 
+class procedure TTest.Option5;
+begin
+  coutXY(10,10,'Option 5 pressed',etInfo);
+end;
+
 begin
   try
     conmenu := TConsoleMenu.Create;
@@ -58,10 +68,11 @@ begin
 
     conmenu.AddMenu('Option 4',VK_F4,Test.Option4);
 
-    conmenu.AddMenu('Option 5',VK_F5,procedure
+    conmenu.AddMenu('Option 5',VK_F5,{$IFDEF FPC}Test.Option5);{$ELSE}procedure
                                  begin
                                    coutXY(10,10,'Option 5 pressed',etInfo);
                                  end);
+                                 {$ENDIF}
 
     for i := 0 to 30 do writeln('hola que tal');
 

+ 0 - 0
samples/QuickConsole/QuickConsoleMenu.dproj → samples/delphi/QuickConsole/ConsoleMenu/QuickConsoleMenu.dproj


+ 0 - 0
samples/QuickConsole/QuickConsoleMenu.res → samples/delphi/QuickConsole/ConsoleMenu/QuickConsoleMenu.res


+ 32 - 0
samples/delphi/QuickConsole/ConsoleOut/ConsoleOut.dpr

@@ -0,0 +1,32 @@
+program ConsoleOut;
+
+{$APPTYPE CONSOLE}
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF}
+
+{$R *.res}
+
+uses
+  SysUtils,
+  Quick.Commons,
+  Quick.Console;
+
+begin
+  try
+    coutXY(20,10,'this line will be replaced by the next',etInfo);
+    coutXY(20,10,'this line replaces previous',etSuccess);
+    cout('Normal line 1',etInfo);
+    coutBL('bottom line: 1',etInfo);
+    cout('Normal line 2',etInfo);
+    coutXY(10,5,'I''m here',etSuccess);
+    coutBL('bottom line: 2',etInfo);
+    cout('Normal line 3',etInfo);
+    coutBL('bottomline: 3',etInfo);
+    ConsoleWaitForEnterKey;
+  except
+    on E: Exception do
+      Writeln(E.ClassName, ': ', E.Message);
+  end;
+end.

+ 4 - 4
samples/QuickConsole/QuickConsoleSample.dproj → samples/delphi/QuickConsole/ConsoleOut/ConsoleOut.dproj

@@ -1,9 +1,9 @@
 <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
     <PropertyGroup>
         <ProjectGuid>{B4CDB6F9-CB8D-402E-A8EB-2DCA8AC583C9}</ProjectGuid>
-        <ProjectVersion>18.2</ProjectVersion>
+        <ProjectVersion>18.4</ProjectVersion>
         <FrameworkType>None</FrameworkType>
-        <MainSource>QuickConsoleSample.dpr</MainSource>
+        <MainSource>ConsoleOut.dpr</MainSource>
         <Base>True</Base>
         <Config Condition="'$(Config)'==''">Debug</Config>
         <Platform Condition="'$(Platform)'==''">Win32</Platform>
@@ -74,7 +74,7 @@
         <DCC_K>false</DCC_K>
         <DCC_UsePackage>RESTComponents;FireDACIBDriver;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;FireDAC;FireDACSqliteDriver;soaprtl;soapmidas;$(DCC_UsePackage)</DCC_UsePackage>
         <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
-        <SanitizedProjectName>QuickConsoleSample</SanitizedProjectName>
+        <SanitizedProjectName>ConsoleOut</SanitizedProjectName>
     </PropertyGroup>
     <PropertyGroup Condition="'$(Base_Android)'!=''">
         <DCC_UsePackage>DBXSqliteDriver;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;dbexpress;IndyCore;dsnap;bindengine;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;bindcomp;CoolTrayIcon_D210_XE7;IndyIPClient;dbxcds;Gauge3D;dsnapxml;dbrtl;IndyProtocols;$(DCC_UsePackage)</DCC_UsePackage>
@@ -157,7 +157,7 @@
         <BorlandProject>
             <Delphi.Personality>
                 <Source>
-                    <Source Name="MainSource">QuickConsoleSample.dpr</Source>
+                    <Source Name="MainSource">ConsoleOut.dpr</Source>
                 </Source>
             </Delphi.Personality>
             <Deployment Version="3"/>

+ 0 - 0
samples/QuickConsole/QuickConsoleSample.res → samples/delphi/QuickConsole/ConsoleOut/ConsoleOut.res


+ 2 - 2
samples/QuickNetwork/GetIPRangeSample.dpr → samples/delphi/QuickNetwork/GetIPRange/GetIPRanges.dpr

@@ -1,11 +1,11 @@
-program GetIPRangeSample;
+program GetIPRanges;
 
 {$APPTYPE CONSOLE}
 
 {$R *.res}
 
 uses
-  System.SysUtils,
+  SysUtils,
   Quick.Commons,
   Quick.Network,
   Quick.Console;

+ 6 - 6
samples/QuickNetwork/GetIPRangeSample.dproj → samples/delphi/QuickNetwork/GetIPRange/GetIPRanges.dproj

@@ -1,9 +1,9 @@
 <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
     <PropertyGroup>
         <ProjectGuid>{36FE2FD1-B3D8-464C-BE25-24E59EADE7E3}</ProjectGuid>
-        <ProjectVersion>18.2</ProjectVersion>
+        <ProjectVersion>18.4</ProjectVersion>
         <FrameworkType>None</FrameworkType>
-        <MainSource>GetIPRangeSample.dpr</MainSource>
+        <MainSource>GetIPRanges.dpr</MainSource>
         <Base>True</Base>
         <Config Condition="'$(Config)'==''">Debug</Config>
         <Platform Condition="'$(Platform)'==''">Win32</Platform>
@@ -74,7 +74,7 @@
         <DCC_K>false</DCC_K>
         <DCC_UsePackage>RESTComponents;FireDACIBDriver;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;FireDAC;FireDACSqliteDriver;soaprtl;soapmidas;$(DCC_UsePackage)</DCC_UsePackage>
         <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
-        <SanitizedProjectName>GetIPRangeSample</SanitizedProjectName>
+        <SanitizedProjectName>GetIPRanges</SanitizedProjectName>
     </PropertyGroup>
     <PropertyGroup Condition="'$(Base_Android)'!=''">
         <DCC_UsePackage>DBXSqliteDriver;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;dbexpress;IndyCore;dsnap;bindengine;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;bindcomp;CoolTrayIcon_D210_XE7;IndyIPClient;dbxcds;Gauge3D;dsnapxml;dbrtl;IndyProtocols;$(DCC_UsePackage)</DCC_UsePackage>
@@ -157,7 +157,7 @@
         <BorlandProject>
             <Delphi.Personality>
                 <Source>
-                    <Source Name="MainSource">GetIPRangeSample.dpr</Source>
+                    <Source Name="MainSource">GetIPRanges.dpr</Source>
                 </Source>
             </Delphi.Personality>
             <Deployment Version="3">
@@ -181,9 +181,9 @@
                         <Overwrite>true</Overwrite>
                     </Platform>
                 </DeployFile>
-                <DeployFile LocalName="Win32\Debug\GetIPRangeSample.exe" Configuration="Debug" Class="ProjectOutput">
+                <DeployFile LocalName="Win32\Debug\GetIPRanges.exe" Configuration="Debug" Class="ProjectOutput">
                     <Platform Name="Win32">
-                        <RemoteName>GetIPRangeSample.exe</RemoteName>
+                        <RemoteName>GetIPRanges.exe</RemoteName>
                         <Overwrite>true</Overwrite>
                     </Platform>
                 </DeployFile>

+ 0 - 0
samples/QuickNetwork/GetIPRangeSample.res → samples/delphi/QuickNetwork/GetIPRange/GetIPRanges.res


+ 2 - 3
samples/QuickService/ServicesSample.dpr → samples/delphi/QuickService/ServiceManagement/ServiceManagement.dpr

@@ -1,11 +1,11 @@
-program ServicesSample;
+program ServiceManagement;
 
 {$APPTYPE CONSOLE}
 
 {$R *.res}
 
 uses
-  System.SysUtils,
+  SysUtils,
   Quick.Commons,
   Quick.Console,
   Quick.Service;
@@ -14,7 +14,6 @@ var
   svcname : string;
 
 begin
-
   try
     svcname := 'aspnet_state';
     cout('Need to run as admin',etWarning);

+ 5 - 5
samples/QuickService/ServicesSample.dproj → samples/delphi/QuickService/ServiceManagement/ServiceManagement.dproj

@@ -3,7 +3,7 @@
         <ProjectGuid>{D435A5BC-1132-4D26-A93B-74996B8B1709}</ProjectGuid>
         <ProjectVersion>18.4</ProjectVersion>
         <FrameworkType>None</FrameworkType>
-        <MainSource>ServicesSample.dpr</MainSource>
+        <MainSource>ServiceManagement.dpr</MainSource>
         <Base>True</Base>
         <Config Condition="'$(Config)'==''">Debug</Config>
         <Platform Condition="'$(Platform)'==''">Win32</Platform>
@@ -74,7 +74,7 @@
         <DCC_K>false</DCC_K>
         <DCC_UsePackage>RESTComponents;FireDACIBDriver;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;FireDAC;FireDACSqliteDriver;soaprtl;soapmidas;$(DCC_UsePackage)</DCC_UsePackage>
         <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
-        <SanitizedProjectName>ServicesSample</SanitizedProjectName>
+        <SanitizedProjectName>ServiceManagement</SanitizedProjectName>
     </PropertyGroup>
     <PropertyGroup Condition="'$(Base_Android)'!=''">
         <DCC_UsePackage>DBXSqliteDriver;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;dbexpress;IndyCore;dsnap;bindengine;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;bindcomp;CoolTrayIcon_D210_XE7;IndyIPClient;dbxcds;dsnapxml;dbrtl;IndyProtocols;$(DCC_UsePackage)</DCC_UsePackage>
@@ -157,7 +157,7 @@
         <BorlandProject>
             <Delphi.Personality>
                 <Source>
-                    <Source Name="MainSource">ServicesSample.dpr</Source>
+                    <Source Name="MainSource">ServiceManagement.dpr</Source>
                 </Source>
             </Delphi.Personality>
             <Deployment Version="3">
@@ -181,9 +181,9 @@
                         <Overwrite>true</Overwrite>
                     </Platform>
                 </DeployFile>
-                <DeployFile LocalName="Win32\Debug\ServicesSample.exe" Configuration="Debug" Class="ProjectOutput">
+                <DeployFile LocalName="Win32\Debug\ServiceManagement.exe" Configuration="Debug" Class="ProjectOutput">
                     <Platform Name="Win32">
-                        <RemoteName>ServicesSample.exe</RemoteName>
+                        <RemoteName>ServiceManagement.exe</RemoteName>
                         <Overwrite>true</Overwrite>
                     </Platform>
                 </DeployFile>

+ 0 - 0
samples/QuickService/ServicesSample.res → samples/delphi/QuickService/ServiceManagement/ServiceManagement.res


+ 62 - 0
samples/fpc/QuickAppService/ConsoleAndService/MyServiceConsole.lpi

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasScaledStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="QuickAppService"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0"/>
+    </RunParams>
+    <RequiredPackages Count="1">
+      <Item1>
+        <PackageName Value="QuickLib"/>
+      </Item1>
+    </RequiredPackages>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="MyServiceConsole.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="MyServiceConsole"/>
+    </Target>
+    <SearchPaths>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 66 - 0
samples/fpc/QuickAppService/ConsoleAndService/MyServiceConsole.lpr

@@ -0,0 +1,66 @@
+program MyServiceConsole;
+
+{$APPTYPE CONSOLE}
+
+{$MODE DELPHI}
+
+{$R *.res}
+
+uses
+  SysUtils,
+  Quick.Commons,
+  Quick.Console,
+  Quick.AppService;
+
+type
+
+  TSrvFactory = class
+    class procedure CreateMyService;
+  end;
+
+  TMyService = class
+  public
+    procedure Execute;
+  end;
+
+  procedure TMyService.Execute;
+  begin
+    //your code
+  end;
+
+var
+
+  MyService : TMyService;
+
+class procedure TSrvFactory.CreateMyService;
+begin
+ MyService := TMyService.Create;
+end;
+
+begin
+
+  try
+    if not AppService.IsRunningAsService then
+    begin
+      cout('Running in console mode',etInfo);
+      MyService := TMyService.Create;
+      MyService.Execute;
+      cout('Press [Enter] to exit',etInfo);
+      ConsoleWaitForEnterKey;
+      cout('Closing app...',etInfo);
+      MyService.Free;
+    end
+    else
+    begin
+        AppService.ServiceName := 'MyService';
+        AppService.DisplayName := 'MyServicesvc';
+        AppService.OnStart := TSrvFactory.CreateMyService;
+        AppService.OnExecute := MyService.Execute;
+        AppService.OnStop := MyService.Free;
+        AppService.CheckParams;
+    end;
+  except
+    on E: Exception do
+      Writeln(E.ClassName, ': ', E.Message);
+  end;
+end.

+ 22 - 0
samples/fpc/QuickAppService/ConsoleAndService/MyServiceConsole.lps

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectSession>
+    <PathDelim Value="\"/>
+    <Version Value="11"/>
+    <BuildModes Active="Default"/>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="MyServiceConsole.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <IsVisibleTab Value="True"/>
+        <EditorIndex Value="-1"/>
+        <UsageCount Value="20"/>
+      </Unit0>
+    </Units>
+    <JumpHistory HistoryIndex="-1"/>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0" ActiveMode=""/>
+    </RunParams>
+  </ProjectSession>
+</CONFIG>

二进制
samples/fpc/QuickAppService/ConsoleAndService/MyServiceConsole.res


+ 62 - 0
samples/fpc/QuickAppService/ConsoleAndService/backup/MyServiceConsole.lpi

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasScaledStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="QuickAppService"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0"/>
+    </RunParams>
+    <RequiredPackages Count="1">
+      <Item1>
+        <PackageName Value="QuickLib"/>
+      </Item1>
+    </RequiredPackages>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="MyServiceConsole.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="MyServiceConsole"/>
+    </Target>
+    <SearchPaths>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 22 - 0
samples/fpc/QuickAppService/ConsoleAndService/backup/MyServiceConsole.lps

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectSession>
+    <PathDelim Value="\"/>
+    <Version Value="11"/>
+    <BuildModes Active="Default"/>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="MyServiceConsole.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <IsVisibleTab Value="True"/>
+        <EditorIndex Value="-1"/>
+        <UsageCount Value="20"/>
+      </Unit0>
+    </Units>
+    <JumpHistory HistoryIndex="-1"/>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0" ActiveMode=""/>
+    </RunParams>
+  </ProjectSession>
+</CONFIG>

+ 80 - 0
samples/fpc/QuickAppService/ConsoleAndService/backup/MyServiceConsole.pas

@@ -0,0 +1,80 @@
+program MyServiceConsole;
+
+{$APPTYPE CONSOLE}
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF}
+
+{$R *.res}
+
+uses
+  SysUtils,
+  Quick.Commons,
+  Quick.Console,
+  Quick.AppService;
+
+type
+
+  {$IFDEF FPC}
+  TSrvFactory = class
+    class procedure CreateMyService;
+  end;
+  {$ENDIF}
+
+  TMyService = class
+  public
+    procedure Execute;
+  end;
+
+  procedure TMyService.Execute;
+  begin
+    //your code
+  end;
+
+var
+
+  MyService : TMyService;
+
+{$IFDEF FPC}
+class procedure TSrvFactory.CreateMyService;
+begin
+ MyService := TMyService.Create;
+end;
+{$ENDIF}
+
+begin
+
+  try
+    if not AppService.IsRunningAsService then
+    begin
+      cout('Running in console mode',etInfo);
+      MyService := TMyService.Create;
+      MyService.Execute;
+      cout('Press [Enter] to exit',etInfo);
+      ConsoleWaitForEnterKey;
+      cout('Closing app...',etInfo);
+      MyService.Free;
+    end
+    else
+    begin
+        AppService.ServiceName := 'MyService';
+        AppService.DisplayName := 'MyServicesvc';
+        {$IFDEF FPC}
+        AppService.OnStart := TSrvFactory.CreateMyService;
+        {$ELSE}
+        //you can pass an anonymous method to events
+        AppService.OnStart := procedure
+                              begin
+                                MyService := TMyService.Start;
+                              end;
+        {$ENDIF}
+        AppService.OnExecute := MyService.Execute;
+        AppService.OnStop := MyService.Free;
+        AppService.CheckParams;
+    end;
+  except
+    on E: Exception do
+      Writeln(E.ClassName, ': ', E.Message);
+  end;
+end.

+ 88 - 0
samples/fpc/QuickAppService/ConsoleAndService/backup/QuickAppServiceSample.lps

@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectSession>
+    <PathDelim Value="\"/>
+    <Version Value="11"/>
+    <BuildModes Active="Default"/>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <IsPartOfProject Value="True"/>
+        <IsVisibleTab Value="True"/>
+        <TopLine Value="48"/>
+        <CursorPos X="55" Y="66"/>
+        <UsageCount Value="20"/>
+        <Loaded Value="True"/>
+      </Unit0>
+    </Units>
+    <JumpHistory Count="16" HistoryIndex="15">
+      <Position1>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+      </Position1>
+      <Position2>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <Caret Line="9" Column="3"/>
+      </Position2>
+      <Position3>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <Caret Line="52" Column="46" TopLine="30"/>
+      </Position3>
+      <Position4>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <Caret Line="26" Column="3" TopLine="12"/>
+      </Position4>
+      <Position5>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <Caret Line="56" Column="32" TopLine="36"/>
+      </Position5>
+      <Position6>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <Caret Line="13" Column="5"/>
+      </Position6>
+      <Position7>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <Caret Line="27" Column="26" TopLine="14"/>
+      </Position7>
+      <Position8>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <Caret Line="29" Column="26" TopLine="21"/>
+      </Position8>
+      <Position9>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <Caret Line="52" Column="47" TopLine="32"/>
+      </Position9>
+      <Position10>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <Caret Line="54" Column="49" TopLine="31"/>
+      </Position10>
+      <Position11>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <Caret Line="52" Column="32" TopLine="32"/>
+      </Position11>
+      <Position12>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <Caret Line="15" Column="22" TopLine="11"/>
+      </Position12>
+      <Position13>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <Caret Line="56" Column="32" TopLine="36"/>
+      </Position13>
+      <Position14>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <Caret Line="37" Column="7" TopLine="12"/>
+      </Position14>
+      <Position15>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <Caret Line="46" Column="8" TopLine="29"/>
+      </Position15>
+      <Position16>
+        <Filename Value="QuickAppServiceSample.dpr"/>
+        <Caret Line="9" Column="17"/>
+      </Position16>
+    </JumpHistory>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0" ActiveMode=""/>
+    </RunParams>
+  </ProjectSession>
+</CONFIG>

二进制
samples/fpc/QuickAppService/ConsoleAndService/lib/i386-win32/MyServiceConsole.or


二进制
samples/fpc/QuickAppService/ConsoleAndService/lib/i386-win32/MyServiceConsole.res


二进制
samples/fpc/QuickAppService/ConsoleAndService/lib/i386-win32/QuickAppServiceSample.or


二进制
samples/fpc/QuickAppService/ConsoleAndService/lib/i386-win32/QuickAppServiceSample.res


二进制
samples/fpc/QuickConfig/ConfigToFileAndRegistry/QuickConfig.ico


+ 85 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/QuickConfig.lpi

@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="QuickConfig"/>
+      <Scaled Value="True"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <XPManifest>
+        <DpiAware Value="True"/>
+      </XPManifest>
+      <Icon Value="0"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0"/>
+    </RunParams>
+    <RequiredPackages Count="2">
+      <Item1>
+        <PackageName Value="QuickLib"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="LCL"/>
+      </Item2>
+    </RequiredPackages>
+    <Units Count="3">
+      <Unit0>
+        <Filename Value="QuickConfig.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="Main.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="umain.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="Form1"/>
+        <ResourceBaseClass Value="Form"/>
+        <UnitName Value="uMain"/>
+      </Unit2>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="QuickConfig"/>
+    </Target>
+    <SearchPaths>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Linking>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 20 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/QuickConfig.lpr

@@ -0,0 +1,20 @@
+program QuickConfig;
+
+{$mode objfpc}{$H+}
+
+uses
+  {$IFDEF UNIX}{$IFDEF UseCThreads}
+  cthreads,
+  {$ENDIF}{$ENDIF}
+  Interfaces, // this includes the LCL widgetset
+  Forms;
+
+{$R *.res}
+
+begin
+  RequireDerivedFormResource:=True;
+  Application.Scaled:=True;
+  Application.Initialize;
+  Application.Run;
+end.
+

+ 117 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/QuickConfig.lps

@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectSession>
+    <PathDelim Value="\"/>
+    <Version Value="11"/>
+    <BuildModes Active="Default"/>
+    <Units Count="11">
+      <Unit0>
+        <Filename Value="QuickConfig.pas"/>
+        <IsPartOfProject Value="True"/>
+        <EditorIndex Value="-1"/>
+        <CursorPos X="38" Y="13"/>
+        <UsageCount Value="25"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="Main.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="37"/>
+        <CursorPos X="3" Y="44"/>
+        <UsageCount Value="25"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="umain.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="Form1"/>
+        <ResourceBaseClass Value="Form"/>
+        <UnitName Value="uMain"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="26"/>
+        <CursorPos X="3" Y="34"/>
+        <UsageCount Value="22"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="..\..\..\..\Quick.Config.pas"/>
+        <IsVisibleTab Value="True"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="62"/>
+        <CursorPos X="53" Y="82"/>
+        <UsageCount Value="13"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="D:\Lazarus\fpcsrc\packages\fcl-json\src\fpjsonrtti.pp"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="837"/>
+        <CursorPos Y="844"/>
+        <UsageCount Value="13"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="D:\Lazarus\fpcsrc\packages\rtl-objpas\src\inc\rtti.pp"/>
+        <UnitName Value="Rtti"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="81"/>
+        <CursorPos X="13" Y="95"/>
+        <UsageCount Value="13"/>
+      </Unit5>
+      <Unit6>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="139"/>
+        <CursorPos X="3" Y="154"/>
+        <UsageCount Value="12"/>
+      </Unit6>
+      <Unit7>
+        <Filename Value="..\..\..\..\Quick.Files.pas"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="284"/>
+        <CursorPos X="15" Y="297"/>
+        <UsageCount Value="12"/>
+      </Unit7>
+      <Unit8>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Registry.pas"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="329"/>
+        <CursorPos X="26" Y="196"/>
+        <UsageCount Value="12"/>
+      </Unit8>
+      <Unit9>
+        <Filename Value="D:\Lazarus\fpcsrc\packages\fcl-json\src\fpjson.pp"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="494"/>
+        <CursorPos X="25" Y="518"/>
+        <UsageCount Value="12"/>
+      </Unit9>
+      <Unit10>
+        <Filename Value="umain.lfm"/>
+        <EditorIndex Value="-1"/>
+        <UsageCount Value="10"/>
+        <DefaultSyntaxHighlighter Value="LFM"/>
+      </Unit10>
+    </Units>
+    <JumpHistory HistoryIndex="-1"/>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0" ActiveMode=""/>
+    </RunParams>
+  </ProjectSession>
+  <Debugging>
+    <BreakPoints Count="2">
+      <Item1>
+        <Kind Value="bpkSource"/>
+        <WatchScope Value="wpsLocal"/>
+        <WatchKind Value="wpkWrite"/>
+        <Source Value="D:\Lazarus\fpcsrc\packages\fcl-json\src\fpjsonrtti.pp"/>
+        <Line Value="736"/>
+      </Item1>
+      <Item2>
+        <Kind Value="bpkSource"/>
+        <WatchScope Value="wpsLocal"/>
+        <WatchKind Value="wpkWrite"/>
+        <Source Value="D:\Lazarus\fpcsrc\packages\fcl-json\src\fpjsonrtti.pp"/>
+        <Line Value="844"/>
+      </Item2>
+    </BreakPoints>
+  </Debugging>
+</CONFIG>

+ 13 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/QuickConfig.pas

@@ -0,0 +1,13 @@
+program QuickConfig;
+
+uses
+  Forms, Interfaces,
+  uMain in 'uMain.pas' {MainForm};
+
+{$R *.res}
+
+begin
+  Application.Initialize;
+  Application.CreateForm(TForm1, Form1);
+  Application.Run;
+end.

二进制
samples/fpc/QuickConfig/ConfigToFileAndRegistry/QuickConfig.res


+ 64 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/Main.dfm

@@ -0,0 +1,64 @@
+object MainForm: TMainForm
+  AlignWithMargins = True
+  Left = 0
+  Top = 0
+  Caption = 'Quick Config Demo'
+  ClientHeight = 347
+  ClientWidth = 523
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  OldCreateOrder = False
+  OnClose = FormClose
+  OnCreate = FormCreate
+  PixelsPerInch = 96
+  TextHeight = 13
+  object meInfo: TMemo
+    Left = 8
+    Top = 8
+    Width = 507
+    Height = 273
+    ReadOnly = True
+    ScrollBars = ssBoth
+    TabOrder = 0
+  end
+  object btnLoadJson: TButton
+    Left = 208
+    Top = 287
+    Width = 145
+    Height = 25
+    Caption = 'Load From Json'
+    TabOrder = 1
+    OnClick = btnLoadJsonClick
+  end
+  object btnSaveJson: TButton
+    Left = 359
+    Top = 287
+    Width = 154
+    Height = 25
+    Caption = 'Save To Json'
+    TabOrder = 2
+    OnClick = btnSaveJsonClick
+  end
+  object btnLoadRegistry: TButton
+    Left = 208
+    Top = 318
+    Width = 145
+    Height = 25
+    Caption = 'Load From Registry'
+    TabOrder = 3
+    OnClick = btnLoadRegistryClick
+  end
+  object SaveRegistry: TButton
+    Left = 359
+    Top = 318
+    Width = 154
+    Height = 25
+    Caption = 'Save To Registry'
+    TabOrder = 4
+    OnClick = SaveRegistryClick
+  end
+end

+ 225 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/Main.pas

@@ -0,0 +1,225 @@
+unit Main;
+
+{$mode delphi}{$H+}
+
+interface
+
+uses
+  Windows,
+  Messages,
+  SysUtils,
+  Variants,
+  Classes,
+  Graphics,
+  Controls,
+  Forms,
+  Dialogs,
+  StdCtrls,
+  Quick.Config,
+  //Quick.Config.Provider.Registry,
+  Generics.Collections,
+  Quick.Config.Provider.Json;
+
+type
+
+  TMyPriority = (msLow, msMed, msHigh);
+
+  TWinPos = record
+  public
+    PosX : Integer;
+    PosY : Integer;
+  end;
+
+  TProcessType = record
+    Id : Integer;
+    Priority : TMyPriority;
+    Redundant : Boolean;
+  end;
+
+  TWorker = class
+    Name : string;
+    Active : Boolean;
+  end;
+
+  TMyConfig = class(TAppConfig)
+  private
+    fTitle : string;
+    fHidden : Boolean;
+    fSessionName: string;
+  public
+    Sizes : array of Integer;
+    LastFilename : string;
+    WindowPos : TWinPos;
+    History : array of TProcessType;
+    Complex : TProcessType;
+    ModifyDate : TDateTime;
+    WorkList : TObjectList<TWorker>;
+    constructor Create; override;
+    destructor Destroy; override;
+    procedure DefaultValues;
+    property Title : string read fTitle write fTitle;
+    property SessionName : string read fSessionName write fSessionName;
+  end;
+
+  TMainForm = class(TForm)
+    meInfo: TMemo;
+    btnLoadJson: TButton;
+    btnSaveJson: TButton;
+    btnLoadRegistry: TButton;
+    SaveRegistry: TButton;
+    procedure FormCreate(Sender: TObject);
+    procedure btnLoadJsonClick(Sender: TObject);
+    procedure btnSaveJsonClick(Sender: TObject);
+    procedure SaveRegistryClick(Sender: TObject);
+    procedure btnLoadRegistryClick(Sender: TObject);
+    procedure SetConfig(cConfig: TMyConfig);
+    function TestConfig(cConfig1, cConfig2: TMyConfig) : Boolean;
+    procedure FormClose(Sender: TObject; var Action: TCloseAction);
+  end;
+
+var
+  MainForm: TMainForm;
+  ConfigJson : TMyConfig;
+  ConfigReg : TMyConfig;
+  ConfigTest : TMyConfig;
+  AppConfigJson : TAppConfigJsonProvider<TMyConfig>;
+  //AppConfigReg : TAppConfigRegistryProvider<TMyConfig>;
+
+implementation
+
+{$R *.lfm}
+
+procedure TMainForm.btnLoadJsonClick(Sender: TObject);
+begin
+  meInfo.Lines.Add('Load ConfigJson');
+  AppConfigJson.Load(ConfigJson);
+  meInfo.Lines.Add(ConfigJson.ToJSON);
+  if TestConfig(ConfigTest,ConfigJson) then meInfo.Lines.Add('Test passed successfully!');
+end;
+
+procedure TMainForm.btnLoadRegistryClick(Sender: TObject);
+begin
+  meInfo.Lines.Add('Load ConfigReg');
+  //AppConfigReg.Load(ConfigReg);
+  meInfo.Lines.Add(ConfigReg.ToJSON);
+  if TestConfig(ConfigTest,ConfigReg) then meInfo.Lines.Add('Test passed successfully!');
+end;
+
+procedure TMainForm.btnSaveJsonClick(Sender: TObject);
+begin
+  SetConfig(ConfigJson);
+  AppConfigJson.Save(ConfigJson);
+  meInfo.Lines.Add('Saved Config in Json at ' + DateTimeToStr(ConfigJson.LastSaved));
+end;
+
+procedure TMainForm.SaveRegistryClick(Sender: TObject);
+begin
+  SetConfig(ConfigReg);
+  //AppConfigReg.Save(ConfigReg);
+  meInfo.Lines.Add('Saved Config in Registry at ' + DateTimeToStr(ConfigReg.LastSaved));
+end;
+
+procedure TMainForm.SetConfig(cConfig : TMyConfig);
+var
+  protype : TProcessType;
+  i : Integer;
+  worker : TWorker;
+begin
+  cConfig.LastFilename := 'library.txt';
+  cConfig.Sizes := [23,11,554,12,34,29,77,30,48,59,773,221,98,3,22,983,122,231,433,12,31,987];
+  cConfig.WindowPos.PosX := 640;
+  cConfig.WindowPos.PosX := 480;
+  cConfig.Complex.Priority := msHigh;
+  cConfig.Complex.Redundant := False;
+  cConfig.Title := 'a fresh title';
+  cConfig.SessionName := 'First Session';
+  for I := 0 to 22 do
+  begin
+    worker := TWorker.Create;
+    worker.Name := 'Process ' + i.ToString;
+    worker.Active := Boolean(Random(1));
+    cConfig.WorkList.Add(worker);
+  end;
+  for i := 0 to 15 do
+  begin
+    protype.Id := i;
+    protype.Priority := msLow;
+    protype.Redundant := True;
+    SetLength(cConfig.History,High(cConfig.History)+1);
+    cConfig.History[High(cConfig.History)] := protype;
+  end;
+  cConfig.ModifyDate := Now();
+end;
+
+function  TMainForm.TestConfig(cConfig1, cConfig2 : TMyConfig) : Boolean;
+var
+  i : Integer;
+begin
+  try
+    Assert(cConfig1.LastFilename = cConfig2.LastFilename);
+    for i := Low(cConfig1.Sizes) to High(cConfig1.Sizes) do
+      Assert(cConfig1.Sizes[i] = cConfig2.Sizes[i]);
+    Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
+    Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
+    Assert(cConfig1.Complex.Priority = cConfig2.Complex.Priority);
+    Assert(cConfig1.Complex.Redundant  = cConfig2.Complex.Redundant);
+    Assert(cConfig1.Title = cConfig2.Title);
+    for i := 0 to cConfig1.WorkList.Count - 1 do
+    begin
+      Assert(cConfig1.WorkList[i].Name = cConfig2.WorkList[i].Name);
+      Assert(cConfig1.WorkList[i].Active = cConfig2.WorkList[i].Active);
+    end;
+    for i := 0 to High(cConfig1.History) do
+    begin
+      Assert(cConfig1.History[i].Priority = cConfig2.History[i].Priority);
+      Assert(cConfig1.History[i].Redundant = cConfig2.History[i].Redundant);
+    end;
+    Result := True;
+  except
+    ShowMessage('Configuration not has been saved previously or has a corruption problem');
+  end;
+end;
+
+procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
+begin
+  if Assigned(AppConfigJson) then AppConfigJson.Free;
+  //if Assigned(AppConfigReg) then AppConfigReg.Free;
+  if Assigned(ConfigTest) then ConfigTest.Free;
+  if Assigned(ConfigReg) then ConfigReg.Free;
+  if Assigned(ConfigJson) then ConfigJson.Free;
+end;
+
+procedure TMainForm.FormCreate(Sender: TObject);
+begin
+  ConfigTest := TMyConfig.Create;
+  SetConfig(ConfigTest);
+  AppConfigJson := TAppConfigJsonProvider<TMyConfig>.Create(ConfigJson);
+  AppConfigJson.CreateIfNotExists := True;
+  AppConfigJson.Filename := 'Config.json';
+  //AppConfigReg := TAppConfigRegistryProvider<TMyConfig>.Create(ConfigReg);
+  //AppConfigReg.HRoot := HKEY_CURRENT_USER;
+  //AppConfigReg.MainKey := '_AppConfig';
+end;
+
+{ TMyConfig }
+
+constructor TMyConfig.Create;
+begin
+  inherited;
+  WorkList := TObjectList<TWorker>.Create(True);
+  DefaultValues;
+end;
+
+procedure TMyConfig.DefaultValues;
+begin
+  fTitle := 'Default value';
+end;
+
+destructor TMyConfig.Destroy;
+begin
+  if Assigned(WorkList) then WorkList.Free;
+  inherited;
+end;
+
+end.
+

+ 85 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/QuickConfig.lpi

@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="QuickConfig"/>
+      <Scaled Value="True"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <XPManifest>
+        <DpiAware Value="True"/>
+      </XPManifest>
+      <Icon Value="0"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0"/>
+    </RunParams>
+    <RequiredPackages Count="2">
+      <Item1>
+        <PackageName Value="QuickLib"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="LCL"/>
+      </Item2>
+    </RequiredPackages>
+    <Units Count="3">
+      <Unit0>
+        <Filename Value="QuickConfig.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="Main.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="umain.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="Form1"/>
+        <ResourceBaseClass Value="Form"/>
+        <UnitName Value="uMain"/>
+      </Unit2>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="QuickConfig"/>
+    </Target>
+    <SearchPaths>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Linking>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 141 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/QuickConfig.lps

@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectSession>
+    <PathDelim Value="\"/>
+    <Version Value="11"/>
+    <BuildModes Active="Default"/>
+    <Units Count="11">
+      <Unit0>
+        <Filename Value="QuickConfig.pas"/>
+        <IsPartOfProject Value="True"/>
+        <CursorPos X="38" Y="13"/>
+        <UsageCount Value="25"/>
+        <Loaded Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="Main.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="37"/>
+        <CursorPos X="3" Y="44"/>
+        <UsageCount Value="25"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="umain.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="Form1"/>
+        <ResourceBaseClass Value="Form"/>
+        <UnitName Value="uMain"/>
+        <EditorIndex Value="1"/>
+        <TopLine Value="26"/>
+        <CursorPos X="3" Y="34"/>
+        <UsageCount Value="22"/>
+        <Loaded Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="..\..\..\..\Quick.Config.pas"/>
+        <IsVisibleTab Value="True"/>
+        <EditorIndex Value="3"/>
+        <TopLine Value="62"/>
+        <CursorPos X="53" Y="82"/>
+        <UsageCount Value="13"/>
+        <Loaded Value="True"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="D:\Lazarus\fpcsrc\packages\fcl-json\src\fpjsonrtti.pp"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="837"/>
+        <CursorPos Y="844"/>
+        <UsageCount Value="13"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="D:\Lazarus\fpcsrc\packages\rtl-objpas\src\inc\rtti.pp"/>
+        <UnitName Value="Rtti"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="81"/>
+        <CursorPos X="13" Y="95"/>
+        <UsageCount Value="13"/>
+      </Unit5>
+      <Unit6>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <EditorIndex Value="2"/>
+        <TopLine Value="139"/>
+        <CursorPos X="3" Y="154"/>
+        <UsageCount Value="12"/>
+        <Loaded Value="True"/>
+      </Unit6>
+      <Unit7>
+        <Filename Value="..\..\..\..\Quick.Files.pas"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="284"/>
+        <CursorPos X="15" Y="297"/>
+        <UsageCount Value="12"/>
+      </Unit7>
+      <Unit8>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Registry.pas"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="329"/>
+        <CursorPos X="26" Y="196"/>
+        <UsageCount Value="12"/>
+      </Unit8>
+      <Unit9>
+        <Filename Value="D:\Lazarus\fpcsrc\packages\fcl-json\src\fpjson.pp"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="494"/>
+        <CursorPos X="25" Y="518"/>
+        <UsageCount Value="12"/>
+      </Unit9>
+      <Unit10>
+        <Filename Value="umain.lfm"/>
+        <EditorIndex Value="-1"/>
+        <UsageCount Value="10"/>
+        <DefaultSyntaxHighlighter Value="LFM"/>
+      </Unit10>
+    </Units>
+    <JumpHistory Count="5" HistoryIndex="4">
+      <Position1>
+        <Filename Value="QuickConfig.pas"/>
+        <Caret Line="13" Column="38"/>
+      </Position1>
+      <Position2>
+        <Filename Value="umain.pas"/>
+        <Caret Line="63" Column="3" TopLine="16"/>
+      </Position2>
+      <Position3>
+        <Filename Value="..\..\..\..\Quick.Config.pas"/>
+        <Caret Line="79" Column="26" TopLine="65"/>
+      </Position3>
+      <Position4>
+        <Filename Value="umain.pas"/>
+        <Caret Line="97" TopLine="77"/>
+      </Position4>
+      <Position5>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="68" Column="19" TopLine="47"/>
+      </Position5>
+    </JumpHistory>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0" ActiveMode=""/>
+    </RunParams>
+  </ProjectSession>
+  <Debugging>
+    <BreakPoints Count="2">
+      <Item1>
+        <Kind Value="bpkSource"/>
+        <WatchScope Value="wpsLocal"/>
+        <WatchKind Value="wpkWrite"/>
+        <Source Value="D:\Lazarus\fpcsrc\packages\fcl-json\src\fpjsonrtti.pp"/>
+        <Line Value="736"/>
+      </Item1>
+      <Item2>
+        <Kind Value="bpkSource"/>
+        <WatchScope Value="wpsLocal"/>
+        <WatchKind Value="wpkWrite"/>
+        <Source Value="D:\Lazarus\fpcsrc\packages\fcl-json\src\fpjsonrtti.pp"/>
+        <Line Value="844"/>
+      </Item2>
+    </BreakPoints>
+  </Debugging>
+</CONFIG>

+ 14 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/QuickConfigDemo.dpr

@@ -0,0 +1,14 @@
+program QuickConfigDemo;
+
+uses
+  Forms, Interfaces,
+  uMain in 'uMain.pas' {MainForm};
+
+{$R *.res}
+
+begin
+  Application.Initialize;
+  Application.MainFormOnTaskbar := True;
+  Application.CreateForm(TForm1, Form1);
+  Application.Run;
+end.

+ 85 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/QuickConfigDemo.lpi

@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="QuickConfigDemo"/>
+      <Scaled Value="True"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <XPManifest>
+        <DpiAware Value="True"/>
+      </XPManifest>
+      <Icon Value="0"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0"/>
+    </RunParams>
+    <RequiredPackages Count="2">
+      <Item1>
+        <PackageName Value="QuickLib"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="LCL"/>
+      </Item2>
+    </RequiredPackages>
+    <Units Count="3">
+      <Unit0>
+        <Filename Value="QuickConfigDemo.dpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="Main.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="umain.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="Form1"/>
+        <ResourceBaseClass Value="Form"/>
+        <UnitName Value="uMain"/>
+      </Unit2>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="QuickConfigDemo"/>
+    </Target>
+    <SearchPaths>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Linking>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 248 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/QuickConfigDemo.lps

@@ -0,0 +1,248 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectSession>
+    <PathDelim Value="\"/>
+    <Version Value="11"/>
+    <BuildModes Active="Default"/>
+    <Units Count="10">
+      <Unit0>
+        <Filename Value="QuickConfigDemo.dpr"/>
+        <IsPartOfProject Value="True"/>
+        <CursorPos X="26" Y="10"/>
+        <UsageCount Value="25"/>
+        <Loaded Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="Main.pas"/>
+        <IsPartOfProject Value="True"/>
+        <HasResources Value="True"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="37"/>
+        <CursorPos X="3" Y="44"/>
+        <UsageCount Value="25"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="..\..\..\..\Quick.Config.pas"/>
+        <EditorIndex Value="1"/>
+        <TopLine Value="65"/>
+        <CursorPos X="21" Y="79"/>
+        <UsageCount Value="13"/>
+        <Loaded Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="D:\Lazarus\fpcsrc\packages\fcl-json\src\fpjsonrtti.pp"/>
+        <IsVisibleTab Value="True"/>
+        <EditorIndex Value="8"/>
+        <TopLine Value="837"/>
+        <CursorPos Y="844"/>
+        <UsageCount Value="13"/>
+        <Loaded Value="True"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="D:\Lazarus\fpcsrc\packages\rtl-objpas\src\inc\rtti.pp"/>
+        <UnitName Value="Rtti"/>
+        <EditorIndex Value="7"/>
+        <TopLine Value="81"/>
+        <CursorPos X="13" Y="95"/>
+        <UsageCount Value="13"/>
+        <Loaded Value="True"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <EditorIndex Value="3"/>
+        <TopLine Value="152"/>
+        <CursorPos Y="181"/>
+        <UsageCount Value="12"/>
+        <Loaded Value="True"/>
+      </Unit5>
+      <Unit6>
+        <Filename Value="..\..\..\..\Quick.Files.pas"/>
+        <EditorIndex Value="6"/>
+        <TopLine Value="284"/>
+        <CursorPos X="15" Y="297"/>
+        <UsageCount Value="12"/>
+        <Loaded Value="True"/>
+      </Unit6>
+      <Unit7>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Registry.pas"/>
+        <EditorIndex Value="4"/>
+        <TopLine Value="329"/>
+        <CursorPos X="26" Y="196"/>
+        <UsageCount Value="12"/>
+        <Loaded Value="True"/>
+      </Unit7>
+      <Unit8>
+        <Filename Value="D:\Lazarus\fpcsrc\packages\fcl-json\src\fpjson.pp"/>
+        <EditorIndex Value="5"/>
+        <TopLine Value="494"/>
+        <CursorPos X="25" Y="518"/>
+        <UsageCount Value="12"/>
+        <Loaded Value="True"/>
+      </Unit8>
+      <Unit9>
+        <Filename Value="umain.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="Form1"/>
+        <ResourceBaseClass Value="Form"/>
+        <UnitName Value="uMain"/>
+        <EditorIndex Value="2"/>
+        <TopLine Value="77"/>
+        <CursorPos Y="97"/>
+        <UsageCount Value="22"/>
+        <Loaded Value="True"/>
+        <LoadedDesigner Value="True"/>
+      </Unit9>
+    </Units>
+    <JumpHistory Count="30" HistoryIndex="29">
+      <Position1>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="160" TopLine="147"/>
+      </Position1>
+      <Position2>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="161" TopLine="147"/>
+      </Position2>
+      <Position3>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="178" TopLine="147"/>
+      </Position3>
+      <Position4>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="179" TopLine="147"/>
+      </Position4>
+      <Position5>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="180" TopLine="148"/>
+      </Position5>
+      <Position6>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="181" TopLine="149"/>
+      </Position6>
+      <Position7>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="152" Column="25" TopLine="150"/>
+      </Position7>
+      <Position8>
+        <Filename Value="umain.pas"/>
+        <Caret Line="97" TopLine="77"/>
+      </Position8>
+      <Position9>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="155" TopLine="148"/>
+      </Position9>
+      <Position10>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="157" TopLine="148"/>
+      </Position10>
+      <Position11>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="159" TopLine="148"/>
+      </Position11>
+      <Position12>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="160" TopLine="148"/>
+      </Position12>
+      <Position13>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="161" TopLine="148"/>
+      </Position13>
+      <Position14>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="178" TopLine="148"/>
+      </Position14>
+      <Position15>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="179" TopLine="148"/>
+      </Position15>
+      <Position16>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="180" TopLine="148"/>
+      </Position16>
+      <Position17>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="181" TopLine="149"/>
+      </Position17>
+      <Position18>
+        <Filename Value="..\..\..\..\Quick.Config.pas"/>
+        <Caret Line="79" Column="21" TopLine="65"/>
+      </Position18>
+      <Position19>
+        <Filename Value="umain.pas"/>
+        <Caret Line="97" TopLine="77"/>
+      </Position19>
+      <Position20>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="154" TopLine="147"/>
+      </Position20>
+      <Position21>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="157" TopLine="158"/>
+      </Position21>
+      <Position22>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="159" TopLine="152"/>
+      </Position22>
+      <Position23>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="160" TopLine="152"/>
+      </Position23>
+      <Position24>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="161" TopLine="152"/>
+      </Position24>
+      <Position25>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="178" TopLine="152"/>
+      </Position25>
+      <Position26>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="179" TopLine="152"/>
+      </Position26>
+      <Position27>
+        <Filename Value="..\..\..\..\Quick.Config.Provider.Json.pas"/>
+        <Caret Line="180" TopLine="152"/>
+      </Position27>
+      <Position28>
+        <Filename Value="D:\Lazarus\fpcsrc\packages\fcl-json\src\fpjsonrtti.pp"/>
+        <Caret Line="71" Column="26" TopLine="57"/>
+      </Position28>
+      <Position29>
+        <Filename Value="D:\Lazarus\fpcsrc\packages\fcl-json\src\fpjsonrtti.pp"/>
+        <Caret Line="736" TopLine="718"/>
+      </Position29>
+      <Position30>
+        <Filename Value="D:\Lazarus\fpcsrc\packages\fcl-json\src\fpjsonrtti.pp"/>
+        <Caret Line="90" Column="32" TopLine="61"/>
+      </Position30>
+    </JumpHistory>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0" ActiveMode=""/>
+    </RunParams>
+  </ProjectSession>
+  <Debugging>
+    <BreakPoints Count="3">
+      <Item1>
+        <Kind Value="bpkSource"/>
+        <WatchScope Value="wpsLocal"/>
+        <WatchKind Value="wpkWrite"/>
+        <Source Value="umain.pas"/>
+        <Line Value="97"/>
+      </Item1>
+      <Item2>
+        <Kind Value="bpkSource"/>
+        <WatchScope Value="wpsLocal"/>
+        <WatchKind Value="wpkWrite"/>
+        <Source Value="D:\Lazarus\fpcsrc\packages\fcl-json\src\fpjsonrtti.pp"/>
+        <Line Value="736"/>
+      </Item2>
+      <Item3>
+        <Kind Value="bpkSource"/>
+        <WatchScope Value="wpsLocal"/>
+        <WatchKind Value="wpkWrite"/>
+        <Source Value="D:\Lazarus\fpcsrc\packages\fcl-json\src\fpjsonrtti.pp"/>
+        <Line Value="844"/>
+      </Item3>
+    </BreakPoints>
+  </Debugging>
+</CONFIG>

+ 39 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/umain.lfm

@@ -0,0 +1,39 @@
+object Form1: TForm1
+  Left = 379
+  Height = 433
+  Top = 229
+  Width = 592
+  Caption = 'Form1'
+  ClientHeight = 433
+  ClientWidth = 592
+  OnClose = FormClose
+  OnCreate = FormCreate
+  LCLVersion = '1.9.0.0'
+  object btnSaveJson: TButton
+    Left = 456
+    Height = 25
+    Top = 384
+    Width = 107
+    Caption = 'Save to Json'
+    OnClick = btnSaveJsonClick
+    TabOrder = 0
+  end
+  object btnLoadJson: TButton
+    Left = 336
+    Height = 25
+    Top = 384
+    Width = 107
+    Caption = 'Load From Json'
+    OnClick = btnLoadJsonClick
+    TabOrder = 1
+  end
+  object meInfo: TMemo
+    Left = 19
+    Height = 363
+    Top = 9
+    Width = 549
+    ReadOnly = True
+    ScrollBars = ssAutoBoth
+    TabOrder = 2
+  end
+end

+ 186 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/umain.pas

@@ -0,0 +1,186 @@
+unit uMain;
+
+{$mode delphi}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
+  Quick.Config,
+  //Quick.Config.Provider.Registry,
+  Generics.Collections,
+  Quick.Config.Provider.Json;
+
+type
+
+  TMyPriority = (msLow, msMed, msHigh);
+
+  TWinPos = record
+    PosX : Integer;
+    PosY : Integer;
+  end;
+
+  TProcessType = record
+    Id : Integer;
+    Priority : TMyPriority;
+    Redundant : Boolean;
+  end;
+
+  TWorker = class
+    Name : string;
+    Active : Boolean;
+  end;
+
+  {$M+} TMyConfig2 = class(TAppConfig)
+  private
+    fhola : Integer;
+  published
+    property hola : Integer read fhola write fhola;
+  end;
+
+  {$M+} TMyConfig = class(TAppConfig)
+  private
+    fTitle : string;
+    fHidden : Boolean;
+    fSessionName: string;
+  public
+    Sizes : array of Integer;
+    LastFilename : string;
+    WindowPos : TWinPos;
+    History : array of TProcessType;
+    Complex : TProcessType;
+    ModifyDate : TDateTime;
+    WorkList : TObjectList<TWorker>;
+    constructor Create; override;
+    destructor Destroy; override;
+    procedure DefaultValues;
+    property Title : string read fTitle write fTitle;
+    property SessionName : string read fSessionName write fSessionName;
+  end;
+
+  { TForm1 }
+
+  TForm1 = class(TForm)
+    btnSaveJson: TButton;
+    btnLoadJson: TButton;
+    meInfo: TMemo;
+    procedure btnLoadJsonClick(Sender: TObject);
+    procedure btnSaveJsonClick(Sender: TObject);
+    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
+    procedure FormCreate(Sender: TObject);
+  private
+
+  public
+    procedure SetConfig(cConfig: TMyConfig);
+    function TestConfig(cConfig1, cConfig2 : TMyConfig) : Boolean;
+
+  end;
+
+var
+  Form1: TForm1;
+  ConfigJson : TMyConfig;
+  ConfigJson2 : TMyConfig2;
+  ConfigReg : TMyConfig;
+  ConfigTest : TMyConfig;
+  AppConfigJson : TAppConfigJsonProvider<TMyConfig2>;
+  //AppConfigReg : TAppConfigRegistryProvider<TMyConfig>;
+
+implementation
+
+{$R *.lfm}
+
+{ TForm1 }
+
+procedure TForm1.btnSaveJsonClick(Sender: TObject);
+begin
+  SetConfig(ConfigJson);
+  AppConfigJson.Save(ConfigJson2);
+  meInfo.Lines.Add('Saved Config in Json at ' + DateTimeToStr(ConfigJson.LastSaved));
+end;
+
+procedure TForm1.btnLoadJsonClick(Sender: TObject);
+begin
+  meInfo.Lines.Add('Load ConfigJson');
+  AppConfigJson.Load(ConfigJson2);
+  meInfo.Lines.Add(ConfigJson.ToJSON);
+  if TestConfig(ConfigTest,ConfigJson) then meInfo.Lines.Add('Test passed successfully!');
+end;
+
+function  TForm1.TestConfig(cConfig1, cConfig2 : TMyConfig) : Boolean;
+var
+  i : Integer;
+begin
+  try
+    Assert(cConfig1.LastFilename = cConfig2.LastFilename);
+    for i := Low(cConfig1.Sizes) to High(cConfig1.Sizes) do
+      Assert(cConfig1.Sizes[i] = cConfig2.Sizes[i]);
+    Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
+    Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
+    Assert(cConfig1.Complex.Priority = cConfig2.Complex.Priority);
+    Assert(cConfig1.Complex.Redundant  = cConfig2.Complex.Redundant);
+    Assert(cConfig1.Title = cConfig2.Title);
+    for i := 0 to cConfig1.WorkList.Count - 1 do
+    begin
+      Assert(cConfig1.WorkList[i].Name = cConfig2.WorkList[i].Name);
+      Assert(cConfig1.WorkList[i].Active = cConfig2.WorkList[i].Active);
+    end;
+    for i := 0 to High(cConfig1.History) do
+    begin
+      Assert(cConfig1.History[i].Priority = cConfig2.History[i].Priority);
+      Assert(cConfig1.History[i].Redundant = cConfig2.History[i].Redundant);
+    end;
+    Result := True;
+  except
+    ShowMessage('Configuration not has been saved previously or has a corruption problem');
+  end;
+end;
+
+
+procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
+begin
+  if Assigned(AppConfigJson) then AppConfigJson.Free;
+  //if Assigned(AppConfigReg) then AppConfigReg.Free;
+  if Assigned(ConfigTest) then ConfigTest.Free;
+  if Assigned(ConfigReg) then ConfigReg.Free;
+  if Assigned(ConfigJson) then ConfigJson.Free;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+  ConfigTest := TMyConfig.Create;
+  SetConfig(ConfigTest);
+  AppConfigJson := TAppConfigJsonProvider<TMyConfig2>.Create(ConfigJson2);
+  AppConfigJson.CreateIfNotExists := True;
+  AppConfigJson.Filename := 'Config.json';
+  //AppConfigReg := TAppConfigRegistryProvider<TMyConfig>.Create(ConfigReg);
+  //AppConfigReg.HRoot := HKEY_CURRENT_USER;
+  //AppConfigReg.MainKey := '_AppConfig';
+end;
+
+procedure TForm1.SetConfig(cConfig: TMyConfig);
+begin
+
+end;
+
+{ TMyConfig }
+
+constructor TMyConfig.Create;
+begin
+  inherited;
+  WorkList := TObjectList<TWorker>.Create(True);
+  DefaultValues;
+end;
+
+procedure TMyConfig.DefaultValues;
+begin
+  fTitle := 'Default value';
+end;
+
+destructor TMyConfig.Destroy;
+begin
+  if Assigned(WorkList) then WorkList.Free;
+  inherited;
+end;
+
+end.
+

二进制
samples/fpc/QuickConfig/ConfigToFileAndRegistry/lib/i386-win32/QuickConfig.or


二进制
samples/fpc/QuickConfig/ConfigToFileAndRegistry/lib/i386-win32/QuickConfig.res


二进制
samples/fpc/QuickConfig/ConfigToFileAndRegistry/lib/i386-win32/QuickConfigDemo.or


二进制
samples/fpc/QuickConfig/ConfigToFileAndRegistry/lib/i386-win32/QuickConfigDemo.res


+ 39 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/lib/i386-win32/umain.lfm

@@ -0,0 +1,39 @@
+object Form1: TForm1
+  Left = 379
+  Height = 433
+  Top = 229
+  Width = 592
+  Caption = 'Form1'
+  ClientHeight = 433
+  ClientWidth = 592
+  OnClose = FormClose
+  OnCreate = FormCreate
+  LCLVersion = '1.9.0.0'
+  object btnSaveJson: TButton
+    Left = 456
+    Height = 25
+    Top = 384
+    Width = 107
+    Caption = 'Save to Json'
+    OnClick = btnSaveJsonClick
+    TabOrder = 0
+  end
+  object btnLoadJson: TButton
+    Left = 336
+    Height = 25
+    Top = 384
+    Width = 107
+    Caption = 'Load From Json'
+    OnClick = btnLoadJsonClick
+    TabOrder = 1
+  end
+  object meInfo: TMemo
+    Left = 19
+    Height = 363
+    Top = 9
+    Width = 549
+    ReadOnly = True
+    ScrollBars = ssAutoBoth
+    TabOrder = 2
+  end
+end

+ 39 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/umain.lfm

@@ -0,0 +1,39 @@
+object Form1: TForm1
+  Left = 379
+  Height = 433
+  Top = 229
+  Width = 592
+  Caption = 'Form1'
+  ClientHeight = 433
+  ClientWidth = 592
+  OnClose = FormClose
+  OnCreate = FormCreate
+  LCLVersion = '1.9.0.0'
+  object btnSaveJson: TButton
+    Left = 456
+    Height = 25
+    Top = 384
+    Width = 107
+    Caption = 'Save to Json'
+    OnClick = btnSaveJsonClick
+    TabOrder = 0
+  end
+  object btnLoadJson: TButton
+    Left = 336
+    Height = 25
+    Top = 384
+    Width = 107
+    Caption = 'Load From Json'
+    OnClick = btnLoadJsonClick
+    TabOrder = 1
+  end
+  object meInfo: TMemo
+    Left = 19
+    Height = 363
+    Top = 9
+    Width = 549
+    ReadOnly = True
+    ScrollBars = ssAutoBoth
+    TabOrder = 2
+  end
+end

+ 186 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/umain.pas

@@ -0,0 +1,186 @@
+unit uMain;
+
+{$mode delphi}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
+  Quick.Config,
+  //Quick.Config.Provider.Registry,
+  Generics.Collections,
+  Quick.Config.Provider.Json;
+
+type
+
+  TMyPriority = (msLow, msMed, msHigh);
+
+  TWinPos = record
+    PosX : Integer;
+    PosY : Integer;
+  end;
+
+  TProcessType = record
+    Id : Integer;
+    Priority : TMyPriority;
+    Redundant : Boolean;
+  end;
+
+  TWorker = class
+    Name : string;
+    Active : Boolean;
+  end;
+
+  TMyConfig2 = class(TAppConfig)
+  private
+    fhola : Integer;
+  published
+    property hola : Integer read fhola write fhola;
+  end;
+
+  TMyConfig = class(TAppConfig)
+  private
+    fTitle : string;
+    fHidden : Boolean;
+    fSessionName: string;
+  public
+    Sizes : array of Integer;
+    LastFilename : string;
+    WindowPos : TWinPos;
+    History : array of TProcessType;
+    Complex : TProcessType;
+    ModifyDate : TDateTime;
+    WorkList : TObjectList<TWorker>;
+    constructor Create; override;
+    destructor Destroy; override;
+    procedure DefaultValues;
+    property Title : string read fTitle write fTitle;
+    property SessionName : string read fSessionName write fSessionName;
+  end;
+
+  { TForm1 }
+
+  TForm1 = class(TForm)
+    btnSaveJson: TButton;
+    btnLoadJson: TButton;
+    meInfo: TMemo;
+    procedure btnLoadJsonClick(Sender: TObject);
+    procedure btnSaveJsonClick(Sender: TObject);
+    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
+    procedure FormCreate(Sender: TObject);
+  private
+
+  public
+    procedure SetConfig(cConfig: TMyConfig);
+    function TestConfig(cConfig1, cConfig2 : TMyConfig) : Boolean;
+
+  end;
+
+var
+  Form1: TForm1;
+  ConfigJson : TMyConfig;
+  ConfigJson2 : TMyConfig2;
+  ConfigReg : TMyConfig;
+  ConfigTest : TMyConfig;
+  AppConfigJson : TAppConfigJsonProvider<TMyConfig2>;
+  //AppConfigReg : TAppConfigRegistryProvider<TMyConfig>;
+
+implementation
+
+{$R *.lfm}
+
+{ TForm1 }
+
+procedure TForm1.btnSaveJsonClick(Sender: TObject);
+begin
+  SetConfig(ConfigJson);
+  AppConfigJson.Save(ConfigJson2);
+  meInfo.Lines.Add('Saved Config in Json at ' + DateTimeToStr(ConfigJson.LastSaved));
+end;
+
+procedure TForm1.btnLoadJsonClick(Sender: TObject);
+begin
+  meInfo.Lines.Add('Load ConfigJson');
+  AppConfigJson.Load(ConfigJson2);
+  meInfo.Lines.Add(ConfigJson.ToJSON);
+  if TestConfig(ConfigTest,ConfigJson) then meInfo.Lines.Add('Test passed successfully!');
+end;
+
+function  TForm1.TestConfig(cConfig1, cConfig2 : TMyConfig) : Boolean;
+var
+  i : Integer;
+begin
+  try
+    Assert(cConfig1.LastFilename = cConfig2.LastFilename);
+    for i := Low(cConfig1.Sizes) to High(cConfig1.Sizes) do
+      Assert(cConfig1.Sizes[i] = cConfig2.Sizes[i]);
+    Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
+    Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
+    Assert(cConfig1.Complex.Priority = cConfig2.Complex.Priority);
+    Assert(cConfig1.Complex.Redundant  = cConfig2.Complex.Redundant);
+    Assert(cConfig1.Title = cConfig2.Title);
+    for i := 0 to cConfig1.WorkList.Count - 1 do
+    begin
+      Assert(cConfig1.WorkList[i].Name = cConfig2.WorkList[i].Name);
+      Assert(cConfig1.WorkList[i].Active = cConfig2.WorkList[i].Active);
+    end;
+    for i := 0 to High(cConfig1.History) do
+    begin
+      Assert(cConfig1.History[i].Priority = cConfig2.History[i].Priority);
+      Assert(cConfig1.History[i].Redundant = cConfig2.History[i].Redundant);
+    end;
+    Result := True;
+  except
+    ShowMessage('Configuration not has been saved previously or has a corruption problem');
+  end;
+end;
+
+
+procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
+begin
+  if Assigned(AppConfigJson) then AppConfigJson.Free;
+  //if Assigned(AppConfigReg) then AppConfigReg.Free;
+  if Assigned(ConfigTest) then ConfigTest.Free;
+  if Assigned(ConfigReg) then ConfigReg.Free;
+  if Assigned(ConfigJson) then ConfigJson.Free;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+  ConfigTest := TMyConfig.Create;
+  SetConfig(ConfigTest);
+  AppConfigJson := TAppConfigJsonProvider<TMyConfig2>.Create(ConfigJson2);
+  AppConfigJson.CreateIfNotExists := True;
+  AppConfigJson.Filename := 'Config.json';
+  //AppConfigReg := TAppConfigRegistryProvider<TMyConfig>.Create(ConfigReg);
+  //AppConfigReg.HRoot := HKEY_CURRENT_USER;
+  //AppConfigReg.MainKey := '_AppConfig';
+end;
+
+procedure TForm1.SetConfig(cConfig: TMyConfig);
+begin
+
+end;
+
+{ TMyConfig }
+
+constructor TMyConfig.Create;
+begin
+  inherited;
+  WorkList := TObjectList<TWorker>.Create(True);
+  DefaultValues;
+end;
+
+procedure TMyConfig.DefaultValues;
+begin
+  fTitle := 'Default value';
+end;
+
+destructor TMyConfig.Destroy;
+begin
+  if Assigned(WorkList) then WorkList.Free;
+  inherited;
+end;
+
+end.
+

+ 62 - 0
samples/fpc/QuickConsole/ConsoleMenu/ConsoleMenu.lpi

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasScaledStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="Console Menu"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0"/>
+    </RunParams>
+    <RequiredPackages Count="1">
+      <Item1>
+        <PackageName Value="QuickLib"/>
+      </Item1>
+    </RequiredPackages>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="ConsoleMenu.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="ConsoleMenu"/>
+    </Target>
+    <SearchPaths>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 37 - 0
samples/fpc/QuickConsole/ConsoleMenu/ConsoleMenu.lps

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectSession>
+    <PathDelim Value="\"/>
+    <Version Value="11"/>
+    <BuildModes Active="Default"/>
+    <Units Count="2">
+      <Unit0>
+        <Filename Value="ConsoleMenu.pas"/>
+        <IsPartOfProject Value="True"/>
+        <IsVisibleTab Value="True"/>
+        <EditorIndex Value="-1"/>
+        <CursorPos X="48" Y="12"/>
+        <UsageCount Value="20"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="..\..\..\Quick.Console.pas"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="85"/>
+        <CursorPos X="3" Y="89"/>
+        <UsageCount Value="10"/>
+      </Unit1>
+    </Units>
+    <JumpHistory HistoryIndex="-1"/>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0" ActiveMode=""/>
+    </RunParams>
+  </ProjectSession>
+  <Debugging>
+    <Watches Count="1">
+      <Item1>
+        <Expression Value="EventType"/>
+      </Item1>
+    </Watches>
+  </Debugging>
+</CONFIG>

+ 79 - 0
samples/fpc/QuickConsole/ConsoleMenu/ConsoleMenu.pas

@@ -0,0 +1,79 @@
+program ConsoleMenu;
+
+{$APPTYPE CONSOLE}
+
+{$MODE DELPHI}
+
+{$R *.res}
+
+uses
+  SysUtils,
+  Windows,
+  Quick.Commons,
+  Quick.Console;
+
+type
+  TTest = class
+    class procedure Option1;
+    class procedure Option2;
+    class procedure Option3;
+    class procedure Option4;
+    class procedure Option5;
+  end;
+
+var
+  conmenu : TConsoleMenu;
+  Test : TTest;
+  menuop : TConsoleMenuOption;
+  i : Integer;
+
+{ TTest }
+
+class procedure TTest.Option1;
+begin
+  coutXY(10,10,'Option 1 pressed',etInfo);
+end;
+
+class procedure TTest.Option2;
+begin
+  coutXY(10,10,'Option 2 pressed',etInfo);
+end;
+
+class procedure TTest.Option3;
+begin
+  coutXY(10,10,'Option 3 pressed',etInfo);
+end;
+
+class procedure TTest.Option4;
+begin
+  coutXY(10,10,'Option 4 pressed',etInfo);
+end;
+
+class procedure TTest.Option5;
+begin
+  coutXY(10,10,'Option 5 pressed',etInfo);
+end;
+
+begin
+  try
+    conmenu := TConsoleMenu.Create;
+    menuop.Caption := 'Option 1';
+    menuop.Key := VK_F1;
+    menuop.OnKeyPressed := Test.Option1;
+    conmenu.AddMenu(menuop);
+    conmenu.AddMenu('Option 2',VK_F2,Test.Option2);
+    conmenu.AddMenu('Option 3',VK_F3,Test.Option3);
+
+    conmenu.AddMenu('Option 4',VK_F4,Test.Option4);
+
+    conmenu.AddMenu('Option 5',VK_F5,Test.Option5);
+
+    for i := 0 to 30 do writeln('hola que tal');
+
+    conmenu.WaitForKeys;
+    conmenu.Free;
+  except
+    on E: Exception do
+      Writeln(E.ClassName, ': ', E.Message);
+  end;
+end.

二进制
samples/fpc/QuickConsole/ConsoleMenu/ConsoleMenu.res


+ 62 - 0
samples/fpc/QuickConsole/ConsoleMenu/backup/ConsoleMenu.lpi

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasScaledStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="Console Menu"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0"/>
+    </RunParams>
+    <RequiredPackages Count="1">
+      <Item1>
+        <PackageName Value="QuickLib"/>
+      </Item1>
+    </RequiredPackages>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="ConsoleMenu.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="ConsoleMenu"/>
+    </Target>
+    <SearchPaths>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 38 - 0
samples/fpc/QuickConsole/ConsoleMenu/backup/ConsoleMenu.lps

@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectSession>
+    <PathDelim Value="\"/>
+    <Version Value="11"/>
+    <BuildModes Active="Default"/>
+    <Units Count="2">
+      <Unit0>
+        <Filename Value="ConsoleMenu.pas"/>
+        <IsPartOfProject Value="True"/>
+        <IsVisibleTab Value="True"/>
+        <TopLine Value="50"/>
+        <CursorPos Y="4"/>
+        <UsageCount Value="20"/>
+        <Loaded Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="..\..\..\Quick.Console.pas"/>
+        <EditorIndex Value="-1"/>
+        <TopLine Value="85"/>
+        <CursorPos X="3" Y="89"/>
+        <UsageCount Value="10"/>
+      </Unit1>
+    </Units>
+    <JumpHistory HistoryIndex="-1"/>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0" ActiveMode=""/>
+    </RunParams>
+  </ProjectSession>
+  <Debugging>
+    <Watches Count="1">
+      <Item1>
+        <Expression Value="EventType"/>
+      </Item1>
+    </Watches>
+  </Debugging>
+</CONFIG>

+ 85 - 0
samples/fpc/QuickConsole/ConsoleMenu/backup/ConsoleMenu.pas

@@ -0,0 +1,85 @@
+program ConsoleMenu;
+
+{$APPTYPE CONSOLE}
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF}
+
+{$R *.res}
+
+uses
+  SysUtils,
+  Windows,
+  Quick.Commons,
+  Quick.Console;
+
+type
+  TTest = class
+    class procedure Option1;
+    class procedure Option2;
+    class procedure Option3;
+    class procedure Option4;
+    class procedure Option5;
+  end;
+
+var
+  conmenu : TConsoleMenu;
+  Test : TTest;
+  menuop : TConsoleMenuOption;
+  i : Integer;
+
+{ TTest }
+
+class procedure TTest.Option1;
+begin
+  coutXY(10,10,'Option 1 pressed',etInfo);
+end;
+
+class procedure TTest.Option2;
+begin
+  coutXY(10,10,'Option 2 pressed',etInfo);
+end;
+
+class procedure TTest.Option3;
+begin
+  coutXY(10,10,'Option 3 pressed',etInfo);
+end;
+
+class procedure TTest.Option4;
+begin
+  coutXY(10,10,'Option 4 pressed',etInfo);
+end;
+
+class procedure TTest.Option5;
+begin
+  coutXY(10,10,'Option 5 pressed',etInfo);
+end;
+
+begin
+  try
+    conmenu := TConsoleMenu.Create;
+    menuop.Caption := 'Option 1';
+    menuop.Key := VK_F1;
+    menuop.OnKeyPressed := Test.Option1;
+    conmenu.AddMenu(menuop);
+    conmenu.AddMenu('Option 2',VK_F2,Test.Option2);
+    conmenu.AddMenu('Option 3',VK_F3,Test.Option3);
+
+    conmenu.AddMenu('Option 4',VK_F4,Test.Option4);
+
+    conmenu.AddMenu('Option 5',VK_F5,{$IFDEF FPC}Test.Option5);{$ELSE}procedure
+                                 begin
+                                   coutXY(10,10,'Option 5 pressed',etInfo);
+                                 end);
+                                 {$ENDIF}
+
+    for i := 0 to 30 do writeln('hola que tal');
+
+    conmenu.WaitForKeys;
+    conmenu.Free;
+  except
+    on E: Exception do
+      Writeln(E.ClassName, ': ', E.Message);
+  end;
+end.

二进制
samples/fpc/QuickConsole/ConsoleMenu/lib/i386-win32/ConsoleMenu.or


二进制
samples/fpc/QuickConsole/ConsoleMenu/lib/i386-win32/ConsoleMenu.res


+ 62 - 0
samples/fpc/QuickConsole/ConsoleOut/ConsoleOut.lpi

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasScaledStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="ConsoleDemo"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0"/>
+    </RunParams>
+    <RequiredPackages Count="1">
+      <Item1>
+        <PackageName Value="QuickLib"/>
+      </Item1>
+    </RequiredPackages>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="ConsoleOut.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="ConsoleOut"/>
+    </Target>
+    <SearchPaths>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 30 - 0
samples/fpc/QuickConsole/ConsoleOut/ConsoleOut.lps

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectSession>
+    <PathDelim Value="\"/>
+    <Version Value="11"/>
+    <BuildModes Active="Default"/>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="ConsoleOut.pas"/>
+        <IsPartOfProject Value="True"/>
+        <IsVisibleTab Value="True"/>
+        <EditorIndex Value="-1"/>
+        <CursorPos Y="4"/>
+        <UsageCount Value="20"/>
+      </Unit0>
+    </Units>
+    <JumpHistory HistoryIndex="-1"/>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0" ActiveMode=""/>
+    </RunParams>
+  </ProjectSession>
+  <Debugging>
+    <Watches Count="1">
+      <Item1>
+        <Expression Value="EventType"/>
+      </Item1>
+    </Watches>
+  </Debugging>
+</CONFIG>

+ 4 - 2
samples/QuickConsole/QuickConsoleSample.dpr → samples/fpc/QuickConsole/ConsoleOut/ConsoleOut.pas

@@ -1,11 +1,13 @@
-program QuickConsoleSample;
+program ConsoleOut;
 
 {$APPTYPE CONSOLE}
 
+{$MODE DELPHI}
+
 {$R *.res}
 
 uses
-  System.SysUtils,
+  SysUtils,
   Quick.Commons,
   Quick.Console;
 

二进制
samples/fpc/QuickConsole/ConsoleOut/ConsoleOut.res


+ 35 - 0
samples/fpc/QuickConsole/ConsoleOut/backup/ConsoleOut.lps

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectSession>
+    <PathDelim Value="\"/>
+    <Version Value="11"/>
+    <BuildModes Active="Default"/>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="ConsoleOut.pas"/>
+        <IsPartOfProject Value="True"/>
+        <IsVisibleTab Value="True"/>
+        <CursorPos Y="4"/>
+        <UsageCount Value="20"/>
+        <Loaded Value="True"/>
+      </Unit0>
+    </Units>
+    <JumpHistory Count="1">
+      <Position1>
+        <Filename Value="ConsoleOut.pas"/>
+        <Caret Line="12" Column="12"/>
+      </Position1>
+    </JumpHistory>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0" ActiveMode=""/>
+    </RunParams>
+  </ProjectSession>
+  <Debugging>
+    <Watches Count="1">
+      <Item1>
+        <Expression Value="EventType"/>
+      </Item1>
+    </Watches>
+  </Debugging>
+</CONFIG>

+ 32 - 0
samples/fpc/QuickConsole/ConsoleOut/backup/ConsoleOut.pas

@@ -0,0 +1,32 @@
+program ConsoleOut;
+
+{$APPTYPE CONSOLE}
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF}
+
+{$R *.res}
+
+uses
+  SysUtils,
+  Quick.Commons,
+  Quick.Console;
+
+begin
+  try
+    coutXY(20,10,'this line will be replaced by the next',etInfo);
+    coutXY(20,10,'this line replaces previous',etSuccess);
+    cout('Normal line 1',etInfo);
+    coutBL('bottom line: 1',etInfo);
+    cout('Normal line 2',etInfo);
+    coutXY(10,5,'I''m here',etSuccess);
+    coutBL('bottom line: 2',etInfo);
+    cout('Normal line 3',etInfo);
+    coutBL('bottomline: 3',etInfo);
+    ConsoleWaitForEnterKey;
+  except
+    on E: Exception do
+      Writeln(E.ClassName, ': ', E.Message);
+  end;
+end.

部分文件因为文件数量过多而无法显示