From 61b3c04515da4f8f30cf28d77ab39b4c9c6e6f0d Mon Sep 17 00:00:00 2001 From: Jacek Date: Mon, 13 Apr 2020 00:52:35 +0200 Subject: [PATCH] [+] Compatibility with Delphi 2009. 2010, XE --- Base/JPL.CmdLineParser.pas | 16 +- Base/JPL.Console.ColorParser.pas | 7 +- Base/JPL.Console.pas | 9 +- Base/JPL.ConsoleApp.pas | 16 +- Base/JPL.Conversion.pas | 23 +- Base/JPL.DateTime.pas | 21 +- Base/JPL.Dialogs.pas | 10 +- Base/JPL.FileSearch.pas | 4 +- Base/JPL.FileSearcher.pas | 8 +- Base/JPL.Files.pas | 11 + Base/JPL.IniFile.pas | 267 ++++++-- Base/JPL.LangMgr.pas | 28 +- Base/JPL.Language.pas | 5 +- Base/JPL.MemIniFile.pas | 52 +- Base/JPL.RTTI.pas | 23 +- Base/JPL.StrHash.pas | 2 + Base/JPL.Strings.Ext.pas | 4 +- Base/JPL.Strings.pas | 72 +- Base/JPL.TStringsHelper.pas | 128 ++++ Base/JPL.Win.Dialogs.pas | 12 +- Base/JPL.Win.FileSystem.pas | 626 ++---------------- Base/JPL.Win.Processes.pas | 31 +- Base/JPL.Win.Shortcuts.pas | 17 +- Base/JPL.Win.System.pas | 56 +- Base/JPL.Win.VersionInfo.pas | 33 +- Binary/JPL.Binary.Elf.pas | 30 +- Binary/JPL.Binary.Mach.Types.pas | 5 +- Binary/JPL.Binary.MachFat.pas | 27 +- Binary/JPL.Binary.MachO.pas | 20 +- Binary/JPL.Binary.Misc.pas | 9 + Binary/JPL.Binary.Pe.pas | 23 +- Binary/JPL.Binary.Procs.pas | 19 +- Binary/JPL.Binary.Types.pas | 85 ++- Binary/JPL.UPX.pas | 19 +- Containers/JPL.StrList.pas | 8 + ...PL.FileIcons.pas => JPL.Win.FileIcons.pas} | 25 +- Graphics/JPL.ColorArrays.pas | 11 +- Graphics/JPL.Colors.ColorClass.pas | 9 +- Graphics/JPL.Colors.List.pas | 13 +- Graphics/JPL.Colors.pas | 34 +- Hash/JPL.Hash.CRC32.pas | 218 ------ Hash/JPL.Hash.Common.pas | 4 + Hash/JPL.Hash.HL_MD2.pas | 6 +- Hash/JPL.Hash.HL_RipeMD.pas | 2 +- Hash/JPL.Hash.HL_RipeMD128.pas | 2 +- Hash/JPL.Hash.HL_RipeMD256.pas | 2 +- Hash/JPL.Hash.HL_RipeMD320.pas | 2 +- Hash/JPL.Hash.HL_Sha0.pas | 2 +- Hash/JPL.Hash.HL_Snefru128.pas | 2 +- Hash/JPL.Hash.HL_Snefru256.pas | 2 +- JppFPC.inc | 41 -- Logging/JPL.SimpleLogger.pas | 11 +- Logging/JPL.TimeLogger.pas | 7 +- jp.inc | 111 ++++ packages/CodeTyphon/jplib.ctpkg | 159 +++-- packages/CodeTyphon/jplib.pas | 7 +- packages/Delphi_10.0_Seattle/JPLib.dpk | 16 +- packages/Delphi_10.1_Berlin/JPLib.dpk | 16 +- packages/Delphi_10.2_Tokyo/JPLib.dpk | 16 +- packages/Delphi_10.3_Rio/JPLib.dpk | 16 +- packages/Delphi_10.3_Rio/JPLib.dproj | 11 +- packages/Delphi_2009/JPLib.dpk | 96 +++ packages/Delphi_2009/JPLib.dproj | 127 ++++ packages/Delphi_2009/JPLib.res | Bin 0 -> 4396 bytes packages/Delphi_2010/JPLib.dpk | 96 +++ packages/Delphi_2010/JPLib.dproj | 146 ++++ packages/Delphi_2010/JPLib.res | Bin 0 -> 4396 bytes packages/Delphi_XE/JPLib.dpk | 96 +++ packages/Delphi_XE/JPLib.dproj | 149 +++++ packages/Delphi_XE/JPLib.res | Bin 0 -> 91336 bytes packages/Delphi_XE2/JPLib.dpk | 16 +- packages/Delphi_XE2/JPLib.dproj | 11 +- packages/Delphi_XE3/JPLib.dpk | 16 +- packages/Delphi_XE3/JPLib.dproj | 11 +- packages/Delphi_XE4/JPLib.dpk | 16 +- packages/Delphi_XE4/JPLib.dproj | 11 +- packages/Delphi_XE5/JPLib.dpk | 16 +- packages/Delphi_XE5/JPLib.dproj | 11 +- packages/Delphi_XE6/JPLib.dpk | 16 +- packages/Delphi_XE6/JPLib.dproj | 11 +- packages/Delphi_XE7/JPLib.dpk | 16 +- packages/Delphi_XE7/JPLib.dproj | 31 +- packages/Delphi_XE8/JPLib.dpk | 16 +- packages/Lazarus/jplib.lpk | 119 ++-- packages/Lazarus/jplib.pas | 14 +- packages/_DpkGen/JPLib_TEMPLATE.dpk | 16 +- packages/_DpkGen/Readme.md | 203 ++++++ packages/_DpkGen/generate_packages.bat | 7 +- 88 files changed, 2369 insertions(+), 1369 deletions(-) create mode 100644 Base/JPL.TStringsHelper.pas rename Containers/{JPL.FileIcons.pas => JPL.Win.FileIcons.pas} (92%) delete mode 100644 Hash/JPL.Hash.CRC32.pas delete mode 100644 JppFPC.inc create mode 100644 jp.inc create mode 100644 packages/Delphi_2009/JPLib.dpk create mode 100644 packages/Delphi_2009/JPLib.dproj create mode 100644 packages/Delphi_2009/JPLib.res create mode 100644 packages/Delphi_2010/JPLib.dpk create mode 100644 packages/Delphi_2010/JPLib.dproj create mode 100644 packages/Delphi_2010/JPLib.res create mode 100644 packages/Delphi_XE/JPLib.dpk create mode 100644 packages/Delphi_XE/JPLib.dproj create mode 100644 packages/Delphi_XE/JPLib.res create mode 100644 packages/_DpkGen/Readme.md diff --git a/Base/JPL.CmdLineParser.pas b/Base/JPL.CmdLineParser.pas index e0b6ec3..307a6c4 100644 --- a/Base/JPL.CmdLineParser.pas +++ b/Base/JPL.CmdLineParser.pas @@ -16,7 +16,8 @@ } -{$IFDEF FPC} {$mode objfpc}{$H+} {$ENDIF} +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE OBJFPC}{$H+}{$ENDIF} {:<@include(..\doc\unit_JP.CmdLineParser.txt)} @@ -55,8 +56,9 @@ interface type - - //TArray = array of T; // Delphi 2009 + {$IFDEF DELPHI2009_OR_BELOW} + TArray = array of T; + {$ENDIF} TClpParsingMode = (cpmCustom, cpmDelphi); { TODO: Zablokować cpmCustom dla Linuksa. Na razie działa prawidłowo tylko na Windowsie. } { Does the CommandLineToArgvW equivalent for Linux exists? } @@ -357,7 +359,8 @@ procedure SplitStrToArray(s: string; var Arr: {$IFDEF FPC}specialize{$ENDIF} TAr while x > 0 do begin SetLength(Arr, Length(Arr) + 1); - Arr[High(Arr)] := Copy(s, 1, x - 1); +// Arr[High(Arr)] := Copy(s, 1, x - 1); + Arr[Length(Arr) - 1] := Copy(s, 1, x - 1); s := Copy(s, x + Length(EndLineStr), Length(s)); x := Pos(EndLineStr, s); end; @@ -365,7 +368,8 @@ procedure SplitStrToArray(s: string; var Arr: {$IFDEF FPC}specialize{$ENDIF} TAr if s <> '' then begin SetLength(Arr, Length(Arr) + 1); - Arr[High(Arr)] := s; +// Arr[High(Arr)] := s; + Arr[Length(Arr) - 1] := s; end; end; {$endregion copied from JPL units} @@ -1923,7 +1927,7 @@ function ParamTypeToStr(const ParamType: TClpParamType): string; cptStopMarker: Result := 'StopParsingSwitch'; cptString: Result := 'String'; else - Result := '?'; + Result := '?'{%H-}; end; end; {$endregion ParamTypeToStr} diff --git a/Base/JPL.Console.ColorParser.pas b/Base/JPL.Console.ColorParser.pas index c621795..998d704 100644 --- a/Base/JPL.Console.ColorParser.pas +++ b/Base/JPL.Console.ColorParser.pas @@ -64,10 +64,9 @@ } -{$IFDEF FPC} - {$mode objfpc}{$H+} -{$ENDIF} -//{$MODESWITCH ADVANCEDRECORDS} + +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE OBJFPC}{$H+}{$ENDIF} interface diff --git a/Base/JPL.Console.pas b/Base/JPL.Console.pas index c11400b..f08bf8b 100644 --- a/Base/JPL.Console.pas +++ b/Base/JPL.Console.pas @@ -80,6 +80,8 @@ } +{$I .\..\jp.inc} + {$IFDEF FPC} {$mode objfpc}{$H+} {$MODESWITCH ADVANCEDRECORDS} @@ -234,8 +236,10 @@ TConsole = record class procedure SetOutputCodePage(AValue: UINT); static; {$ENDIF} + {$IF Defined(FPC) or Defined(DELPHIXE2_OR_ABOVE)} class function GetTextCodePage: Cardinal; static; class procedure SetTextCodePage(AValue: Cardinal); static; + {$IFEND} public {$region ' colors '} @@ -369,7 +373,9 @@ TConsole = record class property OriginalOutputCodePage: UINT read FOriginalOutputCodePage; class property OutputCodePage: UINT read GetOutputCodePage write SetOutputCodePage; {$ENDIF} + {$IF Defined(FPC) or Defined(DELPHIXE2_OR_ABOVE)} class property TextCodePage: Cardinal read GetTextCodePage write SetTextCodePage; + {$IFEND} end; @@ -1169,6 +1175,7 @@ class function TConsole.RestoreOriginalOutputCodePage: Boolean; end; {$ENDIF} +{$IF Defined(FPC) or Defined(DELPHIXE2_OR_ABOVE)} class procedure TConsole.SetTextCodePage(AValue: Cardinal); {$IFDEF FPC}static;{$ENDIF} begin System.SetTextCodePage(Output, AValue); @@ -1178,7 +1185,7 @@ class function TConsole.GetTextCodePage: Cardinal; begin Result := System.GetTextCodePage(Output); end; - +{$IFEND} class procedure TConsole.ResetColors; begin diff --git a/Base/JPL.ConsoleApp.pas b/Base/JPL.ConsoleApp.pas index 8596f9e..fff8636 100644 --- a/Base/JPL.ConsoleApp.pas +++ b/Base/JPL.ConsoleApp.pas @@ -6,6 +6,8 @@ Last mod: 2018.03.18 } +{$I .\..\jp.inc} + {$IFDEF FPC} {$mode objfpc}{$H+} {$ENDIF} @@ -16,7 +18,7 @@ interface uses {$IFDEF MSWINDOWS} Windows, ShellApi, {$ENDIF} - SysUtils, + SysUtils, Types, JPL.Strings, JPL.Console, JPL.SimpleLogger, @@ -379,7 +381,11 @@ procedure TJPConsoleApp.DisplayShortUsage; procedure TJPConsoleApp.DisplayTaggedText(const TaggedText: string); var + {$IFDEF DELPHI2009_OR_BELOW} + Arr: TStringDynArray; + {$ELSE} Arr: {$IFDEF DCC}TArray; {$ELSE}TStringArray; {$ENDIF} + {$ENDIF} i: integer; s: string; begin @@ -389,7 +395,7 @@ procedure TJPConsoleApp.DisplayTaggedText(const TaggedText: string); Exit; end; - SplitStrToArray(TaggedText, Arr); + JPL.Strings.SplitStrToArray(TaggedText, Arr{%H-}); for i := 0 to High(Arr) do begin s := Arr[i]; @@ -435,13 +441,17 @@ procedure TJPConsoleApp.Display(bBanner, bShortUsage, bUsage, bExtraInfo, bExamp procedure TJPConsoleApp.DisplayColoredText(const s: string; const cc: TConsoleColors); var + {$IFDEF DELPHI2009_OR_BELOW} + Arr: TStringDynArray; + {$ELSE} Arr: {$IFDEF FPC}array of string;{$ELSE}TArray;{$ENDIF} + {$ENDIF} i: integer; s2: string; begin if UseColors then begin - SplitStrToArray(s, Arr); + JPL.Strings.SplitStrToArray(s, Arr{%H-}); for i := 0 to High(Arr) do begin s2 := Arr[i]; diff --git a/Base/JPL.Conversion.pas b/Base/JPL.Conversion.pas index 1fc4edf..4336630 100644 --- a/Base/JPL.Conversion.pas +++ b/Base/JPL.Conversion.pas @@ -9,8 +9,9 @@ } +{$I .\..\jp.inc} + {$IFDEF FPC} - {$I JppFPC.Inc} {$mode objfpc}{$H+} {$ENDIF} @@ -420,22 +421,22 @@ function IsValidFloat(const s: string): Boolean; function TryStoF(s: string; var x: Double): Boolean; overload; begin - s := StringReplace(s, ',', FormatSettings.DecimalSeparator{%H-}, [rfReplaceAll]); - s := StringReplace(s, '.', FormatSettings.DecimalSeparator{%H-}, [rfReplaceAll]); + s := StringReplace(s, ',', GetDecimalSeparator{%H-}, [rfReplaceAll]); + s := StringReplace(s, '.', GetDecimalSeparator{%H-}, [rfReplaceAll]); Result := TryStrToFloat(s, x); end; function TryStoF(s: string; var x: Single): Boolean; overload; begin - s := StringReplace(s, ',', FormatSettings.DecimalSeparator{%H-}, [rfReplaceAll]); - s := StringReplace(s, '.', FormatSettings.DecimalSeparator{%H-}, [rfReplaceAll]); + s := StringReplace(s, ',', GetDecimalSeparator{%H-}, [rfReplaceAll]); + s := StringReplace(s, '.', GetDecimalSeparator{%H-}, [rfReplaceAll]); Result := TryStrToFloat(s, x); end; function stof(s: string; ErrorValue: Real): Real; begin - s := StringReplace(s, ',', FormatSettings.DecimalSeparator, [rfReplaceAll]); - s := StringReplace(s, '.', FormatSettings.DecimalSeparator, [rfReplaceAll]); + s := StringReplace(s, ',', GetDecimalSeparator, [rfReplaceAll]); + s := StringReplace(s, '.', GetDecimalSeparator, [rfReplaceAll]); try Result := StrToFloat(s); except @@ -463,8 +464,8 @@ function ftos(xr: Extended; RoundTo: integer = 2; DSep: string = ''): string; Delete(s, i, 1); end; end; - if s[Length(s)] = FormatSettings.DecimalSeparator then Delete(s, Length(s), 1); - if DSep <> '' then s := StringReplace(s, FormatSettings.DecimalSeparator, DSep, []); + if s[Length(s)] = GetDecimalSeparator then Delete(s, Length(s), 1); + if DSep <> '' then s := StringReplace(s, GetDecimalSeparator, DSep, []); Result := s; end; @@ -473,7 +474,7 @@ function ftosEx(xr: Extended; Format: string = '0.00'; DecSeparator: string = '. xp, i, Len, k: integer; begin Result := FormatFloat(Format, xr); - Result := StringReplace(Result, FormatSettings.DecimalSeparator, DecSeparator, []); + Result := StringReplace(Result, GetDecimalSeparator, DecSeparator, []); xp := Pos(DecSeparator, Result); if xp = 0 then xp := Length(Result); @@ -581,7 +582,7 @@ function TryBinToInt(BinStr: string; var xInt: Int64): Boolean; x := Pos('1', BinStr); Deleted := Deleted + x; SetLength(arr, Length(arr) + 1); - arr[Length(arr) - 1] := LengthBin - Deleted; + arr[Length(arr) - 1] := Int64(LengthBin) - Int64(Deleted); BinStr := Copy(BinStr, x + 1, Length(BinStr)); until (Pos('1', BinStr) = 0); diff --git a/Base/JPL.DateTime.pas b/Base/JPL.DateTime.pas index c4330ee..fca315b 100644 --- a/Base/JPL.DateTime.pas +++ b/Base/JPL.DateTime.pas @@ -5,6 +5,7 @@ http://www.pazera-software.com } +{$I .\..\jp.inc} {$IFDEF FPC} {$mode objfpc}{$H+} {$ENDIF} interface @@ -116,7 +117,7 @@ function MsToSecStr(const Ms: integer; PaddingS: Byte = 4; PaddingMs: Byte = 3): begin sec := ms div 1000; msec := ms mod 1000; - Result := Pad(IntToStr(sec), PaddingS, '0') + '.' + Pad(IntToStr(msec), 3, '0'); + Result := Pad(IntToStr(sec), PaddingS, '0') + '.' + Pad(IntToStr(msec), PaddingMs, '0'); end; function GetDateTimeStr(dt: TDateTime; Format: string = '$Y.$M.$D-$H;$MIN;$S,$MS'): string; @@ -328,19 +329,19 @@ function ParseDate(dt: TDateTime; DateFormat: TDateFormat): string; if DateFormat = dfLongNames then s := - FormatSettings.LongDayNames[dnum] + ', ' + + {$IFDEF HAS_FORMATSETTINGS}FormatSettings.LongDayNames[dnum] + ', ' + {$ELSE}LongDayNames[dnum] + ', ' + {$ENDIF} Pad(IntToStr(Day), 2, '0') + ' ' + - FormatSettings.LongMonthNames[Month] + ' ' + + {$IFDEF HAS_FORMATSETTINGS}FormatSettings.LongMonthNames[Month] + ' ' + {$ELSE}LongMonthNames[Month] + ' ' + {$ENDIF} IntToStr(Year) else if DateFormat = dfShortNames then s := - FormatSettings.ShortDayNames[dnum] + ', ' + + {$IFDEF HAS_FORMATSETTINGS}FormatSettings.ShortDayNames[dnum] + ', ' + {$ELSE}ShortDayNames[dnum] + ', ' + {$ENDIF} Pad(IntToStr(Day), 2, '0') + ' ' + - FormatSettings.ShortMonthNames[Month] + ' ' + + {$IFDEF HAS_FORMATSETTINGS}FormatSettings.ShortMonthNames[Month] + ' ' + {$ELSE}ShortMonthNames[Month] + ' ' + {$ENDIF} IntToStr(Year) else if DateFormat = dfShortDay then s := - FormatSettings.ShortDayNames[dnum] + ', ' + + {$IFDEF HAS_FORMATSETTINGS}FormatSettings.ShortDayNames[dnum] + ', ' + {$ELSE}ShortDayNames[dnum] + ', ' + {$ENDIF} Pad(IntToStr(Day), 2, '0') + '.' + Pad(IntToStr(Month), 2, '0') + '.' + IntToStr(Year) @@ -356,7 +357,7 @@ function ParseDate(dt: TDateTime; DateFormat: TDateFormat): string; Pad(IntToStr(Day), 2, '0') else s := - FormatSettings.LongDayNames[dnum] + ', ' + + {$IFDEF HAS_FORMATSETTINGS}FormatSettings.LongDayNames[dnum] + ', ' + {$ELSE}LongDayNames[dnum] + ', ' + {$ENDIF} Pad(IntToStr(Day), 2, '0') + '.' + Pad(IntToStr(Month), 2, '0') + '.' + IntToStr(Year); @@ -415,11 +416,11 @@ function MsToDateTime(Ms: DWORD): TDateTime; h, m, s, msec {, msecv}: DWORD; begin h := ms div MsHour; - ms := ms - h * MsHour; + ms := ms {%H-}- h * MsHour; m := ms div MsMin; - ms := ms - DWORD(m * MsMin); + ms := ms {%H-}- DWORD(m * MsMin); s := ms div MsSec; - ms := ms - s * MsSec; + ms := ms {%H-}- s * MsSec; //msecv := ms; msec := ms div 100; diff --git a/Base/JPL.Dialogs.pas b/Base/JPL.Dialogs.pas index 7ac0498..117f70a 100644 --- a/Base/JPL.Dialogs.pas +++ b/Base/JPL.Dialogs.pas @@ -1,12 +1,12 @@ unit JPL.Dialogs; -{$IFDEF FPC} {$mode objfpc}{$H+} {$ENDIF} +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE OBJFPC}{$H+}{$ENDIF} interface uses - {$IFDEF MSWINDOWS}Windows,{$ENDIF} - SysUtils, Graphics, {$IFDEF DCC}System.UITypes, {$ENDIF} + SysUtils, Types, Graphics, {$IFDEF DELPHIXE2_OR_ABOVE}System.UITypes,{$ENDIF} Forms, Dialogs, Controls, StdCtrls; @@ -128,7 +128,11 @@ function ShowWinStr(const MemoText: string; Caption: string = ''; Width: integer var Form: TForm; Memo: TMemo; + {$IFDEF DELPHI2009_OR_BELOW} + Arr: TStringDynArray; + {$ELSE} Arr: {$IFDEF FPC}specialize{$ENDIF} TArray; + {$ENDIF} s: string; i: integer; begin diff --git a/Base/JPL.FileSearch.pas b/Base/JPL.FileSearch.pas index 0c99f6f..34020bd 100644 --- a/Base/JPL.FileSearch.pas +++ b/Base/JPL.FileSearch.pas @@ -36,9 +36,9 @@ } -//{$WARN SYMBOL_PLATFORM OFF} -{$IFDEF FPC} {$mode objfpc}{$H+} {$ENDIF} +{$I .\..\jp.inc} +{$IFDEF FPC}{$mode objfpc}{$H+}{$ENDIF} interface diff --git a/Base/JPL.FileSearcher.pas b/Base/JPL.FileSearcher.pas index 17f999b..d26dac0 100644 --- a/Base/JPL.FileSearcher.pas +++ b/Base/JPL.FileSearcher.pas @@ -270,12 +270,12 @@ procedure TJPFileSearcher.SetOnFoundFile(AValue: TJPEnumFilesProcObj); end; -function EnumDirsProc(CurrentDirNo: integer; CurrentDir: string): Boolean; +function EnumDirsProc({%H-}CurrentDirNo: integer; {%H-}CurrentDir: string): Boolean; begin Result := True; end; -function EnumFilesProc(Dirs, CurrentFileNo, CurrentDirNo: integer; CurrentFile: string): Boolean; +function EnumFilesProc({%H-}Dirs, {%H-}CurrentFileNo, {%H-}CurrentDirNo: integer; {%H-}CurrentFile: string): Boolean; begin Result := True; end; @@ -292,7 +292,7 @@ procedure TJPFileSearcher.Search; function CanContinue: Boolean; begin - Result := not ( (FFileCountLimit > 0) and (xFiles >= FFileCountLimit) ); + Result := not ( (FFileCountLimit > 0) and (xFiles {%H-}>= FFileCountLimit) ); end; begin @@ -369,7 +369,7 @@ function TJPFileSearcher.AddInputWithTag(const Dir: string; FileMasks: array of ii.Directory := Dir; ii.RecurseDepth := RecurseDepth; ii.Tag := Tag; - ii.TagStr := ''; + ii.TagStr := TagStr; ii.FilesToSearch := TFSFilesToSerach.Create; for i := 0 to High(FileMasks) do ii.FilesToSearch.Add(FileMasks[i]); diff --git a/Base/JPL.Files.pas b/Base/JPL.Files.pas index 375cace..98af33b 100644 --- a/Base/JPL.Files.pas +++ b/Base/JPL.Files.pas @@ -5,9 +5,12 @@ http://www.pazera-software.com } +{$I .\..\jp.inc} + {$IFDEF FPC} {$mode objfpc}{$H+} {$WARN 5057 off : Local variable "$1" does not seem to be initialized} + {$WARN 5044 off : Symbol "$1" is not portable} {$modeswitch ADVANCEDRECORDS} {$ENDIF} @@ -26,6 +29,12 @@ interface INVALID_FILE_ATTRIBUTES = DWORD(-1); {$ENDIF} + {$IFDEF DELPHI2010_OR_BELOW} + faCompressed = $00000800; + faEncrypted = $00004000; + faVirtual = $00010000; + {$ENDIF} + type TFileNameRec = record @@ -318,6 +327,7 @@ function TFileAttributesRec.ReadFileAttributes(const FileName: string): Boolean; ValidAttributes := True; Result := True; + {$IFDEF FPC}{$WARN 5044 off : Symbol "$1" is not portable}{$ENDIF} ReadOnly := x and faReadOnly <> 0; Hidden := x and faHidden <> 0; SysFile := x and faSysFile <> 0; @@ -333,6 +343,7 @@ function TFileAttributesRec.ReadFileAttributes(const FileName: string): Boolean; Encrypted := x and faEncrypted <> 0; Virtual := x and faVirtual <> 0; AnyFile := x and faAnyFile <> 0; + {$IFDEF FPC}{$WARN 5044 on : Symbol "$1" is not portable}{$ENDIF} end; {$WARN SYMBOL_PLATFORM ON} diff --git a/Base/JPL.IniFile.pas b/Base/JPL.IniFile.pas index 738a083..4929ef6 100644 --- a/Base/JPL.IniFile.pas +++ b/Base/JPL.IniFile.pas @@ -3,22 +3,23 @@ { Jacek Pazera http://www.pazera-software.com - 06.2015 + First version: 06.2015 TJPIniFile - INI file with comments support // Co mnie napadło, żeby to zrobić na Kolekcjach?! } +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} + interface + uses - //Winapi.Windows, - System.SysUtils, System.Classes, System.Generics.Collections, - Vcl.Graphics, + SysUtils, Classes, {Generics.Collections,} Graphics, StrUtils, JPL.Strings, JPL.Conversion, JPL.Colors; - //System.ZLib, JP.Common.Procs; type @@ -39,7 +40,7 @@ TJPIniItem = class(TCollectionItem) procedure SetKey(const Value: string); procedure SetValue(const Value: string); public - constructor Create(Collection: TCollection); override; + constructor Create(ACollection: TCollection); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; function AsString: string; @@ -57,7 +58,7 @@ TJPIniSectionItems = class(TCollection) protected function GetKeyIndex(Key: string): integer; public - constructor Create(ItemClass: TCollectionItemClass); + constructor Create({%H-}AItemClass: TCollectionItemClass); function GetItem(Index: Integer): TJPIniItem; overload; function GetItem(Key: string; CreateIfNotExists: Boolean = True): TJPIniItem; overload; function Add: TJPIniItem; @@ -110,7 +111,7 @@ TJPIniSection = class(TCollectionItem) procedure SetName(const Value: string); procedure SetSectionItems(const Value: TJPIniSectionItems); public - constructor Create(Collection: TCollection); override; + constructor Create(ACollection: TCollection); override; destructor Destroy; override; function AsString: string; @@ -160,7 +161,7 @@ TJPIniSections = class(TCollection) procedure SetItem(Index: Integer; const Value: TJPIniSection); procedure SetSectionsSeparator(const Value: string); public - constructor Create(ItemClass: TCollectionItemClass); + constructor Create({%H-}AItemClass: TCollectionItemClass); function Add: TJPIniSection; procedure Delete(Index: Integer); function Insert(Index: Integer): TJPIniSection; @@ -428,7 +429,10 @@ procedure TJPIniFile.LoadFile; sl := TStringList.Create; try - sl.LoadFromFile(FFileName, FEncoding); + {$IFDEF DCC}sl.LoadFromFile(FFileName, FEncoding);{$ENDIF} + {$IFDEF FPC} + {$IFDEF HAS_INIFILE_WITH_ENCODING}sl.LoadFromFile(FFileName, FEncoding);{$ELSE}sl.LoadFromFile(FFileName); {$ENDIF} + {$ENDIF} ParseText(sl.Text); finally sl.Free; @@ -460,31 +464,39 @@ procedure TJPIniFile.ParseText(Source: string); if Line = '' then Continue; // ------------ section ----------------- - if (Line.Chars[0] = '[') and (Line.Chars[Line.Length - 1] = ']') then + //if (Line.Chars[0] = '[') and (Line.Chars[Line.Length - 1] = ']') then + if IsBoundedWith(Line, '[', ']') then begin Section := Sections.Add; - Section.Name := Line.Substring(1, Line.Length - 2).Trim; + //Section.Name := Line.Substring(1, Line.Length - 2).Trim; + Section.Name := Trim(TrimBounds(Line, '[', ']')); end // ---------- comment -------------- - else if Line.Chars[0] = ';' then + //else if Line.Chars[0] = ';' then + else if Line[1] = ';' then begin IniItem := Section.SectionItems.Add; IniItem.ItemType := iitComment; - IniItem.Value := Line.Substring(1, Line.Length - 1); + //IniItem.Value := Line.Substring(1, Line.Length - 1); + IniItem.Value := Copy(Line, 2, Length(Line) - 1); end else begin IniItem := Section.SectionItems.Add; - x := Line.IndexOf('='); + //x := Line.IndexOf('='); + x := Pos('=', Line); // -------------- key=value --------------- - if x >= 0 then + //if x >= 0 then + if x > 0 then begin IniItem.ItemType := iitNormal; - IniItem.Key := Line.Substring(0, x).Trim; - IniItem.Value := Line.Substring(x + 1).Trim; + //IniItem.Key := Line.Substring(0, x).Trim; + IniItem.Key := Copy(Line, 1, x - 1); + //IniItem.Value := Line.Substring(x + 1).Trim; + IniItem.Value := Copy(Line, x + 1, Length(Line)); end else // ------------- text line -------------- @@ -550,7 +562,8 @@ function TJPIniFile.CommentsCount(const SectionName: string): integer; i: integer; begin Result := 0; - if SectionName.Trim = '' then Exit; + //if SectionName.Trim = '' then Exit; + if Trim(SectionName) = '' then Exit; Items := GetSectionItems(SectionName); if Items = nil then Exit; for i := 0 to Items.Count - 1 do @@ -588,7 +601,8 @@ function TJPIniFile.HasComments(const SectionName: string): Boolean; i: integer; begin Result := False; - if SectionName.Trim = '' then Exit; + //if SectionName.Trim = '' then Exit; + if Trim(SectionName) = '' then Exit; Items := GetSectionItems(SectionName); if Items = nil then Exit; for i := 0 to Items.Count - 1 do @@ -630,7 +644,8 @@ function TJPIniFile.HasTextLines(const SectionName: string): Boolean; i: integer; begin Result := False; - if SectionName.Trim = '' then Exit; + //if SectionName.Trim = '' then Exit; + if Trim(SectionName) = '' then Exit; Items := GetSectionItems(SectionName); if Items = nil then Exit; for i := 0 to Items.Count - 1 do @@ -647,7 +662,8 @@ function TJPIniFile.HasKeys(const SectionName: string): Boolean; i: integer; begin Result := False; - if SectionName.Trim = '' then Exit; + //if SectionName.Trim = '' then Exit; + if Trim(SectionName) = '' then Exit; Items := GetSectionItems(SectionName); if Items = nil then Exit; for i := 0 to Items.Count - 1 do @@ -668,7 +684,8 @@ function TJPIniFile.ItemsCount(const SectionName: string): integer; Section: TJPIniSection; begin Result := 0; - if SectionName.Trim = '' then Exit; + //if SectionName.Trim = '' then Exit; + if Trim(SectionName) = '' then Exit; Section := GetSection(SectionName, False); if Section <> nil then Result := Section.SectionItems.Count; end; @@ -685,13 +702,15 @@ function TJPIniFile.RenameSection(const OldName, NewName: string): Boolean; begin Result := False; - if (OldName.Trim = '') or (NewName.Trim = '') then Exit; + //if (OldName.Trim = '') or (NewName.Trim = '') then Exit; + if (Trim(OldName) = '') or (Trim(NewName) = '') then Exit; if SectionExists(NewName) then Exit; Section := GetSection(OldName, False); if Section = nil then Exit; - Section.Name := NewName.Trim; + //Section.Name := NewName.Trim; + Section.Name := Trim(NewName); Result := True; end; @@ -720,7 +739,8 @@ function TJPIniFile.KeysCount(const SectionName: string): integer; i: integer; begin Result := 0; - if SectionName.Trim = '' then Exit; + //if SectionName.Trim = '' then Exit; + if Trim(SectionName) = '' then Exit; Items := GetSectionItems(SectionName); if Items = nil then Exit; for i := 0 to Items.Count - 1 do @@ -729,7 +749,8 @@ function TJPIniFile.KeysCount(const SectionName: string): integer; function TJPIniFile.AddSection(const SectionName: string): Boolean; begin - if (SectionExists(SectionName)) or (SectionName.Trim = '') then Result := False + //if (SectionExists(SectionName)) or (SectionName.Trim = '') then Result := False + if (SectionExists(SectionName)) or (Trim(SectionName) = '') then Result := False else Result := GetSection(SectionName, True) <> nil; end; @@ -779,7 +800,8 @@ function TJPIniFile.TextLinesCount(const SectionName: string): integer; i: integer; begin Result := 0; - if SectionName.Trim = '' then Exit; + //if SectionName.Trim = '' then Exit; + if Trim(SectionName) = '' then Exit; Items := GetSectionItems(SectionName); if Items = nil then Exit; for i := 0 to Items.Count - 1 do @@ -790,10 +812,12 @@ procedure TJPIniFile.SaveToFile(const FileName: string); var sl: TStringList; begin - if FileName.Trim = '' then Exit; //raise Exception.Create('File name can not be blank!'); + //if FileName.Trim = '' then Exit; //raise Exception.Create('File name can not be blank!'); + if Trim(FileName) = '' then Exit; sl := TStringList.Create; try - + + {$IFDEF DCC} sl.Text := Text; if FIgnoreExceptionsOnSave then try @@ -801,6 +825,15 @@ procedure TJPIniFile.SaveToFile(const FileName: string); except end else sl.SaveToFile(FileName, FEncoding); + {$ELSE} + sl.Text := Text; + if FIgnoreExceptionsOnSave then + try + {$IFDEF HAS_INIFILE_WITH_ENCODING}sl.SaveToFile(FileName, FEncoding);{$ELSE}sl.SaveToFile(FileName);{$ENDIF} + except + end + else {$IFDEF HAS_INIFILE_WITH_ENCODING}sl.SaveToFile(FileName, FEncoding);{$ELSE}sl.SaveToFile(FileName);{$ENDIF} + {$ENDIF} finally sl.Free; @@ -1152,9 +1185,9 @@ procedure TJPIniFile.WriteTime(const SectionName, Key: string; const Value: TDat {$region ' ------------------------------ TJPIniItem - collection item ---------------------------------- '} -constructor TJPIniItem.Create(Collection: TCollection); +constructor TJPIniItem.Create(ACollection: TCollection); begin - inherited Create(Collection); + inherited Create(ACollection); FKey := ''; FValue := ''; FItemType := iitNormal; @@ -1227,7 +1260,7 @@ function TJPIniSectionItems.AsString: string; Result := Result + Items[i].AsString + #13#10; end; -constructor TJPIniSectionItems.Create(ItemClass: TCollectionItemClass); +constructor TJPIniSectionItems.Create(AItemClass: TCollectionItemClass); begin inherited Create(TJPIniItem); end; @@ -1285,7 +1318,8 @@ procedure TJPIniSectionItems.SetItem(Index: Integer; const Value: TJPIniItem); inherited SetItem(Index, Value); end; - +{$IFDEF DCC} +{$IFDEF DELPHIXE3_OR_ABOVE} function TJPIniSectionItems.ReadBinaryStream(const Key: string; Value: TStream): integer; var Text: string; @@ -1304,7 +1338,6 @@ function TJPIniSectionItems.ReadBinaryStream(const Key: string; Value: TStream): dataLen := Length(Text) div 2; SetLength(DataBytes, dataLen); Pos := Stream.Position; - System.Classes.HexToBin(BytesOf(Text), 0, DataBytes, 0, dataLen); Stream.Write(DataBytes[0], dataLen); Stream.Position := Pos; @@ -1314,15 +1347,82 @@ function TJPIniSectionItems.ReadBinaryStream(const Key: string; Value: TStream): if Value <> Stream then Stream.Free; end; end - else Result := 0; + else + Result := 0; +end; +{$ELSE} +function TJPIniSectionItems.ReadBinaryStream(const Key: string; Value: TStream): integer; +var + Text: string; + Stream: TMemoryStream; + Pos: Integer; +begin + Text := ReadString(Key, ''); + if Text <> '' then + begin + if Value is TMemoryStream then Stream := TMemoryStream(Value) + else Stream := TMemoryStream.Create; + + try + Pos := Stream.Position; + Stream.SetSize(Stream.Size + Length(Text) div 2); + Classes.HexToBin(PChar(Text), Pointer(Integer(Stream.Memory) + Stream.Position)^, Length(Text) div 2); + Stream.Position := Pos; + if Value <> Stream then Value.CopyFrom(Stream, Length(Text) div 2); + Result := Stream.Size - Pos; + finally + if Value <> Stream then Stream.Free; + end; + end + else + Result := 0; +end; +{$ENDIF} + +{$ENDIF} // DCC + +{$IFDEF FPC} +function TJPIniSectionItems.ReadBinaryStream(const Key: string; Value: TStream): integer; +var + //M: TMemoryStream; + S: String; + PB, PR: PByte; + PC: PChar; + H : String[3]; + i, {l2,} code : Integer; +begin + S := ReadString(Key, ''); + Setlength(H, 3); + H[1] := '$'; + Result := Length(S) div 2; + if Result > 0 then + begin + GetMem(PR, Result); + try + PC := PChar(S); + PB := PR; + for I := 1 to Result do + begin + H[2] := PC[0]; + H[3] := PC[1]; + Val(H, PB^, code); + Inc(PC, 2); + Inc(PB); + end; + Value.WriteBuffer(PR^, Result); + finally + FreeMem(PR); + end; + end; end; +{$ENDIF} // FPC function TJPIniSectionItems.ReadBool(const Key: string; Default: Boolean): Boolean; var s, sDefault: string; begin if Default then sDefault := '1' else sDefault := '0'; - s := ReadString(Key, sDefault).Trim; + s := Trim(ReadString(Key, sDefault)); Result := s = '1'; end; @@ -1356,7 +1456,7 @@ function TJPIniSectionItems.ReadDate(const Key: string; Default: TDateTime): TDa s: string; begin Result := Default; - s := ReadString(Key, '').Trim; + s := Trim(ReadString(Key, '')); if s = '' then Exit; try Result := StrToDate(s); @@ -1369,7 +1469,7 @@ function TJPIniSectionItems.ReadDateTime(const Key: string; Default: TDateTime): s: string; begin Result := Default; - s := ReadString(Key, '').Trim; + s := Trim(ReadString(Key, '')); if s = '' then Exit; try Result := StrToDateTime(s); @@ -1383,10 +1483,10 @@ function TJPIniSectionItems.ReadFloat(const Key: string; Default: Double): Doubl begin Result := Default; sDefault := FloatToStr(Default); - sDefault := StringReplace(sDefault, FormatSettings.DecimalSeparator, '.', []); - s := ReadString(Key, sDefault).Trim; + sDefault := StringReplace(sDefault, GetDecimalSeparator, '.', []); + s := Trim(ReadString(Key, sDefault)); if s = '' then Exit; - s := StringReplace(s, '.', FormatSettings.DecimalSeparator, []); + s := StringReplace(s, '.', GetDecimalSeparator, []); try Result := StrToFloat(s); except @@ -1407,7 +1507,8 @@ function TJPIniSectionItems.ReadInteger(const Key: string; Default: integer): in s: string; begin s := ReadString(Key, ''); - if (s.Length > 2) and (s.StartsWith('0x', True)) then s := '$' + s.Substring(2); + s := ReplaceFirst(s, '0x', '$', True); + //if (s.Length > 2) and (s.StartsWith('0x', True)) then s := '$' + s.Substring(2); Result := StrToIntDef(s, Default); end; @@ -1434,7 +1535,7 @@ function TJPIniSectionItems.ReadTime(const Key: string; Default: TDateTime): TDa s: string; begin Result := Default; - s := ReadString(Key, '').Trim; + s := Trim(ReadString(Key, '')); if s = '' then Exit; try Result := StrToTime(s); @@ -1443,6 +1544,9 @@ function TJPIniSectionItems.ReadTime(const Key: string; Default: TDateTime): TDa end; {$region ' ------ Write XXX ------- '} + +{$IFDEF DCC} +{$IFDEF DELPHIXE3_OR_ABOVE} procedure TJPIniSectionItems.WriteBinaryStream(const Key: string; Value: TStream); var Text: string; @@ -1465,12 +1569,77 @@ procedure TJPIniSectionItems.WriteBinaryStream(const Key: string; Value: TStream SetLength(Buffer, Stream.Size * 2); System.Classes.BinToHex(TBytes(Stream.Memory), Stream.Position, Buffer, 0, Stream.Size - Stream.Position); Text := StringOf(Buffer); + + finally + if Value <> Stream then Stream.Free; + end; + end; + WriteString(Key, Text); +end; +{$ELSE} +procedure TJPIniSectionItems.WriteBinaryStream(const Key: string; Value: TStream); +var + Text: string; + Stream: TMemoryStream; +begin + SetLength(Text, (Value.Size - Value.Position) * 2); + if Length(Text) > 0 then + begin + if Value is TMemoryStream then Stream := TMemoryStream(Value) + else Stream := TMemoryStream.Create; + + try + if Stream <> Value then + begin + Stream.CopyFrom(Value, Value.Size - Value.Position); + Stream.Position := 0; + end; + Classes.BinToHex(Pointer(Integer(Stream.Memory) + Stream.Position)^, PChar(Text), + Stream.Size - Stream.Position); + finally if Value <> Stream then Stream.Free; end; end; WriteString(Key, Text); end; +{$ENDIF} +{$ENDIF} // DCC + +{$IFDEF FPC} +procedure TJPIniSectionItems.WriteBinaryStream(const Key: string; Value: TStream); +var + M: TMemoryStream; + S: String; + PB: PByte; + PC: PChar; + H: String[2]; + i: Integer; + +begin + M := TMemoryStream.Create; + try + M.CopyFrom(Value, 0); + SetLength(S, M.Size * 2); + if (length(S) > 0) then + begin + PB := M.Memory; + PC := PChar(S); + for I := 1 to Length(S) div 2 do + begin + H := HexStr(PB^, 2); + PC[0] := H[1]; + PC[1] := H[2]; + Inc(PC, 2); + Inc(PB); + end; + end; + WriteString(Key, S); + finally + M.Free; + end; +end; +{$ENDIF} // FPC procedure TJPIniSectionItems.WriteBool(const Key: string; const Value: Boolean); begin @@ -1513,7 +1682,7 @@ procedure TJPIniSectionItems.WriteFloat(const Key: string; const Value: Double); s: string; begin s := FloatToStr(Value); - s := StringReplace(s, FormatSettings.DecimalSeparator, '.', []); + s := StringReplace(s, GetDecimalSeparator, '.', []); WriteString(Key, s); end; @@ -1529,7 +1698,7 @@ procedure TJPIniSectionItems.WriteHtmlColor(const Key: string; const Value: TCol procedure TJPIniSectionItems.WriteInteger(const Key: string; const Value: Integer); begin - WriteString(Key, Value.ToString); + WriteString(Key, itos(Value)); end; procedure TJPIniSectionItems.WriteString(const Key, Value: string); @@ -1562,9 +1731,9 @@ procedure TJPIniSectionItems.WriteTime(const Key: string; const Value: TDateTime {$region ' ----------------------------------- TJPIniSection - collection item ------------------------------- '} -constructor TJPIniSection.Create(Collection: TCollection); +constructor TJPIniSection.Create(ACollection: TCollection); begin - inherited Create(Collection); + inherited Create(ACollection); FName := ''; FSectionItems := TJPIniSectionItems.Create(TJPIniItem); end; @@ -1767,7 +1936,7 @@ function TJPIniSections.AsString: string; Result := Result + Items[i].AsString + SectionsSeparator; end; -constructor TJPIniSections.Create(ItemClass: TCollectionItemClass); +constructor TJPIniSections.Create(AItemClass: TCollectionItemClass); begin inherited Create(TJPIniSection); end; diff --git a/Base/JPL.LangMgr.pas b/Base/JPL.LangMgr.pas index 0a014b5..717cc60 100644 --- a/Base/JPL.LangMgr.pas +++ b/Base/JPL.LangMgr.pas @@ -2,10 +2,26 @@ interface +{$I .\..\jp.inc} + +{$IFDEF FPC} + {$MODE DELPHI} + {$IFNDEF HAS_RTTI} + This unit is only for FPC 3.2 or above + {$ENDIF} + {$WARN 5079 off : Unit "$1" is experimental} +{$ENDIF} + +{$IFDEF DCC} + {$IFDEF DELPHI2009_OR_BELOW} + Unit for Delphi 2010 or newer! + {$ENDIF} +{$ENDIF} + + uses - Winapi.Windows, - System.SysUtils, System.Classes, System.Generics.Collections, System.IniFiles, System.Rtti, System.TypInfo, - Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.ActnList, + SysUtils, Classes, Generics.Collections, IniFiles, Rtti, TypInfo, + StdCtrls, ExtCtrls, ActnList, Dialogs, JPL.Strings, JPL.Conversion, JPL.IniFile, JPL.FileSearch, JPL.RTTI; @@ -327,9 +343,11 @@ procedure TLangSection.UpdateComponents; PropValue := lci.Properties[PropName]; PropValue := fixs(PropValue); - if PropName.Contains('.') then + //if PropName.Contains('.') then + x := Pos('.', PropName); + if x > 0 then begin - x := Pos('.', PropName); + //x := Pos('.', PropName); ObjName := Copy(PropName, 1, x - 1); PropName2 := Copy(PropName, x + 1, Length(PropName)); if TryGetPropertyAsObject(lci.Component, ObjName, Obj) then SetPropertyText(Obj, PropName2, PropValue); diff --git a/Base/JPL.Language.pas b/Base/JPL.Language.pas index f4340af..ac38d9c 100644 --- a/Base/JPL.Language.pas +++ b/Base/JPL.Language.pas @@ -11,7 +11,8 @@ } -{$IFDEF FPC} {$mode objfpc}{$H+} {$ENDIF} +{$I .\..\jp.inc} +{$IFDEF FPC}{$mode objfpc}{$H+}{$ENDIF} interface @@ -40,7 +41,7 @@ function LanguageIDToStr(const LangID: WORD): string; var Buffer: array[0..255] of Char; begin - FillChar(Buffer, SizeOf(Buffer), 0); + FillChar(Buffer{%H-}, SizeOf(Buffer), 0); if VerLanguageName(LangID, Buffer, {size in characters-->}Length(Buffer)) > 0 then Result := Buffer else Result := ''; end; diff --git a/Base/JPL.MemIniFile.pas b/Base/JPL.MemIniFile.pas index 1afd07f..eb14446 100644 --- a/Base/JPL.MemIniFile.pas +++ b/Base/JPL.MemIniFile.pas @@ -4,25 +4,17 @@ Jacek Pazera http://www.pazera-software.com https://github.com/jackdp - - Last mod: 2020.03.14 } -{$IFDEF FPC} - {$mode objfpc}{$H+} - {$I JppFPC.inc} -{$ENDIF} +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE OBJFPC}{$H+}{$ENDIF} interface -uses - {$IFDEF DCC} - Winapi.Windows, - System.SysUtils, System.Classes, System.IniFiles, System.ZLib, Vcl.Graphics, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Forms, - {$ELSE} - SysUtils, Classes, IniFiles, Graphics, StdCtrls, Forms, - {$ENDIF} - JPL.Strings, JPL.Conversion, JPL.Math, JPL.Colors; +uses + SysUtils, Classes, IniFiles, Graphics, Dialogs, StdCtrls, Forms, + {$IFDEF DCC}Zlib, JPL.Math,{$ENDIF} + JPL.Strings, JPL.Conversion, JPL.Colors; type @@ -30,7 +22,7 @@ interface TJppMemIniFile = class private const DEFAULT_SECTION = 'MAIN'; - COMPRESSED_VALUE_PREFIX = 'CBUF_'; + {$IFDEF DCC}COMPRESSED_VALUE_PREFIX = 'CBUF_';{$ENDIF} private FIni: TMemIniFile; FUpdateOnExit: Boolean; @@ -51,6 +43,8 @@ TJppMemIniFile = class {$ENDIF} {$IFDEF FPC}{$IFDEF HAS_INIFILE_WITH_ENCODING} function GetEncoding: TEncoding; + // CodeTyphon 7.00 + FPC 3.3.1: Encoding property is read only (in Lazarus 2.0.7 + FPC 3.3.1 - Encoding is read/write) + //procedure SetEncoding(const Value: TEncoding); {$ENDIF}{$ENDIF} public @@ -84,9 +78,9 @@ TJppMemIniFile = class procedure ReadSectionValues(const Section: string; Strings: TStrings); // Reads the values from all keys within the given section - {$IFDEF DCC} + {$IFDEF DCC}{$IFDEF DELPHI2010_OR_ABOVE} procedure ReadSubSections(const Section: string; Strings: TStrings; Recurse: Boolean = False); - {$ENDIF} + {$ENDIF}{$ENDIF} function ReadBinaryStream(const Section, Ident: string; Value: TStream): integer; @@ -316,6 +310,11 @@ function TJppMemIniFile.GetEncoding: TEncoding; {$ENDIF} {$IFDEF FPC}{$IFDEF HAS_INIFILE_WITH_ENCODING} +//procedure TJppMemIniFile.SetEncoding(const Value: TEncoding); +//begin +// FIni.Encoding := Value; +//end; + function TJppMemIniFile.GetEncoding: TEncoding; begin Result := FIni.Encoding; @@ -339,12 +338,20 @@ procedure TJppMemIniFile.SetUpdateOnExit(const Value: Boolean); procedure TJppMemIniFile.SetCaseSensitive(const Value: Boolean); begin + {$IFDEF FPC} + if Value then FIni.Options := FIni.Options + [ifoCaseSensitive] else FIni.Options := FIni.Options - [ifoCaseSensitive]; + {$ELSE} if FIni.CaseSensitive <> Value then FIni.CaseSensitive := Value; + {$ENDIF} end; function TJppMemIniFile.GetCaseSensitive: Boolean; begin + {$IFDEF FPC} + Result := ifoCaseSensitive in FIni.Options; + {$ELSE} Result := FIni.CaseSensitive; + {$ENDIF} end; @@ -431,12 +438,12 @@ procedure TJppMemIniFile.ReadSectionValues(const Section: string; Strings: TStri FIni.ReadSectionValues(Section, Strings); end; -{$IFDEF DCC} +{$IFDEF DCC}{$IFDEF DELPHI2010_OR_ABOVE} procedure TJppMemIniFile.ReadSubSections(const Section: string; Strings: TStrings; Recurse: Boolean); begin FIni.ReadSubSections(Section, Strings, Recurse); end; -{$ENDIF} +{$ENDIF}{$ENDIF} function TJppMemIniFile.ReadBinaryStream(const Section, Ident: string; Value: TStream): integer; @@ -864,10 +871,11 @@ procedure TJppMemIniFile.WriteStrings(const Section: string; Items: TStrings; Ma procedure TJppMemIniFile.ReadStrings(const Section: string; Items: TStrings {$IFDEF DCC}; ItemsCompressed: Boolean{$ENDIF}); var - sl, slNames: TStringList; + sl: TStringList; i, xp: integer; s: string; {$IFDEF DCC} + slNames: TStringList; ss: TStringStream; ms: TMemoryStream; x: integer; @@ -1051,7 +1059,7 @@ function TJppMemIniFile.ReadDotFloat(const Section, Ident: string; const Default FloatStr: string; begin FloatStr := FIni.ReadString(Section, Ident, ''); - FloatStr := StringReplace(FloatStr, '.', FormatSettings.DecimalSeparator, []); + FloatStr := StringReplace(FloatStr, '.', GetDecimalSeparator, []); Result := Default; if FloatStr <> '' then if not TryStrToFloat(FloatStr, Result) then Result := Default; @@ -1075,7 +1083,7 @@ procedure TJppMemIniFile.WriteDotFloat(const Section, Ident: string; const Value s: string; begin s := FloatToStr(Value); - s := StringReplace(s, FormatSettings.DecimalSeparator, '.', []); + s := StringReplace(s, GetDecimalSeparator, '.', []); FIni.WriteString(Section, Ident, s); end; diff --git a/Base/JPL.RTTI.pas b/Base/JPL.RTTI.pas index ed8dbe1..3109cec 100644 --- a/Base/JPL.RTTI.pas +++ b/Base/JPL.RTTI.pas @@ -1,20 +1,21 @@ unit JPL.RTTI; -{$IFDEF FPC} {$mode delphi} {$I JppFPC.inc} {$ENDIF} +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} -{$IFDEF DCC}{$DEFINE HAS_RTTI}{$ENDIF} +{$IFDEF DCC} + {$IFDEF DELPHI2009_OR_BELOW} + Unit for Delphi 2010 or newer! + {$ENDIF} + {$DEFINE HAS_RTTI} +{$ENDIF} interface uses - {$IFDEF MSWINDOWS} Windows, {$ENDIF} - {$IFDEF DCC} - System.SysUtils, System.Classes, - System.Rtti, System.TypInfo; - {$ELSE} - SysUtils, Classes {$IFDEF HAS_RTTI}, Rtti, TypInfo{$ENDIF}; - {$ENDIF} - + SysUtils, Classes + {$IFDEF HAS_RTTI}, {%H-}Rtti, TypInfo{$ENDIF} + ; {$IFDEF HAS_RTTI} @@ -60,7 +61,7 @@ function SetPropertyText(Obj: TObject; PropertyName: string; Text: string): Bool // http://docwiki.embarcadero.com/Libraries/Rio/en/System.TypInfo.TTypeKinds if (Kind = tkUString) or (Kind = tkString) or (Kind = tkLString) then RProperty.SetValue(Obj, Text) - else if Kind = tkWString then RProperty.SetValue(Obj, WideString(Text)) + else if Kind = tkWString then RProperty.SetValue(Obj, WideString(Text){%H-}) else Exit; Result := True; diff --git a/Base/JPL.StrHash.pas b/Base/JPL.StrHash.pas index e4b0439..0316465 100644 --- a/Base/JPL.StrHash.pas +++ b/Base/JPL.StrHash.pas @@ -5,12 +5,14 @@ xxHash32, Adler32 from "SynCommons.pas" (mORMot project http://synopse.info). } +{$I .\..\jp.inc} {$IFDEF FPC} {$MODE DELPHI}{$H+} {$MACRO ON} {$COPERATORS ON} {$ENDIF} + {$POINTERMATH ON} {$OVERFLOWCHECKS OFF} diff --git a/Base/JPL.Strings.Ext.pas b/Base/JPL.Strings.Ext.pas index 66f77e7..f8c9783 100644 --- a/Base/JPL.Strings.Ext.pas +++ b/Base/JPL.Strings.Ext.pas @@ -5,8 +5,8 @@ http://www.pazera-software.com } - -{$IFDEF FPC} {$mode objfpc}{$H+} {$ENDIF} +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} interface diff --git a/Base/JPL.Strings.pas b/Base/JPL.Strings.pas index 6d00acb..2c9e8c6 100644 --- a/Base/JPL.Strings.pas +++ b/Base/JPL.Strings.pas @@ -10,12 +10,14 @@ } -{$IFDEF FPC} {$mode objfpc}{$H+} {$ENDIF} +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} + interface uses - SysUtils; + SysUtils, Types; const CR = #13; @@ -28,6 +30,10 @@ interface DEG = '°'; +{$IFDEF DELPHI2009_OR_BELOW} +type + TArray = array of T; +{$ENDIF} function Rbs(Dir: string): string; // removes path delimiter from end function Qs(const s: string): string; @@ -44,6 +50,7 @@ function PadRight(Text: string; i: integer; znak: Char = ' '): string; function UnquoteStr(s: string; bDoubleQuote: Boolean = True): string; function IntToStrEx(const x: int64; c: Char = ' '): string; overload; function IntToStrEx(const x: integer; c: Char = ' '): string; overload; +function IntToStrEx(const x: UInt64; c: Char = ' '): string; overload; function GetLastCharIndex(const s: string; c: Char): integer; function GetLastBIndex(const s: string): integer; deprecated {$IFDEF DCC}{$IF CompilerVersion > 19}'Use GetLastBackslashIndex instead'{$IFEND}{$ENDIF}; @@ -110,11 +117,16 @@ function InsertNumSep(NumStr: string; Separator: string = ' '; NumBlockSize: int function CopyString(const s: string; Copies: integer = 2): string; //procedure StrToList(LineToParse: string; var List: TStringList; Separator: string = ','); -procedure SplitStrToArray(s: string; var Arr: {$IFDEF FPC}specialize{$ENDIF} TArray; const EndLineStr: string = sLineBreak); +{$IFDEF DELPHI2009_OR_BELOW} +procedure SplitStrToArray(s: string; var Arr: TStringDynArray; const EndLineStr: string = sLineBreak); +{$ELSE} +procedure SplitStrToArray(s: string; var Arr: TArray; const EndLineStr: string = sLineBreak); +{$ENDIF} function SplitStr(const InStr: string; out LeftStr, RightStr: string; const Separator: string): Boolean; overload; function SplitStr(const InStr: string; out LeftInt, RightInt: integer; const Separator: string): Boolean; overload; function TrimBounds(s: string; LeftBound, RightBound: string): string; +function IsBoundedWith(const s: string; LeftBound, RightBound: string; IgnoreCase: Boolean = False): Boolean; function AddBounds(const s: string; LeftBound, RightBound: Char): string; overload; function AddBounds(const s: string; LeftBound, RightBound: string): string; overload; function AddBounds(const s: string; StringToBoundSeparator: string = ' '; BoundChar: Char = '-'; BoundLen: Integer = 16): string; overload; @@ -133,11 +145,24 @@ function AddFileNameSuffix(const FileName, Suffix: string): string; function AddFileNamePrefix(const FileName, Prefix: string): string; procedure SplitFileName(fName: string; out Dir, BaseFileName, Ext: string; bIncludePathDelimiter: Boolean = True; bRemoveDotFromExt: Boolean = False); +function GetDecimalSeparator: Char; implementation +function GetDecimalSeparator: Char; +begin + {$IFDEF FPC}Result := FormatSettings.DecimalSeparator;{$ENDIF} + {$IFDEF DCC} + {$IFDEF DELPHIXE_OR_ABOVE} + Result := FormatSettings.DecimalSeparator; + {$ELSE} + Result := DecimalSeparator; + {$ENDIF} + {$ENDIF} +end; + function SplitStr(const InStr: string; out LeftStr, RightStr: string; const Separator: string): Boolean; var @@ -291,6 +316,19 @@ function AddBounds(const s: string; StringToBoundSeparator: string = ' '; BoundC Result := sb + StringToBoundSeparator + s + StringToBoundSeparator + sb; end; +function IsBoundedWith(const s: string; LeftBound, RightBound: string; IgnoreCase: Boolean = False): Boolean; +var + sLeft, sRight: string; +begin + sLeft := Copy(s, 1, Length(LeftBound)); + sRight := Copy(s, Length(s) - Length(RightBound) + 1, Length(RightBound)); + + if IgnoreCase then + Result := ( UpperCase(sLeft) = UpperCase(LeftBound) ) and ( UpperCase(sRight) = UpperCase(RightBound) ) + else + Result := ( sLeft = LeftBound ) and (sRight = RightBound); +end; + function TrimBounds(s: string; LeftBound, RightBound: string): string; begin if Copy(s, 1, Length(LeftBound)) = LeftBound then s := Copy(s, 1 + Length(LeftBound), Length(s)); @@ -298,7 +336,11 @@ function TrimBounds(s: string; LeftBound, RightBound: string): string; Result := s; end; -procedure SplitStrToArray(s: string; var Arr: {$IFDEF FPC}specialize{$ENDIF} TArray; const EndLineStr: string = sLineBreak); +{$IFDEF DELPHI2009_OR_BELOW} +procedure SplitStrToArray(s: string; var Arr: TStringDynArray; const EndLineStr: string = sLineBreak); +{$ELSE} +procedure SplitStrToArray(s: string; var Arr: TArray; const EndLineStr: string = sLineBreak); +{$ENDIF} var x: integer; begin @@ -309,7 +351,7 @@ procedure SplitStrToArray(s: string; var Arr: {$IFDEF FPC}specialize{$ENDIF} TAr while x > 0 do begin SetLength(Arr, Length(Arr) + 1); - Arr[High(Arr)] := Copy(s, 1, x - 1); + Arr[Length(Arr) - 1] := Copy(s, 1, x - 1); s := Copy(s, x + Length(EndLineStr), Length(s)); x := Pos(EndLineStr, s); end; @@ -317,7 +359,7 @@ procedure SplitStrToArray(s: string; var Arr: {$IFDEF FPC}specialize{$ENDIF} TAr if s <> '' then begin SetLength(Arr, Length(Arr) + 1); - Arr[High(Arr)] := s; + Arr[Length(Arr) - 1] := s; end; end; @@ -339,7 +381,7 @@ function InsertNumSep(NumStr: string; Separator: string = ' '; NumBlockSize: int xp := Pos('.', s); if xp > 0 then LastDigitPos := xp - 1; - xp := Pos(FormatSettings.DecimalSeparator, s); + xp := Pos(GetDecimalSeparator, s); if xp > 0 then LastDigitPos := xp - 1; Len := LastDigitPos; @@ -799,7 +841,7 @@ function ReplaceFirst(const SrcStr, OldStr, NewStr: string; IgnoreCase: Boolean function ReplaceDecimalSeparator(const FloatStr: string; NewSeparator: string = '.'): string; begin - Result := StringReplace(FloatStr, FormatSettings.DecimalSeparator, NewSeparator, [rfReplaceAll, rfIgnoreCase]); + Result := StringReplace(FloatStr, GetDecimalSeparator, NewSeparator, [rfReplaceAll, rfIgnoreCase]); end; {$hints off} @@ -1116,6 +1158,20 @@ function IntToStrEx(const x: integer; c: Char = ' '): string; Result := Trim(s); end; +function IntToStrEx(const x: UInt64; c: Char = ' '): string; +var + s: string; + i, k, Len: integer; +begin + s := IntToStr(x); + + k := Length(s) div 3; + Len := Length(s); + for i := 1 to k do Insert(c, s, Len - (i * 3) + 1); + + Result := Trim(s); +end; + end. diff --git a/Base/JPL.TStringsHelper.pas b/Base/JPL.TStringsHelper.pas new file mode 100644 index 0000000..574224a --- /dev/null +++ b/Base/JPL.TStringsHelper.pas @@ -0,0 +1,128 @@ +unit JPL.TStringsHelper; + +{$I .\..\jp.inc} + +interface + +uses + SysUtils, Classes; + + +type + + TStringsHelper = class helper for TStrings + procedure TrimAllLines; + procedure RemoveEmptyLines; + procedure TrimAndRemoveEmptyLines; + + // Warning! Use only for lists with a relatively small number of lines (up to several thousand) + // With larger lists it is very slow! + procedure RemoveDuplicatesWithoutSorting(IgnoreCase: Boolean = False); + end; + + +implementation + + + + +procedure TStringsHelper.RemoveEmptyLines; +var + i: integer; +begin + BeginUpdate; + try + for i := Count - 1 downto 0 do + if Strings[i] = '' then Delete(i); + finally + EndUpdate; + end; +end; + +procedure TStringsHelper.TrimAllLines; +var + i: integer; +begin + BeginUpdate; + try + for i := 0 to Count - 1 do + Strings[i] := Trim(Strings[i]); + finally + EndUpdate; + end; +end; + +procedure TStringsHelper.TrimAndRemoveEmptyLines; +var + i: integer; +begin + BeginUpdate; + try + for i := Count - 1 downto 0 do + begin + Strings[i] := Trim(Strings[i]); + if Strings[i] = '' then Delete(i); + end; + finally + EndUpdate; + end; +end; + + +procedure TStringsHelper.RemoveDuplicatesWithoutSorting(IgnoreCase: Boolean); +var + TempList: TStringList; + AB: array of Boolean; + i: integer; + Line: string; + + function _IsLineDuplicated(const IndStart: integer): Boolean; + var + x: integer; + begin + Result := False; + for x := IndStart downto 0 do + if TempList[x] = Line then + begin + Result := True; + Break; + end; + end; + +begin + if Count = 0 then Exit; + + // Wyszukiwanie indeksów linii do usunięcia. + // Tablica AB jest zsynchronizowana z listą. + // Jeśli linia jest zduplikowana, to w tablicy AB o indeksie równym indeksowi linii ze StringLista + // zapisywana jest wartość True, w przeciwnym razie - False. + TempList := TStringList.Create; + try + + TempList.Assign(Self); + if IgnoreCase then TempList.Text := UpperCase(TempList.Text); + SetLength(AB, TempList.Count); + + for i := TempList.Count - 1 downto 0 do + begin + Line := TempList[i]; + AB[i] := _IsLineDuplicated(i - 1); + end; + + finally + TempList.Free; + end; + + + // Usuwanie duplikatów + BeginUpdate; + try + for i := Count - 1 downto 0 do + if AB[i] then Delete(i); + finally + EndUpdate; + end; +end; + + +end. diff --git a/Base/JPL.Win.Dialogs.pas b/Base/JPL.Win.Dialogs.pas index 8f10a01..bef27ed 100644 --- a/Base/JPL.Win.Dialogs.pas +++ b/Base/JPL.Win.Dialogs.pas @@ -1,10 +1,12 @@ unit JPL.Win.Dialogs; -{$IFDEF FPC} {$mode objfpc}{$H+} {$ENDIF} - interface {$IFDEF MSWINDOWS} + +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE OBJFPC}{$H+}{$ENDIF} + uses Windows; @@ -21,7 +23,9 @@ procedure WinMsgInfo(Text: string; Caption: string = 'Information'; Handle: HWND procedure WinMsgWarning(Text: string; Caption: string = 'Warning'; Handle: HWND = 0); procedure WinMsgError(Text: string; Caption: string = 'Error'; Handle: HWND = 0); -{$ENDIF} + +{$ENDIF} // MSWINDOWS + implementation @@ -52,8 +56,8 @@ procedure WinMsgError(Text: string; Caption: string = 'Error'; Handle: HWND = 0) begin WinMsg(Text, Caption, Handle, MB_OK or MB_ICONERROR); end; -{$ENDIF} +{$ENDIF} // MSWINDOWS end. diff --git a/Base/JPL.Win.FileSystem.pas b/Base/JPL.Win.FileSystem.pas index cb70182..619d0ab 100644 --- a/Base/JPL.Win.FileSystem.pas +++ b/Base/JPL.Win.FileSystem.pas @@ -1,22 +1,23 @@ unit JPL.Win.FileSystem; -{$IFDEF FPC} {$mode delphi} {$ENDIF} - interface - {$IFDEF MSWINDOWS} + +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} + uses - Windows, SysUtils, Classes, {$IFDEF DCC}IOUtils,{$ENDIF} - //JP_Lists, - JPL.Strings, JPL.Conversion, + Windows, SysUtils, Classes, {$IFDEF DCC}{$IFDEF DELPHI2010_OR_ABOVE}IOUtils,{$ENDIF}{$ENDIF} + JPL.Strings, Dialogs, - Registry, Menus, + Menus, ShellAPI, ComObj, ShlObj, ActiveX; const CSIDL_PROFILES = $003e; + SHGFP_TYPE_CURRENT = 0; {$region ' --- CSIDLs --- '} ArrCSIDL: array[0..38] of integer = ( @@ -157,44 +158,9 @@ TShellLink = class(TObject) function GetInfoStr(Sep: string = ' '): string; end; -// {$region ' --- TFileSystem --- '} -// TFileSystem = class(TObject) -// public -// AppPaths: array of TAppPathRec; -// SpecialFolders: array of TSpecialFolderRec; -// FileList: TStringList; -// UserList: TStringList; -// PathList: TStringList; -// constructor Create; -// destructor Destroy; override; -// //procedure FillFileList(StartDir: string; FileMask: string = '*.*'; SubdirsCount: integer = 20; StatusProc: TFillFileListStatusProc = nil); -// function GetEnvVar(EnvVarName: string): string; -// procedure FillPathList; -// procedure FillAppPaths(FileMustExists: Boolean = True); -// function GetAppPathsStr: string; -// function GetAppPathFileName(AppName: string): string; -// function GetAppPathIndex(AppName: string): integer; -// function GetSpecialFolder(CSIDL: integer): string; -// procedure FillSpecialFolders; -// function GetSpecialFoldersStr: string; -// function GetFullFileName(ShortName: string): string; -// function GetFileIcon(fName: string; IconIndex: integer = 0): HICON; -// end; -// {$endregion TFileSystem} - - - - -////////////////////////////////////////////////////////////////////////////////////////// + function DirectoryExists(const Name: string): Boolean; function CreateEmptyFile(const fName: string): Boolean; -//function FileSizeInt(const FileName: string): int64; -//function FileSizeInt2(const FileName: string): int64; -//function FileSizeInt3(const FileName: string): int64; -//function FileSizeStr(FileName: string): string; -//function GetFileSizeString(FileSize: Int64): string; -//function GetFileSizeString64(FileSize: Int64): string; -//function DelFile(const FileName: string): Boolean; function GetFileVersionString(FileName, VerStr: string): string; function CopyFile(const SrcFile, DestFile: string): Boolean; function ShowFilePropertiesDialog(hOwner: HWND; const FileName: string): Boolean; @@ -204,23 +170,35 @@ function SetFileAttr(fName: string; R, A, S, H: Boolean): Boolean; function IsFileReadOnly(fName: string): Boolean; function FileOnCdrom(fName: string): Boolean; function GetFileText(fName: string): string; -//function GetFilesSize(Dir: string; xSubdirs: integer = 50; StatusProc: TFillFileListStatusProc = nil): int64; function GetFileSizeEx(hFile: THandle; lpFileSize: PLargeInteger): BOOL; stdcall; external kernel32 name 'GetFileSizeEx'; function GetDesktopFolder: string; function GetSpecialFolder(const CSIDL: integer; Default: string = ''): string; function GetTmpFileName(Prefix: string = ''; Ext: string = ''; NameLen: Byte = 12): string; +{$IFDEF DELPHI2009_OR_BELOW} +function SHGetFolderPathA(hwnd: HWND; csidl: Integer; hToken: THandle; dwFlags: DWORD; pszPath: LPSTR): HResult; stdcall; +function SHGetFolderPathW(hwnd: HWND; csidl: Integer; hToken: THandle; dwFlags: DWORD; pszPath: LPWSTR): HResult; stdcall; +function SHGetFolderPath(hwnd: HWND; csidl: Integer; hToken: THandle; dwFlags: DWORD; pszPath: LPWSTR): HResult; stdcall; +{$ENDIF} + {$ENDIF} // MSWINDOWS implementation + {$IFDEF MSWINDOWS} + uses JPL.Files, JPL.Win.System; +{$IFDEF DELPHI2009_OR_BELOW} +function SHGetFolderPath; external 'shell32.dll' name 'SHGetFolderPathW'; +function SHGetFolderPathA; external 'shell32.dll' name 'SHGetFolderPathA'; +function SHGetFolderPathW; external 'shell32.dll' name 'SHGetFolderPathW'; +{$ENDIF} function GetTmpFileName(Prefix: string = ''; Ext: string = ''; NameLen: Byte = 12): string; var @@ -242,33 +220,14 @@ function GetSpecialFolder(const CSIDL: integer; Default: string = ''): string; var Path: array[0..Max_Path] of Char; begin - if ShGetFolderPath(0, CSIDL, 0, SHGFP_TYPE_CURRENT, Path) = S_OK then Result := Path + if ShGetFolderPath(0, CSIDL, 0, SHGFP_TYPE_CURRENT, Path{%H-}) = S_OK then Result := Path else Result := Default; end; function GetDesktopFolder: string; -//var -// pidl: PItemIDList; -// pMalloc: IMalloc; -// hr: HRESULT; -// Buffer: array[0..1023] of Char; begin Result := GetSpecialFolder(CSIDL_DESKTOPDIRECTORY, ''); -// Result := ''; -// pMalloc := nil; -// hr := SHGetMalloc(pMalloc); -// if hr <> NOERROR then Exit; -// -// hr := SHGetSpecialFolderLocation(0, CSIDL_DESKTOP, pidl); -// if hr <> S_OK then Exit; -// -// FillChar(Buffer, SizeOf(Buffer), 0); -// if SHGetPathFromIDList(pidl, Buffer) then Result := Buffer; -// -// pMalloc.Free(pidl); -// pMalloc._Release; - end; function GetFileText(fName: string): string; @@ -311,6 +270,7 @@ function IsFileReadOnly(fName: string): Boolean; Result := FileIsReadOnly(fName); end; +{$WARN SYMBOL_PLATFORM OFF} function SetFileAttr(fName: string; R, A, S, H: Boolean): Boolean; var Attrs: integer; @@ -329,6 +289,7 @@ function SetFileAttr(fName: string; R, A, S, H: Boolean): Boolean; end; Result := True; end; +{$WARN SYMBOL_PLATFORM ON} function GetCdId(Letter: string): DWORD; var @@ -339,18 +300,16 @@ function GetCdId(Letter: string): DWORD; Name := Letter + ':'; GetVolumeInformation( PChar(Name), - VolName, + VolName{%H-}, SizeOf(VolName), @CdId, - x1, - x2, + x1{%H-}, + x2{%H-}, nil, 0 ); - if UpperCase(VolName) = 'AUDIO CD' then - Result := CdId - else - Result := 0; + if UpperCase(VolName) = 'AUDIO CD' then Result := CdId + else Result := 0; end; function GetDriveNumber(const DriveLetter: Char): integer; @@ -365,8 +324,8 @@ function GetDriveNumber(const DriveLetter: Char): integer; nil, 0, @dwSerial, - dwMaxComLen, - dwSysFlags, + dwMaxComLen{%H-}, + dwSysFlags{%H-}, nil, 0 ) then Result := dwSerial; @@ -469,219 +428,6 @@ function GetFileVersionString(FileName, VerStr: string): string; end; -//{$hints off} -//function DelFile(const FileName: string): Boolean; -//var -// w: WORD; -//begin -// Result := True; -// try -// -// if not DeleteFile(FileName) then -// try -// w := 0 and not faReadOnly and not faSysFile and not faHidden; -// FileSetAttr(FileName, w); -// DeleteFile(FileName); -// except -// Result := not FileExists(FileName); -// end; -// -// Result := not FileExists(FileName); -// -// except -// Result := not FileExists(FileName); -// end; -//end; -//{$hints on} - -{$region ' --------------- File SIZE procs ----------------- '} - - -//function GetFilesSize(Dir: string; xSubdirs: integer = 50; StatusProc: TFillFileListStatusProc = nil): int64; -//var -// sl: TStringList; -// xSize: int64; -// i: integer; -//begin -// -// xSize := 0; -// sl := TStringList.Create; -// try -// FillFileList('*.*', Dir, sl, xSubdirs, StatusProc); -// for i := 0 to sl.Count - 1 do -// begin -// xSize := xSize + FileSizeInt(sl[i]); -// if i mod 4 = 0 then -// if Assigned(StatusProc) then -// if not StatusProc then Break; -// end; -// finally -// sl.Free; -// end; -// Result := xSize; -// -//end; - -// FileSize routines moved to JPL.Files - -//function DSiFileSize(const fileName: string): int64; -//var -// fHandle: DWORD; -//begin -// fHandle := CreateFile(PChar(fileName), 0, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); -// if fHandle = INVALID_HANDLE_VALUE then Result := -1 -// else -// try -// Int64Rec(Result).Lo := GetFileSize(fHandle, @Int64Rec(Result).Hi); -// finally -// CloseHandle(fHandle); -// end; -//end; - -//function FileSizeIntEX(const aFilename: String): Int64; -//var -// info: TWin32FileAttributeData; -//begin -// result := 0; -// -// if not GetFileAttributesEx(PWideChar(aFileName), GetFileExInfoStandard, @info) then EXIT; -// -// Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32); -//end; - -//function FileSizeInt(const FileName: string): int64; -//{var -// h: THandle; } -//begin -// Result := 0; -// try -// //Result := FileSizeIntEX(FileName); -// Result := FileSizeInt3(FileName); -// except -// on E: Exception do -// try -// Result := DSiFileSize(FileName); -// except -// end; -// end; -//end; - -//function FileSizeInt2(const FileName: string): int64; -//var -// h: THandle; -//begin -// if FileExists(FileName) then -// begin -// h := CreateFile(PChar(FileName), -// GENERIC_READ, -// FILE_SHARE_READ, -// nil, -// OPEN_EXISTING, -// FILE_ATTRIBUTE_NORMAL, -// 0); -// GetFileSizeEx(h, @Result); -// CloseHandle(h); -// end -// else -// Result := 0; -//end; - -//function FileSizeInt3(const FileName: string): int64; -//var -// fs: TFileStream; -//begin -// Result := 0; -// if not FileExists(FileName) then Exit; -// -// //try -// fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone); -// try -// Result := fs.Size; -// finally -// fs.Free; -// end; -// -// //except -// //end; -//end; - -{ -function FileSizeInt2(const FileName: string): DWORD; -var - f: file; - i: DWORD; - ofm: BYTE; -begin - Result := 0; - try - AssignFile(f, FileName); - ofm := FileMode; - try - FileMode := fmOpenRead; - Reset(f, 1); - i := DWORD(FileSize(f)); - CloseFile(f); - Result := i; - finally - FileMode := ofm; - end; - except - //on E: Exception do ShowMessage(E.Message); - end; -end; } - - -//function FileSizeStr(FileName: string): string; -//begin -// Result := GetFileSizeString(FileSizeInt(FileName)); -//end; - - - -// MOVED to JPL.Strings - -//function GetFileSizeString(FileSize: Int64): string; -//var -// fs: extended; -// s: ShortString; -// bNegative: Boolean; -//begin -// bNegative := FileSize < 0; -// if bNegative then FileSize := -FileSize; -// Result := IntToStr(FileSize); -// fs := FileSize; -// if fs < 1024 then -// begin -// str( -// fs: 2: 0, s); -// Result := string(s) + ' bytes'; -// end -// else if (fs >= 1024) and (fs < (1024 * 1024)) then -// begin -// fs := fs / 1024; -// str(fs: 2: 2, s); -// Result := string(s) + ' KB'; -// end -// else if (fs >= 1024 * 1024) and (fs < (1024 * 1024 * 1024)) then -// begin -// fs := (fs / 1024) / 1024; -// str(fs: 2: 2, s); -// Result := string(s) + ' MB'; -// end -// else -// begin -// fs := (fs / 1024) / 1024 / 1024; -// str(fs: 2: 2, s); -// Result := string(s) + ' GB'; -// end; -// if bNegative then Result := '-' + Result; -//end; -// -//function GetFileSizeString64(FileSize: Int64): string; -//begin -// Result := GetFileSizeString(FileSize); -//end; -{$endregion File SIZE procs} function DirectoryExists(const Name: string): Boolean; var @@ -705,297 +451,6 @@ function CreateEmptyFile(const fName: string): Boolean; end; -{$region ' ------------------------- TFileSystem ----------------------- '} - -//constructor TFileSystem.Create; -//begin -// inherited Create; -// FileList := TStringList.Create; -// UserList := TStringList.Create; -// PathList := TStringList.Create; -// -// SetLength(AppPaths, 0); -// SetLength(SpecialFolders, 0); -// //FillPathList; -//end; - -//destructor TFileSystem.Destroy; -//begin -// FileList.Free; -// UserList.Free; -// PathList.Free; -// inherited Destroy; -//end; - -//procedure TFileSystem.FillAppPaths(FileMustExists: Boolean); -//var -// Reg: TRegistry; -// slKeys: TStringList; -// i, xInd: integer; -// sAppPaths, sFileName: string; -//begin -// SetLength(AppPaths, 0); -// -// sAppPaths := 'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\'; -// -// Reg := TRegistry.Create; -// slKeys := TStringList.Create; -// try -// with Reg do -// begin -// -// RootKey := HKEY_LOCAL_MACHINE; -// -// if not OpenKey(sAppPaths, False) then Exit; -// GetKeyNames(slKeys); -// CloseKey; -// -// for i := 0 to slKeys.Count - 1 do -// begin -// if not OpenKey(sAppPaths + slKeys[i], False) then Continue; -// sFileName := ReadString(''); -// sFileName := ExpandEnvironmentString(sFileName, False); -// if (ExtractFileDir(sFileName) = '') and Reg.ValueExists('Path') then sFileName := rbs(ReadString('Path')) + '\' + sFileName; -// sFileName := UnquoteStr(sFileName); -// if FileMustExists then -// if not FileExists(sFileName) then -// begin -// CloseKey; -// Continue; -// end; -// SetLength(AppPaths, Length(AppPaths) + 1); -// xInd := Length(AppPaths) - 1; -// AppPaths[xInd].Name := slKeys[i]; -// AppPaths[xInd].FileName := sFileName; -// CloseKey; -// end; -// -// end; -// finally -// Reg.Free; -// slKeys.Free; -// end; -//end; - -//procedure TFileSystem.FillFileList(StartDir: string; FileMask: string; SubdirsCount: integer; StatusProc: TFillFileListStatusProc); -//begin -// FileList.Clear; -// JP_Lists.FillFileList(FileMask, StartDir, FileList, SubdirsCount, StatusProc); -//end; - -//procedure TFileSystem.FillPathList; -//var -// Path: string; -// i: integer; -// -// function fs(s: string): string; -// begin -// Result := rbs(s); -// end; -// -//begin -// Path := GetEnvVar('PATH'); -// MakeList(Path, PathList, ';'); -// for i := 0 to PathList.Count - 1 do PathList[i] := fs(PathList[i]); -//end; - -//function TFileSystem.GetAppPathFileName(AppName: string): string; -//var -// i: integer; -// UName: string; -//begin -// Result := ''; -// UName := AnsiUpperCase(AppName); -// for i := 0 to Length(AppPaths) - 1 do -// if AnsiUpperCase(AppPaths[i].Name) = UName then -// begin -// Result := AppPaths[i].FileName; -// Break; -// end; -//end; - -//function TFileSystem.GetAppPathIndex(AppName: string): integer; -//var -// i: integer; -// UName: string; -//begin -// Result := -1; -// UName := AnsiUpperCase(AppName); -// for i := 0 to Length(AppPaths) - 1 do -// if AnsiUpperCase(AppPaths[i].Name) = UName then -// begin -// Result := i; -// Break; -// end; -//end; - -//function TFileSystem.GetAppPathsStr: string; -//var -// i: integer; -// s: string; -//begin -// s := ''; -// for i := 0 to Length(AppPaths) - 1 do -// begin -// s := -// s + Pad(IntToStr(i + 1), 3, '0') + CRLF + -// ' Name: ' + AppPaths[i].Name + CRLF + -// ' File: ' + AppPaths[i].FileName + CRLF; -// end; -// Result := s; -//end; - -//function TFileSystem.GetEnvVar(EnvVarName: string): string; -//{var -// Buffer: array[0..1023] of Char; -// dwX: DWORD; } -//begin -// Result := GetEnvironmentString(EnvVarName); -//{ FillChar(Buffer, SizeOf(Buffer), 0); -// dwX := GetEnvironmentVariable(PChar(EnvVarName), Buffer, SizeOf(Buffer)); -// if dwX <> 0 then Result := Buffer -// else Result := ''; } -//end; - -//function TFileSystem.GetSpecialFolder(CSIDL: integer): string; -//var -// pidl: PItemIDList; -// pMalloc: IMalloc; -// hr: HRESULT; -// Buffer: array[0..1023] of Char; -//begin -// Result := ''; -// pMalloc := nil; -// hr := SHGetMalloc(pMalloc); -// if hr <> NOERROR then Exit; -// -// hr := SHGetSpecialFolderLocation(0, CSIDL, pidl); -// if hr <> S_OK then Exit; -// -// FillChar(Buffer, SizeOf(Buffer), 0); -// if SHGetPathFromIDList(pidl, Buffer) then Result := Buffer; -// -// pMalloc.Free(pidl); -// pMalloc._Release; -//end; - -//procedure TFileSystem.FillSpecialFolders; -//var -// i, xInd: integer; -//begin -// SetLength(SpecialFolders, 0); -// for i := 0 to Length(ArrCSIDL) - 1 do -// begin -// SetLength(SpecialFolders, Length(SpecialFolders) + 1); -// xInd := Length(SpecialFolders) - 1; -// SpecialFolders[xInd].CSIDL_Name := ArrCSIDLNames[i]; -// SpecialFolders[xInd].Path := GetSpecialFolder(ArrCSIDL[i]); -// end; -//end; - -//function TFileSystem.GetSpecialFoldersStr: string; -//var -// i: integer; -// s: string; -//begin -// s := ''; -// for i := 0 to Length(SpecialFolders) - 1 do -// begin -// s := -// s + Pad(IntToStr(i + 1), 2, '0') + '. ' + -// SpecialFolders[i].CSIDL_Name + ': ' + -// SpecialFolders[i].Path + CRLF; -// end; -// Result := s; -//end; - -//function TFileSystem.GetFullFileName(ShortName: string): string; -//var -// s: string; -// i: integer; -//begin -// Result := ShortName; -// -// if FileExists(ExpandFileName(ShortName)) then -// begin -// Result := ExpandFileName(ShortName); -// Exit; -// end; -// -// if PathList.Count = 0 then FillPathList; -// for i := 0 to PathList.Count - 1 do -// begin -// s := PathList[i] + '\' + s; -// if FileExists(s) then -// begin -// Result := s; -// Exit; -// end; -// end; -// -// if Length(AppPaths) = 0 then FillAppPaths; -// s := GetAppPathFileName(ShortName); -// if FileExists(s) then -// begin -// Result := s; -// Exit; -// end; -// -// if Length(SpecialFolders) = 0 then FillSpecialFolders; -// for i := 0 to Length(SpecialFolders) - 1 do -// begin -// s := SpecialFolders[i].Path + '\' + ShortName; -// if FileExists(s) then -// begin -// Result := s; -// Exit; -// end; -// end; -// -//end; - -//function TFileSystem.GetFileIcon(fName: string; IconIndex: integer): HICON; -//var -// W: WORD; -// hi, hIconLarge, hIconSmall: HICON; -// shfi: TSHFILEINFO; -//begin -// -// if ExtractFileDir(fName) = '' then fName := GetFullFileName(fName); -// -// -// ExtractIconEx(PChar(fName), IconIndex, hIconLarge, hIconSmall, 1); -// hi := hIconSmall; -// -// if hi = 0 then -// begin -// FillChar(shfi, SizeOf(shfi), 0); -// -// shfi.iIcon := IconIndex; -// SHGetFileInfo( -// PChar(fName), -// FILE_ATTRIBUTE_NORMAL, -// shfi, -// SizeOf(shfi), -// SHGFI_USEFILEATTRIBUTES or SHGFI_ICON or SHGFI_SMALLICON -// ); -// -// hi := shfi.hIcon; -// end; -// -// -// -// if hi = 0 then -// begin -// if UpperCase(ExtractFileExt(fName)) <> '.EXE' then -// hi := ExtractAssociatedIcon(hInstance, PChar(fName), W); -// end; -// -// Result := hi; -//end; -{$endregion TFileSystem} - - {$region ' ---------------- TShellLink ------------------- '} procedure TShellLink.ClearShellLinkRec; @@ -1039,12 +494,12 @@ procedure TShellLink.GetLinkInfo(LinkFile: string); begin FillChar(Buffer, SizeOf(Buffer), 0); end; - + begin ClearShellLinkRec; if not FileExists(LinkFile) then Exit; - fName := LinkFile; + fName := WideString(LinkFile); CoInitialize(nil); Obj := CreateComObject(CLSID_ShellLink); @@ -1055,8 +510,8 @@ procedure TShellLink.GetLinkInfo(LinkFile: string); CB; - StrPCopy(Buffer, fName); - if Link.GetPath(Buffer, SizeOf(Buffer), pwd, SLGP_RAWPATH) = S_OK then + StrPCopy(Buffer{%H-}, fName{%H-}); + if Link.GetPath(Buffer, SizeOf(Buffer), pwd{%H-}, SLGP_RAWPATH) = S_OK then ShellLinkRec.Path := UnquoteStr(ExpandEnvironmentString(Buffer, False)); CB; @@ -1068,7 +523,7 @@ procedure TShellLink.GetLinkInfo(LinkFile: string); ShellLinkRec.Description := UnquoteStr(Buffer); CB; - if Link.GetIconLocation(Buffer, SizeOf(Buffer), x) = S_OK then + if Link.GetIconLocation(Buffer, SizeOf(Buffer), x{%H-}) = S_OK then begin ShellLinkRec.IconFile := UnquoteStr(ExpandEnvironmentString(Buffer, False)); ShellLinkRec.IconIndex := x; @@ -1081,7 +536,7 @@ procedure TShellLink.GetLinkInfo(LinkFile: string); if Link.GetWorkingDirectory(Buffer, SizeOf(Buffer)) = S_OK then ShellLinkRec.WorkingDirectory := UnquoteStr(ExpandEnvironmentString(Buffer, False)); - if Link.GetHotkey(w) = S_OK then ShellLinkRec.Hotkey := w; + if Link.GetHotkey(w{%H-}) = S_OK then ShellLinkRec.Hotkey := w; end; procedure TShellLink.SaveLinkFile(LinkFile: string); @@ -1091,7 +546,7 @@ procedure TShellLink.SaveLinkFile(LinkFile: string); PF: IPersistFile; fName: WideString; begin - fName := LinkFile; + fName := WideString(LinkFile); CoInitialize(nil); Obj := CreateComObject(CLSID_ShellLink); @@ -1224,7 +679,8 @@ function TURLFile.GetInfoStr(Sep: string): string; end; {$endregion TURLFile} -{$ENDIF} //MSWINDOWS + +{$ENDIF} // MSWINDOWS end. diff --git a/Base/JPL.Win.Processes.pas b/Base/JPL.Win.Processes.pas index dbddfee..5c397e3 100644 --- a/Base/JPL.Win.Processes.pas +++ b/Base/JPL.Win.Processes.pas @@ -1,11 +1,14 @@ unit JPL.Win.Processes; -{$IFDEF FPC} {$mode delphi} {$ENDIF} - interface +{$IFDEF MSWINDOWS} + +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} + uses - Windows, SysUtils, Classes, TlHelp32, PsAPI, ShellAPI; + Windows, SysUtils, Classes, {$IFDEF FPC}JwaTlHelp32, JwaPsApi{$ELSE}TlHelp32, PsAPI{$ENDIF}, ShellAPI; function GetProcessFileName(const pID: DWORD): string; @@ -14,15 +17,23 @@ function GetThreadFileName(const tID: DWORD): string; procedure RunAsAdmin(hWnd: HWND; FileName, Parameters: string); +{$ENDIF} // MSWINDOWS + implementation +{$IFDEF MSWINDOWS} + procedure RunAsAdmin(hWnd: HWND; FileName, Parameters: string); var - sei: TShellExecuteInfo; + {$IFDEF UNICODE} + sei: TShellExecuteInfoW; + {$ELSE} + sei: TShellExecuteInfoA; + {$ENDIF} begin - FillChar(sei, SizeOf(sei), 0); + FillChar(sei{%H-}, SizeOf(sei), 0); sei.cbSize := sizeof(sei); sei.Wnd := hWnd; sei.fMask := SEE_MASK_FLAG_DDEWAIT or SEE_MASK_FLAG_NO_UI; @@ -30,7 +41,11 @@ procedure RunAsAdmin(hWnd: HWND; FileName, Parameters: string); sei.lpFile := PChar(FileName); sei.lpParameters := PChar(Parameters); sei.nShow := SW_SHOWNORMAL; - if not ShellExecuteEx(@sei) then RaiseLastOSError; + {$IFDEF UNICODE} + if not ShellExecuteExW(@sei) then RaiseLastOSError; + {$ELSE} + if not ShellExecuteExA(@sei) then RaiseLastOSError; + {$ENDIF} end; function GetThreadFileName(const tID: DWORD): string; @@ -113,7 +128,7 @@ function GetProcessFileName(const pID: DWORD): string; hProc := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, pID); if hProc <> 0 then begin - FillChar(buffer, SizeOf(buffer), 0); + FillChar(buffer{%H-}, SizeOf(buffer), 0); GetModuleFileNameEx(hProc, 0, buffer, SizeOf(buffer)); Result := buffer; end; @@ -135,6 +150,6 @@ function GetProcessFileName(const pID: DWORD): string; end; end; - +{$ENDIF} // MSWINDOWS end. diff --git a/Base/JPL.Win.Shortcuts.pas b/Base/JPL.Win.Shortcuts.pas index e632d1a..5f9b8a4 100644 --- a/Base/JPL.Win.Shortcuts.pas +++ b/Base/JPL.Win.Shortcuts.pas @@ -1,12 +1,14 @@ unit JPL.Win.Shortcuts; -{$IFDEF FPC} {$mode delphi} {$ENDIF} - interface {$IFDEF MSWINDOWS} + +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} + uses - Windows, Messages, SysUtils, Variants, Classes, Registry, + Windows, SysUtils, Variants, Classes, Registry, ShlObj, ActiveX, ComObj; //JPL.Strings; @@ -14,13 +16,14 @@ interface procedure DeleteShortcut(const Folder, LnkShortName: string); function ShortcutExists(const Folder, LnkShortName: string): Boolean; -procedure CreateShortcut(const Name, FileName, Folder, LnkShortName: string; Description: string = ''); +procedure CreateShortcut(const {%H-}Name, FileName, Folder, LnkShortName: string; Description: string = ''); -{$ENDIF} +{$ENDIF} // MSWINDOWS implementation + {$IFDEF MSWINDOWS} procedure DeleteShortcut(const Folder, LnkShortName: string); @@ -112,14 +115,14 @@ procedure CreateShortcut(const Name, FileName, Folder, LnkShortName: string; Des end; //fName := dir + '\' + Name + '.lnk'; - fName := dir + '\' + LnkShortName; + fName := WideString(dir) + '\' + WideString(LnkShortName); pf.Save(PWChar(fName), false); except end; end; - {$ENDIF} // MSWINDOWS + end. diff --git a/Base/JPL.Win.System.pas b/Base/JPL.Win.System.pas index 714b259..d1ba135 100644 --- a/Base/JPL.Win.System.pas +++ b/Base/JPL.Win.System.pas @@ -1,11 +1,13 @@ unit JPL.Win.System; -{$IFDEF FPC} {$mode delphi} {$ENDIF} - - interface {$IFDEF MSWINDOWS} + +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} + + uses Windows, SysUtils, Classes, Messages, JPL.Strings; @@ -34,7 +36,8 @@ function SetWindowOnTop(const WinHandle: HWND; const OnTop: Boolean): Boolean; PBM_SETBKCOLOR = $2000 + 1; PBM_SETBARCOLOR = WM_USER + 9; -{$ENDIF} +{$ENDIF} // MSWINDOWS + implementation @@ -70,7 +73,7 @@ procedure ShowLastError(const Error: LongWord; MsgPrefix: string = ''; MsgTitle: PChar(@lpBuffer), 0, nil ); MessageBox(dwHandle, PChar(MsgPrefix + string(lpBuffer)), PChar(MsgTitle), MB_OK or MB_ICONEXCLAMATION); - LocalFree(Cardinal(lpBuffer)); + LocalFree({%H-}Cardinal(lpBuffer)); end; @@ -83,23 +86,18 @@ function RestartWindows: Boolean; begin Result := False; - FillChar(tp, SizeOf(tp), 0); + FillChar(tp{%H-}, SizeOf(tp), 0); vi.dwOSVersionInfoSize := SizeOf(TOSVersionInfo); GetVersionEx(vi); - if vi.dwPlatformId <> VER_PLATFORM_WIN32_NT then - Result := ExitWindowsEx(EWX_REBOOT or EWX_FORCE, 0) + if vi.dwPlatformId <> VER_PLATFORM_WIN32_NT then Result := ExitWindowsEx(EWX_REBOOT or EWX_FORCE, 0) else - if OpenProcessToken(GetCurrentProcess, - TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, - hToken) then - if LookupPrivilegeValue(nil, 'SeShutdownPrivilege', - tp.Privileges[0].Luid) then + if OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken{%H-}) then + if LookupPrivilegeValue(nil, 'SeShutdownPrivilege', tp.Privileges[0].Luid) then begin tp.PrivilegeCount := 1; tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; - if AdjustTokenPrivileges(hToken, False, tp, SizeOf(tp), - tp, ReturnLength) then + if AdjustTokenPrivileges(hToken, False, tp, SizeOf(tp), tp, ReturnLength{%H-}) then Result := ExitWindowsEx(EWX_REBOOT or EWX_FORCE, 0); end; end; @@ -117,16 +115,16 @@ function ExitWindows2: Boolean; vi.dwOSVersionInfoSize := SizeOf(TOSVersionInfo); if not GetVersionEx(vi) then Exit; - FillChar(tp, SizeOf(tp), 0); + FillChar(tp{%H-}, SizeOf(tp), 0); if vi.dwPlatformId <> VER_PLATFORM_WIN32_NT then Result := ExitWindowsEx(EWX_POWEROFF or EWX_FORCE, 0) else - if OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then + if OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken{%H-}) then if LookupPrivilegeValue(nil, 'SeShutdownPrivilege', tp.Privileges[0].Luid) then begin tp.PrivilegeCount := 1; tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; - if AdjustTokenPrivileges(hToken, False, tp, SizeOf(tp), tp, ReturnLength) then + if AdjustTokenPrivileges(hToken, False, tp, SizeOf(tp), tp, ReturnLength{%H-}) then Result := ExitWindowsEx(EWX_POWEROFF or EWX_FORCE, 0); end; end; @@ -138,8 +136,8 @@ function SearchPathForFile(const ShortFileName: string; DefResult: string; PathT dwX: DWORD; begin Result := DefResult; - FillChar(Buffer, SizeOf(Buffer), 0); - dwX := SearchPath(nil, PChar(ShortFileName), nil, Length(Buffer), Buffer, lpFilePart); + FillChar(Buffer{%H-}, SizeOf(Buffer), 0); + dwX := SearchPath(PChar(PathToSearch), PChar(ShortFileName), nil, Length(Buffer), Buffer, lpFilePart{%H-}); if dwX = 0 then Exit; Result := Buffer; end; @@ -169,7 +167,7 @@ function ComputerName: string; BufSize: DWORD; begin BufSize := SizeOf(buffer); - FillChar(buffer, BufSize, 0); + FillChar(buffer{%H-}, BufSize, 0); GetComputerName(buffer, BufSize); Result := buffer; end; @@ -180,7 +178,7 @@ function UserName: string; BufSize: DWORD; begin BufSize := SizeOf(Buffer); - FillChar(Buffer, BufSize, 0); + FillChar(Buffer{%H-}, BufSize, 0); GetUserName(Buffer, BufSize); Result := Buffer; end; @@ -189,18 +187,17 @@ function TempDir(ErrorResult: string = ''): string; var Buffer: array[0..MAX_PATH - 1] of Char; begin - FillChar(Buffer, SizeOf(Buffer), 0); + FillChar(Buffer{%H-}, SizeOf(Buffer), 0); Windows.GetTempPath(Length(Buffer), Buffer); if Buffer <> '' then Result := Buffer else Result := ErrorResult; - //Result := ExtractFileDir(ParamStr(0)); end; function WinDir: string; var Buffer: array[0..MAX_PATH - 1] of Char; begin - FillChar(Buffer, SizeOf(Buffer), 0); + FillChar(Buffer{%H-}, SizeOf(Buffer), 0); GetWindowsDirectory(Buffer, SizeOf(Buffer)); Result := Buffer; end; @@ -209,7 +206,7 @@ function SysDir: string; var Buffer: array[0..MAX_PATH - 1] of Char; begin - FillChar(Buffer, SizeOf(Buffer), 0); + FillChar(Buffer{%H-}, SizeOf(Buffer), 0); GetSystemDirectory(Buffer, SizeOf(Buffer)); Result := Buffer; end; @@ -218,7 +215,7 @@ procedure GetEnvironmentList(sl: TStringList); var Base, P: PChar; EnvStr: string; -begin +begin Base := GetEnvironmentStrings; if Base = nil then Exit; P := Base; @@ -235,7 +232,7 @@ function GetEnvironmentString(EnvVar: string; AddPercents: Boolean = True): stri var Buffer: array[0..2047] of Char; begin - FillChar(Buffer, SizeOf(Buffer), 0); + FillChar(Buffer{%H-}, SizeOf(Buffer), 0); if AddPercents then EnvVar := '%' + EnvVar + '%'; ExpandEnvironmentStrings(PChar(EnvVar), Buffer, SizeOf(Buffer)); Result := Buffer; @@ -246,10 +243,7 @@ function ExpandEnvironmentString(const EnvVar: string; AddPercents: Boolean = Tr Result := GetEnvironmentString(EnvVar, AddPercents); end; - {$ENDIF} // MSWINDOWS - - end. diff --git a/Base/JPL.Win.VersionInfo.pas b/Base/JPL.Win.VersionInfo.pas index 1615b03..53f3ce8 100644 --- a/Base/JPL.Win.VersionInfo.pas +++ b/Base/JPL.Win.VersionInfo.pas @@ -32,12 +32,15 @@ { TODO: Pobrać dodatkowe informacje o FixedFileInfo. (zob. opis struktury VS_FIXEDFILEINFO w MSDN } -{$IFDEF FPC} {$mode objfpc}{$H+} {$ENDIF} interface {$IFDEF MSWINDOWS} -uses + +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE OBJFPC}{$H+}{$ENDIF} + +uses Windows, SysUtils, JPL.Strings, JPL.Language, JPL.Conversion; @@ -132,17 +135,19 @@ TJPVersionInfo = class procedure VIClearStringInfoItem(var sii: TVIStringInfoItem); -function VIStringInfoItemToStr(const sii: TVIStringInfoItem; bIncludeTranslationRec: Boolean = False; - bIncludeLangInfo: Boolean = False; PadStr: string = ''): string; +function VIStringInfoItemToStr(const sii: TVIStringInfoItem; bIncludeTranslationRec: Boolean = False; bIncludeLangInfo: Boolean = False; PadStr: string = ''): string; function VIFileVersionToStr(const fv: TVIFileVersion): string; -{$ENDIF} + +{$ENDIF} // MSWINDOWS implementation + {$IFDEF MSWINDOWS} + function VIFixedFileInfoToStr(const ffi: TVSFIXEDFILEINFO): string; begin Result := @@ -162,7 +167,6 @@ function VIFixedFileInfoToStr(const ffi: TVSFIXEDFILEINFO): string; end; - constructor TJPVersionInfo.Create(const FileName: string); begin inherited Create; @@ -187,7 +191,8 @@ procedure TJPVersionInfo.ClearAll; FValidVersionInfo := False; FFixedFileInfoExists := False; FEnglishStringItemIndex := -1; - for i := 0 to High(FStringItems) do VIClearStringInfoItem(FStringItems[i]); +// for i := 0 to High(FStringItems) do VIClearStringInfoItem(FStringItems[i]); + for i := 0 to Length(FStringItems) - 1 do VIClearStringInfoItem(FStringItems[i]); SetLength(FStringItems, 0); end; @@ -337,8 +342,10 @@ procedure TJPVersionInfo.ReadFile; SetLength(FStringItems, Length(FStringItems) + 1); - FStringItems[High(FStringItems)] := sii; - if sii.TranslateRec.wLanguage = VI_LANGID_ENGLISH then FEnglishStringItemIndex := High(FStringItems); +// FStringItems[High(FStringItems)] := sii; + FStringItems[Length(FStringItems) - 1] := sii; +// if sii.TranslateRec.wLanguage = VI_LANGID_ENGLISH then FEnglishStringItemIndex := High(FStringItems); + if sii.TranslateRec.wLanguage = VI_LANGID_ENGLISH then FEnglishStringItemIndex := Length(FStringItems) - 1; finally FreeMem(PTranslate); @@ -358,12 +365,6 @@ procedure TJPVersionInfo.ReadFile; end; - - - - - - procedure VIClearStringInfoItem(var sii: TVIStringInfoItem); begin sii.TranslateRec.wCodePage := 0; @@ -441,7 +442,7 @@ function VIFileVersionToStr(const fv: TVIFileVersion): string; itos(fv.Build); end; -{$ENDIF} // MSWINDOWS +{$ENDIF} // MSWINDOWS end. diff --git a/Binary/JPL.Binary.Elf.pas b/Binary/JPL.Binary.Elf.pas index 4e4f848..f89647b 100644 --- a/Binary/JPL.Binary.Elf.pas +++ b/Binary/JPL.Binary.Elf.pas @@ -1,21 +1,31 @@ unit JPL.Binary.Elf; -// Jacek Pazera -// http://www.pazera-software.com -// 03.2016 -// Delphi XE7 +{ + Jacek Pazera + http://www.pazera-software.com + https://github.com/jackdp -// Based on: -// https://en.wikipedia.org/wiki/Executable_and_Linkable_Format -// http://www.sco.com/developers/gabi/latest/contents.html + Links: + https://en.wikipedia.org/wiki/Executable_and_Linkable_Format + http://www.sco.com/developers/gabi/latest/contents.html +} + + +{$I .\..\jp.inc} + +{$IFDEF FPC} + {$IFNDEF HAS_SPARTA_GENERICS}For FPC 3.0.4 or newer only!{$ENDIF} + {$MODE DELPHI} +{$ENDIF} interface uses - Windows, Sysutils, Classes, - System.Generics.Collections, - JPL.Strings, JPL.Conversion, JPL.Binary.Types, JPL.UPX, JPL.Binary.Procs; + {$IFDEF MSWINDOWS}Windows,{$ENDIF} + Sysutils, Classes, + Generics.Collections, + JPL.Strings, JPL.Conversion, JPL.UPX, JPL.Binary.Procs; diff --git a/Binary/JPL.Binary.Mach.Types.pas b/Binary/JPL.Binary.Mach.Types.pas index 79aa1a7..5da97c8 100644 --- a/Binary/JPL.Binary.Mach.Types.pas +++ b/Binary/JPL.Binary.Mach.Types.pas @@ -25,11 +25,12 @@ // https://www.mikeash.com/pyblog/friday-qa-2012-11-30-lets-build-a-mach-o-executable.html +{$I .\..\jp.inc} + interface uses - Windows, Sysutils, Classes, - JPL.Binary.Types, JPL.UPX, JPL.Binary.Misc; + Sysutils, Classes; diff --git a/Binary/JPL.Binary.MachFat.pas b/Binary/JPL.Binary.MachFat.pas index 64affdc..6e78e3a 100644 --- a/Binary/JPL.Binary.MachFat.pas +++ b/Binary/JPL.Binary.MachFat.pas @@ -1,17 +1,28 @@ unit JPL.Binary.MachFat; -// Jacek Pazera -// 03.2016 -// https://en.wikipedia.org/wiki/Mach-O +{ + Jacek Pazera + + https://en.wikipedia.org/wiki/Mach-O +} + + +{$I .\..\jp.inc} + +{$IFDEF FPC} + {$IFNDEF HAS_SPARTA_GENERICS}For FPC 3.0.4 or newer only!{$ENDIF} + {$MODE DELPHI} +{$ENDIF} + interface uses - Winapi.Windows, - System.Sysutils, System.Classes, System.Generics.Collections, + Windows, + Sysutils, Classes, Generics.Collections, JPL.Strings, JPL.Conversion, - JPL.Binary.Types, JPL.Binary.Mach.Types, JPL.Binary.MachO, JPL.UPX, JPL.Binary.Misc, JPL.Binary.Procs, JPL.Math; + JPL.Binary.Types, JPL.Binary.Mach.Types, JPL.Binary.MachO, JPL.UPX, JPL.Binary.Procs, JPL.Math; type @@ -143,7 +154,7 @@ procedure TMachFatFile.ReadFileInfo; FFatHeader.magic := SwapBytes(FFatHeader.magic); FFatHeader.nfat_arch := SwapBytes(FFatHeader.nfat_arch); - if fs.Size < SizeOf(FFatHeader) + (FFatHeader.nfat_arch * SizeOf(fat_arch)) then Exit; + if fs.Size < Int64(SizeOf(FFatHeader)) + (Int64(FFatHeader.nfat_arch) * Int64(SizeOf(fat_arch))) then Exit; for i := 1 to FFatHeader.nfat_arch do begin @@ -164,7 +175,7 @@ procedure TMachFatFile.ReadFileInfo; mof := TMachOFile.Create; mof.FileName := FFileName; mof.StartOffset := fa.offset; - mof.EndOffset := fa.offset + fa.size; + mof.EndOffset := Int64(fa.offset) + Int64(fa.size); mof.SearchUpxInfo := FSearchUpxInfo; mof.ReadFileInfo; if not mof.IsValidMachFile then diff --git a/Binary/JPL.Binary.MachO.pas b/Binary/JPL.Binary.MachO.pas index 292255a..ce00be1 100644 --- a/Binary/JPL.Binary.MachO.pas +++ b/Binary/JPL.Binary.MachO.pas @@ -1,13 +1,25 @@ unit JPL.Binary.MachO; -// Jacek Pazera -// 03.2016 -// https://en.wikipedia.org/wiki/Mach-O +{ + Jacek Pazera + + https://en.wikipedia.org/wiki/Mach-O +} + + +{$I .\..\jp.inc} + +{$IFDEF FPC} + {$IFNDEF HAS_SPARTA_GENERICS}For FPC 3.0.4 or newer only!{$ENDIF} + {$MODE DELPHI} +{$ENDIF} + interface + uses - Winapi.Windows, System.Sysutils, System.Classes, System.Generics.Collections, + Windows, Sysutils, Classes, Generics.Collections, JPL.Strings, JPL.Conversion, JPL.Binary.Types, JPL.Binary.Mach.Types, JPL.UPX, JPL.Binary.Misc, JPL.Binary.Procs; diff --git a/Binary/JPL.Binary.Misc.pas b/Binary/JPL.Binary.Misc.pas index 987410d..ca057c6 100644 --- a/Binary/JPL.Binary.Misc.pas +++ b/Binary/JPL.Binary.Misc.pas @@ -1,5 +1,14 @@ unit JPL.Binary.Misc; +{$I .\..\jp.inc} + +{$IFDEF FPC} + {$MODE DELPHI} + {$WARN 4055 off : Conversion between ordinals and pointers is not portable} + {$WARN 6058 off : Call to subroutine "$1" marked as inline is not inlined} +{$ENDIF} + + interface uses diff --git a/Binary/JPL.Binary.Pe.pas b/Binary/JPL.Binary.Pe.pas index 217c6aa..2931770 100644 --- a/Binary/JPL.Binary.Pe.pas +++ b/Binary/JPL.Binary.Pe.pas @@ -1,20 +1,31 @@ unit JPL.Binary.Pe; +{$I .\..\jp.inc} + +{$IFDEF FPC} + {$MODE DELPHI} + {$WARN 6058 off : Call to subroutine "$1" marked as inline is not inlined} +{$ENDIF} + + interface uses - Windows, Messages, SysUtils, Classes, + {$IFDEF MSWINDOWS}Windows,{$ENDIF} + SysUtils, Classes, + {$IFDEF FPC}JwaWinNT,{$ENDIF} JPL.Strings, JPL.Files, - JPL.Binary.Types, JPL.UPX, JPL.Conversion, JPL.Binary.Misc + JPL.Binary.Types, JPL.UPX, JPL.Conversion ; { - Usefule links: + Useful links: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#coff-file-header-object-and-image } + const {$region ' CONST '} @@ -90,8 +101,8 @@ TPeInfoItem = record const - - IMAGE_FILE_AGGRESSIVE_WS_TRIM = IMAGE_FILE_AGGRESIVE_WS_TRIM; // $0010 + {$IFDEF FPC}IMAGE_FILE_AGGRESIVE_WS_TRIM = $0010;{$ENDIF} + IMAGE_FILE_AGGRESSIVE_WS_TRIM = IMAGE_FILE_AGGRESIVE_WS_TRIM; {$region ' CONST - DOS Header '} @@ -1152,7 +1163,7 @@ procedure TPeFile.GetFileInfo; // ------------------------------ PE Signature --------------------------------------- - FOffset_PeSignature := FDosHeader._lfanew; + FOffset_PeSignature := FDosHeader.{$IFDEF FPC}e_lfanew{$ELSE}_lfanew{$ENDIF}; if Stream.Size < FOffset_PeSignature + SizeOf(FPeSignature) then Exit; Stream.Position := FOffset_PeSignature; diff --git a/Binary/JPL.Binary.Procs.pas b/Binary/JPL.Binary.Procs.pas index 84778c8..0a0a70b 100644 --- a/Binary/JPL.Binary.Procs.pas +++ b/Binary/JPL.Binary.Procs.pas @@ -1,11 +1,14 @@ unit JPL.Binary.Procs; +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} + interface uses - Windows, Messages, SysUtils, Classes, - JPL.Binary.Types, JPL.Binary.Pe, JPL.Binary.Mach.Types, - JPL.UPX + {$IFDEF MSWINDOWS}Windows,{$ENDIF} + SysUtils, Classes, + JPL.Binary.Types, JPL.Binary.Pe, JPL.Binary.Mach.Types ; @@ -209,7 +212,7 @@ function GetBitsInfo(Stream: TStream; var BitsInfo: TBitsInfo; NotStandardChar: if Stream.Size < 4 then Exit; Stream.Position := 0; - Stream.ReadBuffer(Arr, Length(Arr)); + Stream.ReadBuffer(Arr{%H-}, Length(Arr)); Stream.Position := OldPos; BitsInfo.B1 := Arr[0]; @@ -361,7 +364,11 @@ function GetWinExeBinType(fName: string): integer; var bt: Cardinal; begin + {$IFDEF DCC} if GetBinaryType(PWideChar(fName), bt) then + {$ELSE} + if GetBinaryType(PChar(fName), bt{%H-}) then + {$ENDIF} begin case bt of BIN_WIN32: Result := BIN_WIN32; @@ -393,9 +400,9 @@ function GetBinMagicStr(Stream: TStream): string; overload; OldPos := Stream.Position; Stream.Position := 0; - x := Stream.Read(Buffer, BufferSize); + x := Stream.Read(Buffer{%H-}, BufferSize); Stream.Position := 0; - Stream.Read(Magic, SizeOf(Magic)); + Stream.Read(Magic{%H-}, SizeOf(Magic)); Stream.Position := OldPos; if x <> BufferSize then Exit; // BufferSize = SizeOf(Magic) diff --git a/Binary/JPL.Binary.Types.pas b/Binary/JPL.Binary.Types.pas index cf030ab..d52b30f 100644 --- a/Binary/JPL.Binary.Types.pas +++ b/Binary/JPL.Binary.Types.pas @@ -1,10 +1,14 @@ unit JPL.Binary.Types; +{$I .\..\jp.inc} + interface uses SysUtils - //, Dialogs + {$IFDEF DCC}{$IFNDEF DELPHIXE2_OR_ABOVE} + , Windows + {$ENDIF}{$ENDIF} ; @@ -48,6 +52,85 @@ TBitsInfo = record BIN_INVALID_OFFSET = -1; +{$IFDEF DCC} +{$IFNDEF DELPHIXE2_OR_ABOVE} +type + PImageOptionalHeader32 = ^TImageOptionalHeader32; + _IMAGE_OPTIONAL_HEADER32 = record + { Standard fields. } + Magic: Word; + MajorLinkerVersion: Byte; + MinorLinkerVersion: Byte; + SizeOfCode: DWORD; + SizeOfInitializedData: DWORD; + SizeOfUninitializedData: DWORD; + AddressOfEntryPoint: DWORD; + BaseOfCode: DWORD; + BaseOfData: DWORD; + { NT additional fields. } + ImageBase: DWORD; + SectionAlignment: DWORD; + FileAlignment: DWORD; + MajorOperatingSystemVersion: Word; + MinorOperatingSystemVersion: Word; + MajorImageVersion: Word; + MinorImageVersion: Word; + MajorSubsystemVersion: Word; + MinorSubsystemVersion: Word; + Win32VersionValue: DWORD; + SizeOfImage: DWORD; + SizeOfHeaders: DWORD; + CheckSum: DWORD; + Subsystem: Word; + DllCharacteristics: Word; + SizeOfStackReserve: DWORD; + SizeOfStackCommit: DWORD; + SizeOfHeapReserve: DWORD; + SizeOfHeapCommit: DWORD; + LoaderFlags: DWORD; + NumberOfRvaAndSizes: DWORD; + DataDirectory: packed array[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1] of TImageDataDirectory; + end; + TImageOptionalHeader32 = _IMAGE_OPTIONAL_HEADER32; + + PImageOptionalHeader64 = ^TImageOptionalHeader64; + _IMAGE_OPTIONAL_HEADER64 = record + { Standard fields. } + Magic: Word; + MajorLinkerVersion: Byte; + MinorLinkerVersion: Byte; + SizeOfCode: DWORD; + SizeOfInitializedData: DWORD; + SizeOfUninitializedData: DWORD; + AddressOfEntryPoint: DWORD; + BaseOfCode: DWORD; + { NT additional fields. } + ImageBase: ULONGLONG; + SectionAlignment: DWORD; + FileAlignment: DWORD; + MajorOperatingSystemVersion: Word; + MinorOperatingSystemVersion: Word; + MajorImageVersion: Word; + MinorImageVersion: Word; + MajorSubsystemVersion: Word; + MinorSubsystemVersion: Word; + Win32VersionValue: DWORD; + SizeOfImage: DWORD; + SizeOfHeaders: DWORD; + CheckSum: DWORD; + Subsystem: Word; + DllCharacteristics: Word; + SizeOfStackReserve: ULONGLONG; + SizeOfStackCommit: ULONGLONG; + SizeOfHeapReserve: ULONGLONG; + SizeOfHeapCommit: ULONGLONG; + LoaderFlags: DWORD; + NumberOfRvaAndSizes: DWORD; + DataDirectory: packed array[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1] of TImageDataDirectory; + end; + TImageOptionalHeader64 = _IMAGE_OPTIONAL_HEADER64; +{$ENDIF} +{$ENDIF} diff --git a/Binary/JPL.UPX.pas b/Binary/JPL.UPX.pas index 845799d..85f3634 100644 --- a/Binary/JPL.UPX.pas +++ b/Binary/JPL.UPX.pas @@ -1,14 +1,23 @@ unit JPL.UPX; -// Jacek Pazera -// Free UPX - http://www.pazera-software.com/products/free-upx/ -// UPX - https://upx.github.io/ +{ + Jacek Pazera + https://github.com/jackdp + FUPX - http://www.pazera-software.com/products/free-upx/ + + UPX - https://upx.github.io/ +} + + +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} interface + uses - Windows, SysUtils //, System.Classes - //, Dialogs + {$IFDEF MSWINDOWS}Windows,{$ENDIF} + SysUtils ; diff --git a/Containers/JPL.StrList.pas b/Containers/JPL.StrList.pas index c92681c..775ff38 100644 --- a/Containers/JPL.StrList.pas +++ b/Containers/JPL.StrList.pas @@ -192,10 +192,14 @@ { TODO: dodać pełną obsługę Name / Value. Na razie dodałem tylko proc. GetNameValue. } +{$I .\..\jp.inc} + {$IFDEF FPC} {$mode objfpc}{$H+} + {$WARN 6058 off : Call to subroutine "$1" marked as inline is not inlined} {$ENDIF} + interface uses @@ -224,6 +228,10 @@ interface PtrUInt = DWord; {$endif} + {$IFDEF DCC}{$IFNDEF DELPHIXE2_OR_ABOVE} + PtrUInt = DWord; + {$ENDIF}{$ENDIF} + {$ENDIF DCC} TSLCompareStrProc = function (const s1, s2: string): integer; diff --git a/Containers/JPL.FileIcons.pas b/Containers/JPL.Win.FileIcons.pas similarity index 92% rename from Containers/JPL.FileIcons.pas rename to Containers/JPL.Win.FileIcons.pas index 84412cf..9f0693a 100644 --- a/Containers/JPL.FileIcons.pas +++ b/Containers/JPL.Win.FileIcons.pas @@ -1,4 +1,4 @@ -unit JPL.FileIcons; +unit JPL.Win.FileIcons; interface @@ -10,9 +10,19 @@ interface w komponentach obsługujących TImageList. } +{$IFDEF MSWINDOWS} + +{$I .\..\jp.inc} + +{$IFDEF FPC} + {$IFNDEF HAS_SPARTA_GENERICS}For FPC 3.0.4 or newer only!{$ENDIF} + {$MODE DELPHI} +{$ENDIF} + + uses // Win API - Windows, Messages, ShellAPI, + ShellAPI, // System SysUtils, Classes, Generics.Collections, @@ -21,7 +31,7 @@ interface Graphics, Controls, ComCtrls, StdCtrls, ExtCtrls, // JPLib - JPL.Strings, JPL.Conversion; + JPL.Strings; type @@ -47,10 +57,16 @@ TFileIcons = class(TObject) end; +{$ENDIF} // MSWINDOWS + + + implementation +{$IFDEF MSWINDOWS} + constructor TFileIcons.Create(ImageList: TImageList; xMaxIconCount: integer = -1); begin inherited Create; @@ -150,5 +166,8 @@ procedure TFileIcons.SetMaxIconCount(const Value: integer); FMaxIconCount := Value; end; + +{$ENDIF} // MSWINDOWS + end. diff --git a/Graphics/JPL.ColorArrays.pas b/Graphics/JPL.ColorArrays.pas index 5712282..627b9b8 100644 --- a/Graphics/JPL.ColorArrays.pas +++ b/Graphics/JPL.ColorArrays.pas @@ -1,20 +1,15 @@ unit JPL.ColorArrays; -{$IFDEF FPC} - {$mode objfpc}{$H+} -{$ENDIF} - { https://en.wikipedia.org/wiki/Web_colors } +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE OBJFPC}{$H+}{$ENDIF} + interface uses - - //JP.Colors, - //Classes, - //SysUtils, Graphics; type diff --git a/Graphics/JPL.Colors.ColorClass.pas b/Graphics/JPL.Colors.ColorClass.pas index 1179823..28b3ded 100644 --- a/Graphics/JPL.Colors.ColorClass.pas +++ b/Graphics/JPL.Colors.ColorClass.pas @@ -1,19 +1,14 @@ unit JPL.Colors.ColorClass; -{$IFDEF FPC} - {$mode delphi} -{$ENDIF} - +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} interface uses - //{$IFDEF MSWINDOWS} Windows,{$ENDIF} //{$IFDEF FPC} LCLType, {$ENDIF} // < TRGBTriple, TRBGQuad, MulDiv ... Graphics, SysUtils, - //Classes, Math, JPL.Colors; - //, JPL.Math, JPL.Strings, JPL.Conversion; type diff --git a/Graphics/JPL.Colors.List.pas b/Graphics/JPL.Colors.List.pas index 5f20f03..4f08351 100644 --- a/Graphics/JPL.Colors.List.pas +++ b/Graphics/JPL.Colors.List.pas @@ -1,17 +1,14 @@ unit JPL.Colors.List; -{$IFDEF FPC} - //{$mode objfpc}{$H+} - //{$MODESWITCH ADVANCEDRECORDS} - {$mode delphi} -{$ENDIF} +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} interface uses - {$IFDEF MSWINDOWS} Windows,{$ENDIF} + {$IFDEF DELPHI2009_OR_BELOW}Windows,{$ENDIF} {$IFDEF FPC} LCLType, {$ENDIF} - Classes, SysUtils, Graphics, Math, JPL.Math, JPL.Strings, JPL.Conversion, JPL.Colors; + Classes, SysUtils, Graphics, JPL.Strings, JPL.Conversion, JPL.Colors; type @@ -161,7 +158,7 @@ function ColorListSortModeToStr(const SortingMode: TColorListSortMode): string; clsmHslSat: Result := 'HSL - Sat'; clsmHslLum: Result := 'HSL - Lum'; else - Result := ''; + Result := ''{%H-}; end; end; diff --git a/Graphics/JPL.Colors.pas b/Graphics/JPL.Colors.pas index a3614d7..e99fbd2 100644 --- a/Graphics/JPL.Colors.pas +++ b/Graphics/JPL.Colors.pas @@ -1,10 +1,5 @@ unit JPL.Colors; -{$IFDEF FPC} - {$mode objfpc}{$H+} - {$MODESWITCH ADVANCEDRECORDS} -{$ENDIF} - { I created this unit to have all the routines that convert colors in one place. The most of the code is mine, but some routines are copied from other free units. @@ -25,13 +20,22 @@ A short explanation of the HSB, HSV, HSL, CMYK color models. } + +{$I .\..\jp.inc} + +{$IFDEF FPC} + {$mode objfpc}{$H+} + {$MODESWITCH ADVANCEDRECORDS} +{$ENDIF} + + interface + uses {$IFDEF MSWINDOWS} Windows,{$ENDIF} {$IFDEF FPC} LCLType, {$ENDIF} // < TRGBTriple, TRBGQuad, MulDiv ... - //Dialogs, Done : POTEM WYKOMENTOWAC - Classes, SysUtils, Graphics, Math, JPL.Math, JPL.Strings, JPL.Conversion; + Classes, SysUtils, Graphics, Math, Types, JPL.Math, JPL.Strings, JPL.Conversion; const HSL_MAX_CSS_HUE = 360; @@ -814,7 +818,11 @@ function ColorToCmykStr(const Color: TColor; Padding: Byte = 3; PaddingChar: Cha function TryCmykStrToColor(s: string; var Color: TColor; Separator: string = ','): Boolean; var ck: TCMYKColor; + {$IFDEF DELPHI2009_OR_BELOW} + Arr: TStringDynArray; + {$ELSE} Arr: {$IFDEF FPC}specialize{$ENDIF} TArray; + {$ENDIF} sC, sM, sY, sK: string; begin Result := False; @@ -1608,17 +1616,21 @@ procedure SetHslWinMaxValues; function TryHslCssStrToColor(HslCssStr: string; out cl: TColor): Boolean; begin - Result := TryHslRangeToColor(HslCssStr, cl, ',', HSL_MAX_CSS_HUE, HSL_MAX_CSS_SAT, HSL_MAX_CSS_LUM); + Result := TryHslRangeToColor(HslCssStr, cl{%H-}, ',', HSL_MAX_CSS_HUE, HSL_MAX_CSS_SAT, HSL_MAX_CSS_LUM); end; function TryHslWinStrToColor(HslWinStr: string; out cl: TColor): Boolean; begin - Result := TryHslRangeToColor(HslWinStr, cl, ',', HSL_MAX_WIN_HUE, HSL_MAX_WIN_SAT, HSL_MAX_WIN_LUM); + Result := TryHslRangeToColor(HslWinStr, cl{%H-}, ',', HSL_MAX_WIN_HUE, HSL_MAX_WIN_SAT, HSL_MAX_WIN_LUM); end; function TryHslRangeToColor(s: string; var Color: TColor; Separator: string = ','; AMaxHue: integer = 360; AMaxSat: integer = 100; AMaxLum: integer = 100): Boolean; var + {$IFDEF DELPHI2009_OR_BELOW} + Arr: TStringDynArray; + {$ELSE} Arr: {$IFDEF FPC}specialize{$ENDIF} TArray; + {$ENDIF} sH, sS, sL: string; xH, xS, xL: integer; begin @@ -1635,7 +1647,7 @@ function TryHslRangeToColor(s: string; var Color: TColor; Separator: string = ', s := RemoveAll(s, '('); s := RemoveAll(s, ')'); s := RemoveAll(s, '%'); - s := RemoveAll(s, DEG); + s := RemoveAll(s, DEG{%H-}); SplitStrToArray(s, Arr{%H-}, Separator); sH := ''; sS := ''; @@ -1709,7 +1721,7 @@ function ColorToHslRangeStr(const Color: TColor; AMaxHue: integer = 360; AMaxSat ColortoHSLRange(Color, H1, S1, L1); sH := Pad(IntToStr(H1), Padding, PaddingChar); - if bShowDeg then sH := sH + DEG; + if bShowDeg then sH := sH + string({%H-}DEG); sS := Pad(IntToStr(S1), Padding, PaddingChar); if bShowPercent then sS := sS + '%'; diff --git a/Hash/JPL.Hash.CRC32.pas b/Hash/JPL.Hash.CRC32.pas deleted file mode 100644 index 5bfe880..0000000 --- a/Hash/JPL.Hash.CRC32.pas +++ /dev/null @@ -1,218 +0,0 @@ -unit JPL.Hash.CRC32; - -{ - Jacek Pazera - http://www.pazera-software.com -} - -{$IFDEF FPC} {$mode objfpc}{$H+} {$ENDIF} - -interface - -uses - SysUtils, Classes, JPL.Math, crc; - - -{$region ' CRC32Table '} -const CRC32Table: array[0..255] of DWORD = - ($00000000, $77073096, $EE0E612C, $990951BA, - $076DC419, $706AF48F, $E963A535, $9E6495A3, - $0EDB8832, $79DCB8A4, $E0D5E91E, $97D2D988, - $09B64C2B, $7EB17CBD, $E7B82D07, $90BF1D91, - $1DB71064, $6AB020F2, $F3B97148, $84BE41DE, - $1ADAD47D, $6DDDE4EB, $F4D4B551, $83D385C7, - $136C9856, $646BA8C0, $FD62F97A, $8A65C9EC, - $14015C4F, $63066CD9, $FA0F3D63, $8D080DF5, - $3B6E20C8, $4C69105E, $D56041E4, $A2677172, - $3C03E4D1, $4B04D447, $D20D85FD, $A50AB56B, - $35B5A8FA, $42B2986C, $DBBBC9D6, $ACBCF940, - $32D86CE3, $45DF5C75, $DCD60DCF, $ABD13D59, - $26D930AC, $51DE003A, $C8D75180, $BFD06116, - $21B4F4B5, $56B3C423, $CFBA9599, $B8BDA50F, - $2802B89E, $5F058808, $C60CD9B2, $B10BE924, - $2F6F7C87, $58684C11, $C1611DAB, $B6662D3D, - $76DC4190, $01DB7106, $98D220BC, $EFD5102A, - $71B18589, $06B6B51F, $9FBFE4A5, $E8B8D433, - $7807C9A2, $0F00F934, $9609A88E, $E10E9818, - $7F6A0DBB, $086D3D2D, $91646C97, $E6635C01, - $6B6B51F4, $1C6C6162, $856530D8, $F262004E, - $6C0695ED, $1B01A57B, $8208F4C1, $F50FC457, - $65B0D9C6, $12B7E950, $8BBEB8EA, $FCB9887C, - $62DD1DDF, $15DA2D49, $8CD37CF3, $FBD44C65, - $4DB26158, $3AB551CE, $A3BC0074, $D4BB30E2, - $4ADFA541, $3DD895D7, $A4D1C46D, $D3D6F4FB, - $4369E96A, $346ED9FC, $AD678846, $DA60B8D0, - $44042D73, $33031DE5, $AA0A4C5F, $DD0D7CC9, - $5005713C, $270241AA, $BE0B1010, $C90C2086, - $5768B525, $206F85B3, $B966D409, $CE61E49F, - $5EDEF90E, $29D9C998, $B0D09822, $C7D7A8B4, - $59B33D17, $2EB40D81, $B7BD5C3B, $C0BA6CAD, - $EDB88320, $9ABFB3B6, $03B6E20C, $74B1D29A, - $EAD54739, $9DD277AF, $04DB2615, $73DC1683, - $E3630B12, $94643B84, $0D6D6A3E, $7A6A5AA8, - $E40ECF0B, $9309FF9D, $0A00AE27, $7D079EB1, - $F00F9344, $8708A3D2, $1E01F268, $6906C2FE, - $F762575D, $806567CB, $196C3671, $6E6B06E7, - $FED41B76, $89D32BE0, $10DA7A5A, $67DD4ACC, - $F9B9DF6F, $8EBEEFF9, $17B7BE43, $60B08ED5, - $D6D6A3E8, $A1D1937E, $38D8C2C4, $4FDFF252, - $D1BB67F1, $A6BC5767, $3FB506DD, $48B2364B, - $D80D2BDA, $AF0A1B4C, $36034AF6, $41047A60, - $DF60EFC3, $A867DF55, $316E8EEF, $4669BE79, - $CB61B38C, $BC66831A, $256FD2A0, $5268E236, - $CC0C7795, $BB0B4703, $220216B9, $5505262F, - $C5BA3BBE, $B2BD0B28, $2BB45A92, $5CB36A04, - $C2D7FFA7, $B5D0CF31, $2CD99E8B, $5BDEAE1D, - $9B64C2B0, $EC63F226, $756AA39C, $026D930A, - $9C0906A9, $EB0E363F, $72076785, $05005713, - $95BF4A82, $E2B87A14, $7BB12BAE, $0CB61B38, - $92D28E9B, $E5D5BE0D, $7CDCEFB7, $0BDBDF21, - $86D3D2D4, $F1D4E242, $68DDB3F8, $1FDA836E, - $81BE16CD, $F6B9265B, $6FB077E1, $18B74777, - $88085AE6, $FF0F6A70, $66063BCA, $11010B5C, - $8F659EFF, $F862AE69, $616BFFD3, $166CCF45, - $A00AE278, $D70DD2EE, $4E048354, $3903B3C2, - $A7672661, $D06016F7, $4969474D, $3E6E77DB, - $AED16A4A, $D9D65ADC, $40DF0B66, $37D83BF0, - $A9BCAE53, $DEBB9EC5, $47B2CF7F, $30B5FFE9, - $BDBDF21C, $CABAC28A, $53B39330, $24B4A3A6, - $BAD03605, $CDD70693, $54DE5729, $23D967BF, - $B3667A2E, $C4614AB8, $5D681B02, $2A6F2B94, - $B40BBE37, $C30C8EA1, $5A05DF1B, $2D02EF8D); -{$endregion} - - -type - THashEnumProc = function(PercentComplete: integer; BufNo: integer): Boolean; - -// Slow -function CalcStreamCRC32_Custom(const AStream: TStream; StartPos: Int64 = 0; HashEnumProc: THashEnumProc = nil): DWORD; -function CalcFileCRC32_Custom(const FileName: string; HashEnumProc: THashEnumProc = nil): DWORD; - -// Fast -function CalcStreamCRC32(const AStream: TStream; StartPos: Int64 = 0; HashEnumProc: THashEnumProc = nil): DWORD; -function CalcFileCRC32(const FileName: string; HashEnumProc: THashEnumProc = nil; IgnoreExceptions: Boolean = False): DWORD; -//function CalcStringCRC32(Text: string {; Encoding: TEncoding}): DWORD; - - -implementation - -{$region ' -------------- CRC32_Custom - SLOW --------------------- '} - -function CalcStreamCRC32_Custom(const AStream: TStream; StartPos: Int64 = 0; HashEnumProc: THashEnumProc = nil): DWORD; -var - //Buffer: array[0..51199] of Byte; // 51200 bytes = 50 KB - Buffer: array[0..102400-1] of Byte; - i, xRead, xPercent, BufNo: integer; - xTotalRead, xStreamSize: Int64; -begin - Result := $FFFFFFFF; - AStream.Position := StartPos; - - xTotalRead := StartPos; - xStreamSize := AStream.Size - StartPos; - BufNo := 0; - - while AStream.Position < AStream.Size do - begin - - Inc(BufNo); - xRead := AStream.Read(Buffer{%H-}, SizeOf(Buffer)); - xTotalRead := xTotalRead + xRead; - xPercent := Round(PercentValue(xTotalRead, xStreamSize)); - - for i := 0 to xRead - 1 do - Result := (Result shr 8) xor CRC32Table[Buffer[i] xor (Result and $000000FF)]; // <-- OK - - if Assigned(HashEnumProc) then - if not HashEnumProc(xPercent, BufNo) then Exit; - - end; - - Result := not Result; -end; - -function CalcFileCRC32_Custom(const FileName: string; HashEnumProc: THashEnumProc = nil): DWORD; -var - fs: TFileStream; -begin - fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone); - try - Result := CalcStreamCRC32_Custom(fs, 0, HashEnumProc); - finally - fs.Free; - end; -end; - -{$endregion CRC32_Custom - SLOW} - -function CalcStreamCRC32(const AStream: TStream; StartPos: Int64 = 0; HashEnumProc: THashEnumProc = nil): DWORD; -var - //Buffer: array[0..51199] of Byte; // 51200 bytes = 50 KB - Buffer: array[0..102400-1] of Byte; // 102 400 bytes = 100 KB - xRead, xPercent, BufNo: integer; - xTotalRead, xStreamSize: Int64; -begin - AStream.Position := StartPos; - - xTotalRead := StartPos; - xStreamSize := AStream.Size - StartPos; - BufNo := 0; - - Result := 0; - while AStream.Position < AStream.Size do - begin - - Inc(BufNo); - xRead := AStream.Read(Buffer, SizeOf(Buffer)); - xTotalRead := xTotalRead + xRead; - xPercent := Round(PercentValue(xTotalRead, xStreamSize)); - Result := crc32(Result, @Buffer, xRead); - - if Assigned(HashEnumProc) then - if not HashEnumProc(xPercent, BufNo) then Exit; - - end; - -end; - - -//function CalcStringCRC32(Text: string {; Encoding: TEncoding}): DWORD; -//var -// ss: TStringStream; -//begin -// ss := TStringStream.Create(Text); //, Encoding); -// try -// Result := CalcStreamCRC32(ss); -// finally -// ss.Free; -// end; -//end; - - -function CalcFileCRC32(const FileName: string; HashEnumProc: THashEnumProc = nil; IgnoreExceptions: Boolean = False): DWORD; -var - fs: TFileStream; -begin - try - - fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone); - try - Result := CalcStreamCRC32(fs, 0, HashEnumProc); - finally - fs.Free; - end; - - except - on E: Exception do - begin - if IgnoreExceptions then Result := 0 - else raise Exception.Create(E.Message); - end; - end; -end; - - - - -end. diff --git a/Hash/JPL.Hash.Common.pas b/Hash/JPL.Hash.Common.pas index 0a55116..463eed9 100644 --- a/Hash/JPL.Hash.Common.pas +++ b/Hash/JPL.Hash.Common.pas @@ -1,7 +1,11 @@ unit JPL.Hash.Common; +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} + interface + uses {$IFDEF MSWINDOWS}Windows,{$ENDIF} SysUtils, Classes, JPL.Conversion diff --git a/Hash/JPL.Hash.HL_MD2.pas b/Hash/JPL.Hash.HL_MD2.pas index e2106da..b7fe05f 100644 --- a/Hash/JPL.Hash.HL_MD2.pas +++ b/Hash/JPL.Hash.HL_MD2.pas @@ -3,12 +3,12 @@ interface uses - Winapi.Windows, System.Classes, System.SysUtils, - JPL.Math, JPL.Win.Dialogs, JPL.TimeLogger, + Classes, SysUtils, + JPL.Math, JPL.TimeLogger, JPL.Hash.Common, // HashLib4Pascal - https://github.com/Xor-el/HashLib4Pascal - HlpHash, HlpHashResult, HlpIHashResult, HlpMD2; + HlpHash, HlpIHashResult, HlpMD2; const diff --git a/Hash/JPL.Hash.HL_RipeMD.pas b/Hash/JPL.Hash.HL_RipeMD.pas index 2bb95d2..9538cec 100644 --- a/Hash/JPL.Hash.HL_RipeMD.pas +++ b/Hash/JPL.Hash.HL_RipeMD.pas @@ -8,7 +8,7 @@ interface JPL.Hash.Common, // HashLib4Pascal - https://github.com/Xor-el/HashLib4Pascal - HlpHash, HlpHashResult, HlpIHashResult, HlpRIPEMD; + HlpHash, HlpIHashResult, HlpRIPEMD; const diff --git a/Hash/JPL.Hash.HL_RipeMD128.pas b/Hash/JPL.Hash.HL_RipeMD128.pas index 7b122e0..9643b04 100644 --- a/Hash/JPL.Hash.HL_RipeMD128.pas +++ b/Hash/JPL.Hash.HL_RipeMD128.pas @@ -8,7 +8,7 @@ interface JPL.Hash.Common, // HashLib4Pascal - https://github.com/Xor-el/HashLib4Pascal - HlpHash, HlpHashResult, HlpIHashResult, HlpRIPEMD128; + HlpHash, HlpIHashResult, HlpRIPEMD128; const diff --git a/Hash/JPL.Hash.HL_RipeMD256.pas b/Hash/JPL.Hash.HL_RipeMD256.pas index c5e3742..cfdb468 100644 --- a/Hash/JPL.Hash.HL_RipeMD256.pas +++ b/Hash/JPL.Hash.HL_RipeMD256.pas @@ -8,7 +8,7 @@ interface JPL.Hash.Common, // HashLib4Pascal - https://github.com/Xor-el/HashLib4Pascal - HlpHash, HlpHashResult, HlpIHashResult, HlpRIPEMD256; + HlpHash, HlpIHashResult, HlpRIPEMD256; const diff --git a/Hash/JPL.Hash.HL_RipeMD320.pas b/Hash/JPL.Hash.HL_RipeMD320.pas index aaa6a18..0dab75d 100644 --- a/Hash/JPL.Hash.HL_RipeMD320.pas +++ b/Hash/JPL.Hash.HL_RipeMD320.pas @@ -8,7 +8,7 @@ interface JPL.Hash.Common, // HashLib4Pascal - https://github.com/Xor-el/HashLib4Pascal - HlpHash, HlpHashResult, HlpIHashResult, HlpRIPEMD320; + HlpHash, HlpIHashResult, HlpRIPEMD320; const diff --git a/Hash/JPL.Hash.HL_Sha0.pas b/Hash/JPL.Hash.HL_Sha0.pas index 9cda296..5f0b8a3 100644 --- a/Hash/JPL.Hash.HL_Sha0.pas +++ b/Hash/JPL.Hash.HL_Sha0.pas @@ -8,7 +8,7 @@ interface JPL.Hash.Common, // HashLib4Pascal - https://github.com/Xor-el/HashLib4Pascal - HlpHash, HlpHashResult, HlpIHashResult, HlpSHA0; + HlpHash, HlpIHashResult, HlpSHA0; const diff --git a/Hash/JPL.Hash.HL_Snefru128.pas b/Hash/JPL.Hash.HL_Snefru128.pas index db6d798..549d4ed 100644 --- a/Hash/JPL.Hash.HL_Snefru128.pas +++ b/Hash/JPL.Hash.HL_Snefru128.pas @@ -8,7 +8,7 @@ interface JPL.Hash.Common, // HashLib4Pascal - https://github.com/Xor-el/HashLib4Pascal - HlpHash, HlpHashResult, HlpIHashResult, HlpHashSize, HlpSnefru; + HlpHash, HlpIHashResult, HlpHashSize, HlpSnefru; const diff --git a/Hash/JPL.Hash.HL_Snefru256.pas b/Hash/JPL.Hash.HL_Snefru256.pas index 7db3ebf..0504df6 100644 --- a/Hash/JPL.Hash.HL_Snefru256.pas +++ b/Hash/JPL.Hash.HL_Snefru256.pas @@ -8,7 +8,7 @@ interface JPL.Hash.Common, // HashLib4Pascal - https://github.com/Xor-el/HashLib4Pascal - HlpHash, HlpHashResult, HlpIHashResult, HlpHashSize, HlpSnefru; + HlpHash, HlpIHashResult, HlpHashSize, HlpSnefru; const diff --git a/JppFPC.inc b/JppFPC.inc deleted file mode 100644 index 8d1a654..0000000 --- a/JppFPC.inc +++ /dev/null @@ -1,41 +0,0 @@ -{$IFDEF FPC} - - -{$UNDEF HAS_TSTRINGS_WRITEBOM} -{$UNDEF HAS_SYSTEM_UITYPES} -{$UNDEF HAS_STREAM_WRITEDATA} -{$UNDEF HAS_READ_WITH_OFFSET} -{$UNDEF HAS_SAVE_WITH_ENCODING} -{$UNDEF HAS_INIFILE_WITH_ENCODING} -{$UNDEF HAS_PANEL_WITH_PARENTBACKGROUND} -{$UNDEF HAS_WINCONTROL_WITH_PARENTDOUBLEBUFFERED} -{$UNDEF HAS_RTTI} -{$UNDEF HAS_UINTTOSTR} - - -// FPC 3.0.4 and UP -{$IF FPC_FULLVERSION >= 30004} - {$DEFINE HAS_PANEL_WITH_PARENTBACKGROUND} - {$DEFINE HAS_WINCONTROL_WITH_PARENTDOUBLEBUFFERED} -{$ENDIF} - -// FPC 3.2 and UP -{$IF FPC_FULLVERSION >= 30200} - {$DEFINE HAS_SYSTEM_UITYPES} - {$DEFINE HAS_TSTRINGS_WRITEBOM} - {$DEFINE HAS_SAVE_WITH_ENCODING} - {$DEFINE HAS_INIFILE_WITH_ENCODING} - {$DEFINE HAS_RTTI} - {$DEFINE HAS_UINTTOSTR} -{$ENDIF} - -// FPC 3.3.1 and UP -{$IF FPC_FULLVERSION >= 30301} - {$DEFINE HAS_STREAM_WRITEDATA} - {$DEFINE HAS_READ_WITH_OFFSET} -{$ENDIF} - - - - -{$ENDIF} \ No newline at end of file diff --git a/Logging/JPL.SimpleLogger.pas b/Logging/JPL.SimpleLogger.pas index 85aa4e0..68529b4 100644 --- a/Logging/JPL.SimpleLogger.pas +++ b/Logging/JPL.SimpleLogger.pas @@ -8,15 +8,20 @@ } -{ TODO : LogEvent } - -interface +{$I .\..\jp.inc} {$IFDEF FPC} {$mode objfpc}{$H+} {$MODESWITCH ADVANCEDRECORDS} {$ENDIF} + +{ TODO : LogEvent } + + +interface + + uses SysUtils, JPL.Conversion; diff --git a/Logging/JPL.TimeLogger.pas b/Logging/JPL.TimeLogger.pas index 90a1b9f..be71199 100644 --- a/Logging/JPL.TimeLogger.pas +++ b/Logging/JPL.TimeLogger.pas @@ -8,11 +8,12 @@ // Acquiring high-resolution time stamps: // https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx + +{$I .\..\jp.inc} +{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} + interface -{$IFDEF FPC} - {$MODESWITCH ADVANCEDRECORDS} -{$ENDIF} uses {$IFDEF MSWINDOWS} Windows, {$ENDIF} diff --git a/jp.inc b/jp.inc new file mode 100644 index 0000000..f083bdb --- /dev/null +++ b/jp.inc @@ -0,0 +1,111 @@ + +{$IFNDEF FPC} + {$IF CompilerVersion < 22} + {$DEFINE DCC} + {$IFEND} +{$ENDIF} + +// --------------- Free Pascal ------------------- +{$IFDEF FPC} + + {$UNDEF HAS_TSTRINGS_WRITEBOM} + {$UNDEF HAS_SYSTEM_UITYPES} + {$UNDEF HAS_STREAM_WRITEDATA} + {$UNDEF HAS_READ_WITH_OFFSET} + {$UNDEF HAS_SAVE_WITH_ENCODING} + {$UNDEF HAS_INIFILE_WITH_ENCODING} + {$UNDEF HAS_PANEL_WITH_PARENTBACKGROUND} + {$UNDEF HAS_WINCONTROL_WITH_PARENTDOUBLEBUFFERED} + {$UNDEF HAS_RTTI} + {$UNDEF HAS_UINTTOSTR} + {$UNDEF HAS_SPARTA_GENERICS} + + {$DEFINE HAS_FORMATSETTINGS} + + + // FPC 3.0.4 and UP + {$IF DEFINED(FPC_FULLVERSION) and (FPC_FULLVERSION >= 30004)} + {$DEFINE HAS_PANEL_WITH_PARENTBACKGROUND} + {$DEFINE HAS_WINCONTROL_WITH_PARENTDOUBLEBUFFERED} + {$DEFINE HAS_SPARTA_GENERICS} + {$IFEND} + + + // FPC 3.2 and UP + {$IF DEFINED(FPC_FULLVERSION) and (FPC_FULLVERSION >= 30200)} + {$DEFINE HAS_SYSTEM_UITYPES} + {$DEFINE HAS_TSTRINGS_WRITEBOM} + {$DEFINE HAS_SAVE_WITH_ENCODING} + {$DEFINE HAS_INIFILE_WITH_ENCODING} + {$DEFINE HAS_RTTI} + {$DEFINE HAS_UINTTOSTR} + {$IFEND} + + // FPC 3.3.1 and UP + {$IF DEFINED(FPC_FULLVERSION) and (FPC_FULLVERSION >= 30301)} + {$DEFINE HAS_STREAM_WRITEDATA} + {$DEFINE HAS_READ_WITH_OFFSET} + {$IFEND} + +{$ENDIF} // FPC + + + +// --------------------- Delphi ---------------------- +{$IFDEF DCC} + + {$IFDEF VER200} + {$DEFINE DELPHI2009} + {$ENDIF} + + {$IFDEF VER210} + {$DEFINE DELPHI2010} + {$ENDIF} + + {$IFDEF VER220} + {$DEFINE DELPHIXE} + {$ENDIF} + + {$IFDEF VER230} + {$DEFINE DELPHIXE2} + {$ENDIF} + + + + + + {$IF CompilerVersion <= 20} + {$DEFINE DELPHI2009_OR_BELOW} + {$IFEND} + + {$IF CompilerVersion >= 20} + {$DEFINE DELPHI2009_OR_ABOVE} + {$DEFINE DELPHI_UNICODE} + {$IFEND} + + + {$IF CompilerVersion <= 21} + {$DEFINE DELPHI2010_OR_BELOW} + {$IFEND} + + {$IF CompilerVersion >= 21} + {$DEFINE DELPHI2010_OR_ABOVE} + {$IFEND} + + + {$IF CompilerVersion >= 22} + {$DEFINE DELPHIXE_OR_ABOVE} + {$DEFINE HAS_FORMATSETTINGS} + {$IFEND} + + + {$IF CompilerVersion >= 23} + {$DEFINE DELPHIXE2_OR_ABOVE} + {$IFEND} + + + {$IF CompilerVersion >= 24} + {$DEFINE DELPHIXE3_OR_ABOVE} + {$IFEND} + +{$ENDIF} // DCC \ No newline at end of file diff --git a/packages/CodeTyphon/jplib.ctpkg b/packages/CodeTyphon/jplib.ctpkg index 65edca7..b1f1672 100644 --- a/packages/CodeTyphon/jplib.ctpkg +++ b/packages/CodeTyphon/jplib.ctpkg @@ -14,144 +14,161 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + - - + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + - - + + - - + + - - + + - - + + + + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - + + - - + + - + diff --git a/packages/CodeTyphon/jplib.pas b/packages/CodeTyphon/jplib.pas index 36a47e1..7b9c33c 100644 --- a/packages/CodeTyphon/jplib.pas +++ b/packages/CodeTyphon/jplib.pas @@ -9,9 +9,10 @@ interface uses JPL.CmdLineParser, JPL.Console.ColorParser, JPL.Console, JPL.ConsoleApp, JPL.Conversion, JPL.DateTime, JPL.Dialogs, JPL.Files, - JPL.FileSearch, JPL.FileSearcher, JPL.JsonHelpers, JPL.Language, JPL.Math, JPL.MemIniFile, JPL.RTTI, JPL.StrHash, JPL.Strings.Ext, - JPL.Strings, JPL.Units, JPL.Utils, JPL.Win.Dialogs, JPL.Win.FileSystem, JPL.Win.Shortcuts, JPL.Win.System, JPL.Win.VersionInfo, - JPL.StrList, JPL.ColorArrays, JPL.Colors.ColorClass, JPL.Colors.List, JPL.Colors, JPL.SimpleLogger, JPL.TimeLogger, TyphonPackageIntf; + JPL.FileSearch, JPL.FileSearcher, JPL.IniFile, JPL.JsonHelpers, JPL.LangMgr, JPL.Language, JPL.Math, JPL.MemIniFile, JPL.RTTI, + JPL.StrHash, JPL.Strings.Ext, JPL.Strings, JPL.Units, JPL.Utils, JPL.Win.Dialogs, JPL.Win.FileSystem, JPL.Win.Processes, + JPL.Win.Shortcuts, JPL.Win.System, JPL.Win.VersionInfo, JPL.StrList, JPL.Win.FileIcons, JPL.ColorArrays, JPL.Colors.ColorClass, + JPL.Colors.List, JPL.Colors, JPL.SimpleLogger, JPL.TimeLogger, TyphonPackageIntf; implementation diff --git a/packages/Delphi_10.0_Seattle/JPLib.dpk b/packages/Delphi_10.0_Seattle/JPLib.dpk index 1fdd65a..3a47ab8 100644 --- a/packages/Delphi_10.0_Seattle/JPLib.dpk +++ b/packages/Delphi_10.0_Seattle/JPLib.dpk @@ -39,10 +39,6 @@ requires contains // BASE - {$IFDEF FPC} - JPL.FileSearcher in '..\..\Base\JPL.FileSearcher.pas', - JPL.JsonHelpers in '..\..\Base\JPL.JsonHelpers.pas', - {$ENDIF} JPL.CmdLineParser in '..\..\Base\JPL.CmdLineParser.pas', JPL.Console.ColorParser in '..\..\Base\JPL.Console.ColorParser.pas', JPL.Console in '..\..\Base\JPL.Console.pas', @@ -52,11 +48,16 @@ contains JPL.Dialogs in '..\..\Base\JPL.Dialogs.pas', JPL.Files in '..\..\Base\JPL.Files.pas', JPL.FileSearch in '..\..\Base\JPL.FileSearch.pas', + JPL.IniFile in '..\..\Base\JPL.IniFile.pas', + JPL.LangMgr in '..\..\Base\JPL.LangMgr.pas', JPL.Language in '..\..\Base\JPL.Language.pas', JPL.Math in '..\..\Base\JPL.Math.pas', + JPL.MemIniFile in '..\..\Base\JPL.MemIniFile.pas', + JPL.RTTI in '..\..\Base\JPL.RTTI.pas', JPL.StrHash in '..\..\Base\JPL.StrHash.pas', JPL.Strings in '..\..\Base\JPL.Strings.pas', JPL.Strings.Ext in '..\..\Base\JPL.Strings.Ext.pas', + JPL.Units in '..\..\Base\JPL.Units.pas', JPL.Utils in '..\..\Base\JPL.Utils.pas', JPL.Win.Dialogs in '..\..\Base\JPL.Win.Dialogs.pas', JPL.Win.FileSystem in '..\..\Base\JPL.Win.FileSystem.pas', @@ -77,12 +78,15 @@ contains JPL.UPX in '..\..\Binary\JPL.UPX.pas', // Containers + JPL.Win.FileIcons in '..\..\Containers\JPL.Win.FileIcons.pas', JPL.StrList in '..\..\Containers\JPL.StrList.pas', // Graphics - JPL.Colors in '..\..\Graphics\JPL.Colors.pas', - JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', JPL.ColorArrays in '..\..\Graphics\JPL.ColorArrays.pas', + JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', + JPL.Colors.List in '..\..\Graphics\JPL.Colors.List.pas', + JPL.Colors in '..\..\Graphics\JPL.Colors.pas', + // Logging JPL.SimpleLogger in '..\..\Logging\JPL.SimpleLogger.pas', diff --git a/packages/Delphi_10.1_Berlin/JPLib.dpk b/packages/Delphi_10.1_Berlin/JPLib.dpk index f2da872..616bfc0 100644 --- a/packages/Delphi_10.1_Berlin/JPLib.dpk +++ b/packages/Delphi_10.1_Berlin/JPLib.dpk @@ -39,10 +39,6 @@ requires contains // BASE - {$IFDEF FPC} - JPL.FileSearcher in '..\..\Base\JPL.FileSearcher.pas', - JPL.JsonHelpers in '..\..\Base\JPL.JsonHelpers.pas', - {$ENDIF} JPL.CmdLineParser in '..\..\Base\JPL.CmdLineParser.pas', JPL.Console.ColorParser in '..\..\Base\JPL.Console.ColorParser.pas', JPL.Console in '..\..\Base\JPL.Console.pas', @@ -52,11 +48,16 @@ contains JPL.Dialogs in '..\..\Base\JPL.Dialogs.pas', JPL.Files in '..\..\Base\JPL.Files.pas', JPL.FileSearch in '..\..\Base\JPL.FileSearch.pas', + JPL.IniFile in '..\..\Base\JPL.IniFile.pas', + JPL.LangMgr in '..\..\Base\JPL.LangMgr.pas', JPL.Language in '..\..\Base\JPL.Language.pas', JPL.Math in '..\..\Base\JPL.Math.pas', + JPL.MemIniFile in '..\..\Base\JPL.MemIniFile.pas', + JPL.RTTI in '..\..\Base\JPL.RTTI.pas', JPL.StrHash in '..\..\Base\JPL.StrHash.pas', JPL.Strings in '..\..\Base\JPL.Strings.pas', JPL.Strings.Ext in '..\..\Base\JPL.Strings.Ext.pas', + JPL.Units in '..\..\Base\JPL.Units.pas', JPL.Utils in '..\..\Base\JPL.Utils.pas', JPL.Win.Dialogs in '..\..\Base\JPL.Win.Dialogs.pas', JPL.Win.FileSystem in '..\..\Base\JPL.Win.FileSystem.pas', @@ -77,12 +78,15 @@ contains JPL.UPX in '..\..\Binary\JPL.UPX.pas', // Containers + JPL.Win.FileIcons in '..\..\Containers\JPL.Win.FileIcons.pas', JPL.StrList in '..\..\Containers\JPL.StrList.pas', // Graphics - JPL.Colors in '..\..\Graphics\JPL.Colors.pas', - JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', JPL.ColorArrays in '..\..\Graphics\JPL.ColorArrays.pas', + JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', + JPL.Colors.List in '..\..\Graphics\JPL.Colors.List.pas', + JPL.Colors in '..\..\Graphics\JPL.Colors.pas', + // Logging JPL.SimpleLogger in '..\..\Logging\JPL.SimpleLogger.pas', diff --git a/packages/Delphi_10.2_Tokyo/JPLib.dpk b/packages/Delphi_10.2_Tokyo/JPLib.dpk index 05d935f..c4b03a3 100644 --- a/packages/Delphi_10.2_Tokyo/JPLib.dpk +++ b/packages/Delphi_10.2_Tokyo/JPLib.dpk @@ -39,10 +39,6 @@ requires contains // BASE - {$IFDEF FPC} - JPL.FileSearcher in '..\..\Base\JPL.FileSearcher.pas', - JPL.JsonHelpers in '..\..\Base\JPL.JsonHelpers.pas', - {$ENDIF} JPL.CmdLineParser in '..\..\Base\JPL.CmdLineParser.pas', JPL.Console.ColorParser in '..\..\Base\JPL.Console.ColorParser.pas', JPL.Console in '..\..\Base\JPL.Console.pas', @@ -52,11 +48,16 @@ contains JPL.Dialogs in '..\..\Base\JPL.Dialogs.pas', JPL.Files in '..\..\Base\JPL.Files.pas', JPL.FileSearch in '..\..\Base\JPL.FileSearch.pas', + JPL.IniFile in '..\..\Base\JPL.IniFile.pas', + JPL.LangMgr in '..\..\Base\JPL.LangMgr.pas', JPL.Language in '..\..\Base\JPL.Language.pas', JPL.Math in '..\..\Base\JPL.Math.pas', + JPL.MemIniFile in '..\..\Base\JPL.MemIniFile.pas', + JPL.RTTI in '..\..\Base\JPL.RTTI.pas', JPL.StrHash in '..\..\Base\JPL.StrHash.pas', JPL.Strings in '..\..\Base\JPL.Strings.pas', JPL.Strings.Ext in '..\..\Base\JPL.Strings.Ext.pas', + JPL.Units in '..\..\Base\JPL.Units.pas', JPL.Utils in '..\..\Base\JPL.Utils.pas', JPL.Win.Dialogs in '..\..\Base\JPL.Win.Dialogs.pas', JPL.Win.FileSystem in '..\..\Base\JPL.Win.FileSystem.pas', @@ -77,12 +78,15 @@ contains JPL.UPX in '..\..\Binary\JPL.UPX.pas', // Containers + JPL.Win.FileIcons in '..\..\Containers\JPL.Win.FileIcons.pas', JPL.StrList in '..\..\Containers\JPL.StrList.pas', // Graphics - JPL.Colors in '..\..\Graphics\JPL.Colors.pas', - JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', JPL.ColorArrays in '..\..\Graphics\JPL.ColorArrays.pas', + JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', + JPL.Colors.List in '..\..\Graphics\JPL.Colors.List.pas', + JPL.Colors in '..\..\Graphics\JPL.Colors.pas', + // Logging JPL.SimpleLogger in '..\..\Logging\JPL.SimpleLogger.pas', diff --git a/packages/Delphi_10.3_Rio/JPLib.dpk b/packages/Delphi_10.3_Rio/JPLib.dpk index b9ccc64..91ba201 100644 --- a/packages/Delphi_10.3_Rio/JPLib.dpk +++ b/packages/Delphi_10.3_Rio/JPLib.dpk @@ -39,10 +39,6 @@ requires contains // BASE - {$IFDEF FPC} - JPL.FileSearcher in '..\..\Base\JPL.FileSearcher.pas', - JPL.JsonHelpers in '..\..\Base\JPL.JsonHelpers.pas', - {$ENDIF} JPL.CmdLineParser in '..\..\Base\JPL.CmdLineParser.pas', JPL.Console.ColorParser in '..\..\Base\JPL.Console.ColorParser.pas', JPL.Console in '..\..\Base\JPL.Console.pas', @@ -52,11 +48,16 @@ contains JPL.Dialogs in '..\..\Base\JPL.Dialogs.pas', JPL.Files in '..\..\Base\JPL.Files.pas', JPL.FileSearch in '..\..\Base\JPL.FileSearch.pas', + JPL.IniFile in '..\..\Base\JPL.IniFile.pas', + JPL.LangMgr in '..\..\Base\JPL.LangMgr.pas', JPL.Language in '..\..\Base\JPL.Language.pas', JPL.Math in '..\..\Base\JPL.Math.pas', + JPL.MemIniFile in '..\..\Base\JPL.MemIniFile.pas', + JPL.RTTI in '..\..\Base\JPL.RTTI.pas', JPL.StrHash in '..\..\Base\JPL.StrHash.pas', JPL.Strings in '..\..\Base\JPL.Strings.pas', JPL.Strings.Ext in '..\..\Base\JPL.Strings.Ext.pas', + JPL.Units in '..\..\Base\JPL.Units.pas', JPL.Utils in '..\..\Base\JPL.Utils.pas', JPL.Win.Dialogs in '..\..\Base\JPL.Win.Dialogs.pas', JPL.Win.FileSystem in '..\..\Base\JPL.Win.FileSystem.pas', @@ -77,12 +78,15 @@ contains JPL.UPX in '..\..\Binary\JPL.UPX.pas', // Containers + JPL.Win.FileIcons in '..\..\Containers\JPL.Win.FileIcons.pas', JPL.StrList in '..\..\Containers\JPL.StrList.pas', // Graphics - JPL.Colors in '..\..\Graphics\JPL.Colors.pas', - JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', JPL.ColorArrays in '..\..\Graphics\JPL.ColorArrays.pas', + JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', + JPL.Colors.List in '..\..\Graphics\JPL.Colors.List.pas', + JPL.Colors in '..\..\Graphics\JPL.Colors.pas', + // Logging JPL.SimpleLogger in '..\..\Logging\JPL.SimpleLogger.pas', diff --git a/packages/Delphi_10.3_Rio/JPLib.dproj b/packages/Delphi_10.3_Rio/JPLib.dproj index 7fa2489..8e03154 100644 --- a/packages/Delphi_10.3_Rio/JPLib.dproj +++ b/packages/Delphi_10.3_Rio/JPLib.dproj @@ -107,11 +107,16 @@ + + + + + @@ -128,10 +133,12 @@ + - - + + + diff --git a/packages/Delphi_2009/JPLib.dpk b/packages/Delphi_2009/JPLib.dpk new file mode 100644 index 0000000..9e63708 --- /dev/null +++ b/packages/Delphi_2009/JPLib.dpk @@ -0,0 +1,96 @@ +package JPLib; + +{$R *.res} +{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO OFF} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES ON} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DEFINE RELEASE} +{$ENDIF IMPLICITBUILDING} +{$DESCRIPTION 'JPLib Runtime Package'} +{$LIBSUFFIX '2009'} +{$RUNONLY} +{$IMPLICITBUILD ON} + +{$WARN SYMBOL_PLATFORM OFF} + +requires + rtl, + vcl; + +contains + + // BASE + JPL.CmdLineParser in '..\..\Base\JPL.CmdLineParser.pas', + JPL.Console.ColorParser in '..\..\Base\JPL.Console.ColorParser.pas', + JPL.Console in '..\..\Base\JPL.Console.pas', + JPL.ConsoleApp in '..\..\Base\JPL.ConsoleApp.pas', + JPL.Conversion in '..\..\Base\JPL.Conversion.pas', + JPL.DateTime in '..\..\Base\JPL.DateTime.pas', + JPL.Dialogs in '..\..\Base\JPL.Dialogs.pas', + JPL.Files in '..\..\Base\JPL.Files.pas', + JPL.FileSearch in '..\..\Base\JPL.FileSearch.pas', + JPL.IniFile in '..\..\Base\JPL.IniFile.pas', + //JPL.LangMgr in '..\..\Base\JPL.LangMgr.pas', + JPL.Language in '..\..\Base\JPL.Language.pas', + JPL.Math in '..\..\Base\JPL.Math.pas', + JPL.MemIniFile in '..\..\Base\JPL.MemIniFile.pas', + //JPL.RTTI in '..\..\Base\JPL.RTTI.pas', + JPL.StrHash in '..\..\Base\JPL.StrHash.pas', + JPL.Strings in '..\..\Base\JPL.Strings.pas', + JPL.Strings.Ext in '..\..\Base\JPL.Strings.Ext.pas', + JPL.Units in '..\..\Base\JPL.Units.pas', + JPL.Utils in '..\..\Base\JPL.Utils.pas', + JPL.Win.Dialogs in '..\..\Base\JPL.Win.Dialogs.pas', + JPL.Win.FileSystem in '..\..\Base\JPL.Win.FileSystem.pas', + JPL.Win.Processes in '..\..\Base\JPL.Win.Processes.pas', + JPL.Win.Shortcuts in '..\..\Base\JPL.Win.Shortcuts.pas', + JPL.Win.System in '..\..\Base\JPL.Win.System.pas', + JPL.Win.VersionInfo in '..\..\Base\JPL.Win.VersionInfo.pas', + + // Binary + JPL.Binary.Elf in '..\..\Binary\JPL.Binary.Elf.pas', + JPL.Binary.Mach.Types in '..\..\Binary\JPL.Binary.Mach.Types.pas', + JPL.Binary.MachFat in '..\..\Binary\JPL.Binary.MachFat.pas', + JPL.Binary.MachO in '..\..\Binary\JPL.Binary.MachO.pas', + JPL.Binary.Misc in '..\..\Binary\JPL.Binary.Misc.pas', + JPL.Binary.Pe in '..\..\Binary\JPL.Binary.Pe.pas', + JPL.Binary.Procs in '..\..\Binary\JPL.Binary.Procs.pas', + JPL.Binary.Types in '..\..\Binary\JPL.Binary.Types.pas', + JPL.UPX in '..\..\Binary\JPL.UPX.pas', + + // Containers + JPL.Win.FileIcons in '..\..\Containers\JPL.Win.FileIcons.pas', + JPL.StrList in '..\..\Containers\JPL.StrList.pas', + + // Graphics + JPL.ColorArrays in '..\..\Graphics\JPL.ColorArrays.pas', + JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', + JPL.Colors.List in '..\..\Graphics\JPL.Colors.List.pas', + JPL.Colors in '..\..\Graphics\JPL.Colors.pas', + + + // Logging + JPL.SimpleLogger in '..\..\Logging\JPL.SimpleLogger.pas', + JPL.TimeLogger in '..\..\Logging\JPL.TimeLogger.pas'; + + +end. diff --git a/packages/Delphi_2009/JPLib.dproj b/packages/Delphi_2009/JPLib.dproj new file mode 100644 index 0000000..bdf4905 --- /dev/null +++ b/packages/Delphi_2009/JPLib.dproj @@ -0,0 +1,127 @@ + + + {D25FECF7-FB9D-4581-8AB8-9E27791A2D73} + JPLib.dpk + Release + DCC32 + 12.0 + + + true + + + true + Base + true + + + true + Base + true + + + true + C:\Users\Public\Documents\RAD Studio\6.0\Bpl\JPLib2009.bpl + true + JPLib Runtime Package + 2009 + true + 00400000 + x86 + + + RELEASE;$(DCC_Define) + 0 + false + false + + + DEBUG;$(DCC_Define) + + + + MainSource + + + + + + + + + + + + + + + + + + Base + + + Cfg_1 + Base + + + Cfg_2 + Base + + + + + Delphi.Personality.12 + Package + + + + JPLib.dpk + + + False + True + False + + + False + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 1033 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + Png Components + CodeGear WebSnap Components + CodeGear Internet Components + CodeGear SOAP Components + CodeGear C++Builder Office 2000 Servers Package + CodeGear C++Builder Office XP Servers Package + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + 12 + + diff --git a/packages/Delphi_2009/JPLib.res b/packages/Delphi_2009/JPLib.res new file mode 100644 index 0000000000000000000000000000000000000000..28e53612c3faeb93e0d6d9663c9a76f621e30286 GIT binary patch literal 4396 zcmbW5y^ice5QS^CNQeYBAfFAiE(S{o$&3%L$5+F6_ ztLm~nvz}%5S}Ik$ySmP)pYE~7%ek+?BU%R{e>Weh`PJ?^N50V=n zX`nry`}9L^kB^TwmExLl%I_aOSl{)AP3VWscsrl#tNuSeU?g^G=90%WPQG5nYbw1> z;;0z_S%yeee;W-|6Mu2+D*J8h)9~Q75&N@ZSKP!8hf!MoE+70OV3Xq|&l)EO z*Lrt5{K=2!-}jLJhlK|*dX1EWNw#os9;cV_lT&& z}Zn$UI;=sGs5}#P{jdmV$iyfbu>xYQj zZRVJR1Mk$|u}5Ja;3+*wAJ`Z1TiM1AzJ#?x&BM>9zy1ggb8zr8TjWP#1NiE(r@CPB z4p+w?WrOV?-Gz`Jk6->g-VqKO&%#EuKXYGCs@ME%$pKDa1~z^hzU=6GFzJIBljFwo zAl+%-5FCgR46lFU&W(fmlQqw2tp*1l>wGXz4xIzo$RX+(Pqy zZLHjDA2^)h1zY~2rY-*D(5>;4bCX}23R8kd7O%a_-@#h*3uI+17DfZp*=E25?k9Y9d@A>Y;PXd<^^`E$L zp5qRP_`Ns4As<7l(TI)mUx>AF&^Yl!@5k@?moLX0sBMTTe%A8N@f>L_`d(Vt89%)r z_0eANC19qo&Y1IemitzR=sWH&IEF9$5x>`8W8(EZ4e~EL*4^hESiY{kc{j3_=Yg@m zmwo)`Y2t3R!@uHBeD~e(13T8I()w3^Bmd&2xx_;Ajet(U=VcDO24lP5h@s&}{`Icf znsG)mH*waM`oOJ|o%VWtq`e=9b|%Fkf7{t}iSO^a>-@JPF%Ikf=l!R5a)Q8*`wL&h zMeNQ^v6I7$HSdM^hFbHmi?3dYdyV)Nk8toGF-HFoAKyTnbD!5c_tesx;)M+y zXWq|rN8Ay6o?Xrv*b9deV{);5Sm#{5#$oCC0~m1G>T_&zyxy~nR}NrZKFlF|XCXOJ zBW(Ph=@M_%@w?Y>)DQU`nL7L3eOwaIJM&25UDc=fEulAvk-Tvy@(xGuCCzWY<-Gna z2RqQq)WU%tqu1UdvUN=LB;OART>N|3b>sx!Z+Vi#YyI$o7kn2UPwh;?;eFW2FFBw+ zwm0O#?dFyX#Z7I}Px^hY&i!ce@hX?6Ctt@d_q`YIntl3vtG?#va=sqTswV%H{3H1! z`6xLyd6Y)p`#kDz2jpmWi+nWuQog?t#z9z}Fl#;D)^E-1dr7Td+b{N`{cOKVezM=B X^V$Bd!M_>$KjZ%1|JC4MkQ@6CnmZz1 literal 0 HcmV?d00001 diff --git a/packages/Delphi_2010/JPLib.dpk b/packages/Delphi_2010/JPLib.dpk new file mode 100644 index 0000000..bf03b25 --- /dev/null +++ b/packages/Delphi_2010/JPLib.dpk @@ -0,0 +1,96 @@ +package JPLib; + +{$R *.res} +{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO OFF} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES ON} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DEFINE RELEASE} +{$ENDIF IMPLICITBUILDING} +{$DESCRIPTION 'JPLib Runtime Package'} +{$LIBSUFFIX '2010'} +{$RUNONLY} +{$IMPLICITBUILD ON} + +{$WARN SYMBOL_PLATFORM OFF} + +requires + rtl, + vcl; + +contains + + // BASE + JPL.CmdLineParser in '..\..\Base\JPL.CmdLineParser.pas', + JPL.Console.ColorParser in '..\..\Base\JPL.Console.ColorParser.pas', + JPL.Console in '..\..\Base\JPL.Console.pas', + JPL.ConsoleApp in '..\..\Base\JPL.ConsoleApp.pas', + JPL.Conversion in '..\..\Base\JPL.Conversion.pas', + JPL.DateTime in '..\..\Base\JPL.DateTime.pas', + JPL.Dialogs in '..\..\Base\JPL.Dialogs.pas', + JPL.Files in '..\..\Base\JPL.Files.pas', + JPL.FileSearch in '..\..\Base\JPL.FileSearch.pas', + JPL.IniFile in '..\..\Base\JPL.IniFile.pas', + JPL.LangMgr in '..\..\Base\JPL.LangMgr.pas', + JPL.Language in '..\..\Base\JPL.Language.pas', + JPL.Math in '..\..\Base\JPL.Math.pas', + JPL.MemIniFile in '..\..\Base\JPL.MemIniFile.pas', + JPL.RTTI in '..\..\Base\JPL.RTTI.pas', + JPL.StrHash in '..\..\Base\JPL.StrHash.pas', + JPL.Strings in '..\..\Base\JPL.Strings.pas', + JPL.Strings.Ext in '..\..\Base\JPL.Strings.Ext.pas', + JPL.Units in '..\..\Base\JPL.Units.pas', + JPL.Utils in '..\..\Base\JPL.Utils.pas', + JPL.Win.Dialogs in '..\..\Base\JPL.Win.Dialogs.pas', + JPL.Win.FileSystem in '..\..\Base\JPL.Win.FileSystem.pas', + JPL.Win.Processes in '..\..\Base\JPL.Win.Processes.pas', + JPL.Win.Shortcuts in '..\..\Base\JPL.Win.Shortcuts.pas', + JPL.Win.System in '..\..\Base\JPL.Win.System.pas', + JPL.Win.VersionInfo in '..\..\Base\JPL.Win.VersionInfo.pas', + + // Binary + JPL.Binary.Elf in '..\..\Binary\JPL.Binary.Elf.pas', + JPL.Binary.Mach.Types in '..\..\Binary\JPL.Binary.Mach.Types.pas', + JPL.Binary.MachFat in '..\..\Binary\JPL.Binary.MachFat.pas', + JPL.Binary.MachO in '..\..\Binary\JPL.Binary.MachO.pas', + JPL.Binary.Misc in '..\..\Binary\JPL.Binary.Misc.pas', + JPL.Binary.Pe in '..\..\Binary\JPL.Binary.Pe.pas', + JPL.Binary.Procs in '..\..\Binary\JPL.Binary.Procs.pas', + JPL.Binary.Types in '..\..\Binary\JPL.Binary.Types.pas', + JPL.UPX in '..\..\Binary\JPL.UPX.pas', + + // Containers + JPL.Win.FileIcons in '..\..\Containers\JPL.Win.FileIcons.pas', + JPL.StrList in '..\..\Containers\JPL.StrList.pas', + + // Graphics + JPL.ColorArrays in '..\..\Graphics\JPL.ColorArrays.pas', + JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', + JPL.Colors.List in '..\..\Graphics\JPL.Colors.List.pas', + JPL.Colors in '..\..\Graphics\JPL.Colors.pas', + + + // Logging + JPL.SimpleLogger in '..\..\Logging\JPL.SimpleLogger.pas', + JPL.TimeLogger in '..\..\Logging\JPL.TimeLogger.pas'; + + +end. diff --git a/packages/Delphi_2010/JPLib.dproj b/packages/Delphi_2010/JPLib.dproj new file mode 100644 index 0000000..255214e --- /dev/null +++ b/packages/Delphi_2010/JPLib.dproj @@ -0,0 +1,146 @@ + + + {4BE82472-7B8A-4998-8E59-E28019FAAB1D} + JPLib.dpk + Release + DCC32 + 12.0 + + + true + + + true + Base + true + + + true + Base + true + + + WinTypes=Windows;WinProcs=Windows;$(DCC_UnitAlias) + true + C:\Users\Public\Documents\RAD Studio\7.0\Bpl\JPLib2010.bpl + true + false + 2010 + false + x86 + JPLib Runtime Package + false + false + 00400000 + false + true + + + RELEASE;$(DCC_Define) + 0 + false + false + + + DEBUG;$(DCC_Define) + + + + MainSource + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Base + + + Cfg_1 + Base + + + Cfg_2 + Base + + + + + Delphi.Personality.12 + Package + + + + JPLib.dpk + + + False + True + False + + + False + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 1033 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + + 12 + + diff --git a/packages/Delphi_2010/JPLib.res b/packages/Delphi_2010/JPLib.res new file mode 100644 index 0000000000000000000000000000000000000000..28e53612c3faeb93e0d6d9663c9a76f621e30286 GIT binary patch literal 4396 zcmbW5y^ice5QS^CNQeYBAfFAiE(S{o$&3%L$5+F6_ ztLm~nvz}%5S}Ik$ySmP)pYE~7%ek+?BU%R{e>Weh`PJ?^N50V=n zX`nry`}9L^kB^TwmExLl%I_aOSl{)AP3VWscsrl#tNuSeU?g^G=90%WPQG5nYbw1> z;;0z_S%yeee;W-|6Mu2+D*J8h)9~Q75&N@ZSKP!8hf!MoE+70OV3Xq|&l)EO z*Lrt5{K=2!-}jLJhlK|*dX1EWNw#os9;cV_lT&& z}Zn$UI;=sGs5}#P{jdmV$iyfbu>xYQj zZRVJR1Mk$|u}5Ja;3+*wAJ`Z1TiM1AzJ#?x&BM>9zy1ggb8zr8TjWP#1NiE(r@CPB z4p+w?WrOV?-Gz`Jk6->g-VqKO&%#EuKXYGCs@ME%$pKDa1~z^hzU=6GFzJIBljFwo zAl+%-5FCgR46lFU&W(fmlQqw2tp*1l>wGXz4xIzo$RX+(Pqy zZLHjDA2^)h1zY~2rY-*D(5>;4bCX}23R8kd7O%a_-@#h*3uI+17DfZp*=E25?k9Y9d@A>Y;PXd<^^`E$L zp5qRP_`Ns4As<7l(TI)mUx>AF&^Yl!@5k@?moLX0sBMTTe%A8N@f>L_`d(Vt89%)r z_0eANC19qo&Y1IemitzR=sWH&IEF9$5x>`8W8(EZ4e~EL*4^hESiY{kc{j3_=Yg@m zmwo)`Y2t3R!@uHBeD~e(13T8I()w3^Bmd&2xx_;Ajet(U=VcDO24lP5h@s&}{`Icf znsG)mH*waM`oOJ|o%VWtq`e=9b|%Fkf7{t}iSO^a>-@JPF%Ikf=l!R5a)Q8*`wL&h zMeNQ^v6I7$HSdM^hFbHmi?3dYdyV)Nk8toGF-HFoAKyTnbD!5c_tesx;)M+y zXWq|rN8Ay6o?Xrv*b9deV{);5Sm#{5#$oCC0~m1G>T_&zyxy~nR}NrZKFlF|XCXOJ zBW(Ph=@M_%@w?Y>)DQU`nL7L3eOwaIJM&25UDc=fEulAvk-Tvy@(xGuCCzWY<-Gna z2RqQq)WU%tqu1UdvUN=LB;OART>N|3b>sx!Z+Vi#YyI$o7kn2UPwh;?;eFW2FFBw+ zwm0O#?dFyX#Z7I}Px^hY&i!ce@hX?6Ctt@d_q`YIntl3vtG?#va=sqTswV%H{3H1! z`6xLyd6Y)p`#kDz2jpmWi+nWuQog?t#z9z}Fl#;D)^E-1dr7Td+b{N`{cOKVezM=B X^V$Bd!M_>$KjZ%1|JC4MkQ@6CnmZz1 literal 0 HcmV?d00001 diff --git a/packages/Delphi_XE/JPLib.dpk b/packages/Delphi_XE/JPLib.dpk new file mode 100644 index 0000000..7c5a3f9 --- /dev/null +++ b/packages/Delphi_XE/JPLib.dpk @@ -0,0 +1,96 @@ +package JPLib; + +{$R *.res} +{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO OFF} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES ON} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DEFINE RELEASE} +{$ENDIF IMPLICITBUILDING} +{$DESCRIPTION 'JPLib Runtime Package'} +{$LIBSUFFIX 'XE'} +{$RUNONLY} +{$IMPLICITBUILD ON} + +{$WARN SYMBOL_PLATFORM OFF} + +requires + rtl, + vcl; + +contains + + // BASE + JPL.CmdLineParser in '..\..\Base\JPL.CmdLineParser.pas', + JPL.Console.ColorParser in '..\..\Base\JPL.Console.ColorParser.pas', + JPL.Console in '..\..\Base\JPL.Console.pas', + JPL.ConsoleApp in '..\..\Base\JPL.ConsoleApp.pas', + JPL.Conversion in '..\..\Base\JPL.Conversion.pas', + JPL.DateTime in '..\..\Base\JPL.DateTime.pas', + JPL.Dialogs in '..\..\Base\JPL.Dialogs.pas', + JPL.Files in '..\..\Base\JPL.Files.pas', + JPL.FileSearch in '..\..\Base\JPL.FileSearch.pas', + JPL.IniFile in '..\..\Base\JPL.IniFile.pas', + JPL.LangMgr in '..\..\Base\JPL.LangMgr.pas', + JPL.Language in '..\..\Base\JPL.Language.pas', + JPL.Math in '..\..\Base\JPL.Math.pas', + JPL.MemIniFile in '..\..\Base\JPL.MemIniFile.pas', + JPL.RTTI in '..\..\Base\JPL.RTTI.pas', + JPL.StrHash in '..\..\Base\JPL.StrHash.pas', + JPL.Strings in '..\..\Base\JPL.Strings.pas', + JPL.Strings.Ext in '..\..\Base\JPL.Strings.Ext.pas', + JPL.Units in '..\..\Base\JPL.Units.pas', + JPL.Utils in '..\..\Base\JPL.Utils.pas', + JPL.Win.Dialogs in '..\..\Base\JPL.Win.Dialogs.pas', + JPL.Win.FileSystem in '..\..\Base\JPL.Win.FileSystem.pas', + JPL.Win.Processes in '..\..\Base\JPL.Win.Processes.pas', + JPL.Win.Shortcuts in '..\..\Base\JPL.Win.Shortcuts.pas', + JPL.Win.System in '..\..\Base\JPL.Win.System.pas', + JPL.Win.VersionInfo in '..\..\Base\JPL.Win.VersionInfo.pas', + + // Binary + JPL.Binary.Elf in '..\..\Binary\JPL.Binary.Elf.pas', + JPL.Binary.Mach.Types in '..\..\Binary\JPL.Binary.Mach.Types.pas', + JPL.Binary.MachFat in '..\..\Binary\JPL.Binary.MachFat.pas', + JPL.Binary.MachO in '..\..\Binary\JPL.Binary.MachO.pas', + JPL.Binary.Misc in '..\..\Binary\JPL.Binary.Misc.pas', + JPL.Binary.Pe in '..\..\Binary\JPL.Binary.Pe.pas', + JPL.Binary.Procs in '..\..\Binary\JPL.Binary.Procs.pas', + JPL.Binary.Types in '..\..\Binary\JPL.Binary.Types.pas', + JPL.UPX in '..\..\Binary\JPL.UPX.pas', + + // Containers + JPL.Win.FileIcons in '..\..\Containers\JPL.Win.FileIcons.pas', + JPL.StrList in '..\..\Containers\JPL.StrList.pas', + + // Graphics + JPL.ColorArrays in '..\..\Graphics\JPL.ColorArrays.pas', + JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', + JPL.Colors.List in '..\..\Graphics\JPL.Colors.List.pas', + JPL.Colors in '..\..\Graphics\JPL.Colors.pas', + + + // Logging + JPL.SimpleLogger in '..\..\Logging\JPL.SimpleLogger.pas', + JPL.TimeLogger in '..\..\Logging\JPL.TimeLogger.pas'; + + +end. diff --git a/packages/Delphi_XE/JPLib.dproj b/packages/Delphi_XE/JPLib.dproj new file mode 100644 index 0000000..1fe454e --- /dev/null +++ b/packages/Delphi_XE/JPLib.dproj @@ -0,0 +1,149 @@ + + + {AC1C2C13-DE4A-4375-9BF2-15019CD3EFEA} + JPLib.dpk + True + Release + Win32 + Package + VCL + DCC32 + 12.3 + + + true + + + true + Base + true + + + true + Base + true + + + true + WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;WinTypes=Windows;WinProcs=Windows;$(DCC_UnitAlias) + true + false + XE + false + false + JPLib Runtime Package + false + 00400000 + false + true + + + RELEASE;$(DCC_Define) + 0 + false + false + + + DEBUG;$(DCC_Define) + true + false + + + + MainSource + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + + + Delphi.Personality.12 + Package + + + + JPLib.dpk + + + False + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 1033 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + + True + + + 12 + + diff --git a/packages/Delphi_XE/JPLib.res b/packages/Delphi_XE/JPLib.res new file mode 100644 index 0000000000000000000000000000000000000000..fe53ea199ba2f58ad325ea1c4620d181bdc53bc4 GIT binary patch literal 91336 zcmV)uK$gD%0000W00030{{R60{{R300000000000000000000?9{~U$00030{{sO3 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ⅇBW= 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⁢dP zY!#-As+8EqMK1T=x`XnSN+qnxKm9M8l?PC*1<0yNsFUPuD4oD$GXAMkCrf@o$t5DtG`U8My2Kar72T)0&z{O{k468L90bsBQK)m6qiCF|N84B?JJ;R8lrihvh);+H(N!y|)j3pC_CDn{`(GOM%&Ku(~xEM91Vw z6KK<&fCPmSI)&GDCz|lyp;M@DY{QHRRfoTJ-!tH>)=ru-Hm%R1={kKnDB}e`4gD-42eWrae3kOUeUx^!+ z%vJ#4cH`8k2JGCm7pG63fy?PqFVv?5XE$eOvi|8M`UaeljG>~k3^QgsTj!=`bTmDj_rov z8g2l*X>Ay)VZ})sTqA`T z9Cn|mKSd#cJAE4GZgbA40i}C@n4m-eP*p|tHe(8^t16J9^W=8pmo~hI-A7IeK`1X6 z*!bOV+`B}M@UzEX+i>JW)8gZ&+Ax_6>$5j6LL#Mf{yW+`uye;=95`?UZcEcoYVg9t zC!=K13(*ifdvcJCRIESFT!2|KXOLSm9uWcr-RAZmK8WtO-$u`&{iunygI~cE55T3$ zg#H^Wq2HY<4xXDG|xnmESn_JS{oAWQL>(D+|i+95t z?3mFbFmv`al$Mo9KEUJf;@2;(L*22Hs4Ol(RY~E-zxnd53ILvZb<2jG`;IN%d+;PC zjv)ZJb*U%=yIHp^62Wdh4BM>e04w1KM_M$C%D0xO6omK>GN3k}!Qa;wfe}(D4Wa=zFaw zAC3vtB3-6A+)Am{`XJBh^19p&_@S)9+Wk59Z>HV0b8^R+dc698<_z_et;IrcY? zHb4u7Brg@C9lJN7n13-I3PJ{!uo7_wPu23}qrIpcCu^o6=?&1mt~N*0DqFkB!@Yjl zOiZe+LO7aKz@R7L^?0!D-96Z`eYYqEGbiApD?J)ajoj17&LWX8rcIlKIdf(p5DdWJ z@+8^Suby6my@yX?N^K3MjvKl0Q#UPE0I+laiG8oG-!XChwgUtJ)wt)Tg(xg2A^>ob z+wa7t&D-$W>NnYKK*r6_BKv4a_c>>s88TslA@s)Sv!`O^4Ob&ZAGXd7N37V>+<>la z+t9sj3(Ak|SE^MkS;brd77=x7(BnoL0NDM~3Uc8ZQ%TPgKzKb;onYpmba3^TM!F0D zL;74Vb?k31TRTR>*`0ryVWx>SVpv@i_t!UwEEqHDxTmito{}$~1=yX6OL!`RWpv+$ z0)=R(s6|up7$nKq9oD_6Wa3OzR~F;iMKdv~rVLTu(B##5EO?IC+4k+b;Nft405`76 zWmw}z1V|jxNqF@&S7834+2oj~M6xW@+l${m^E&DdpTdF}cF$d#DSHndffZykp-T$SRUWMD~R_?!5cg&_Ro)wE*a&+on zB~Cb=-2ZEDxC%az)uK~o1MloY{O}<}w{3!Z?dxhfknWK7NR1_tG{p+k7yvA9LMI?{ zR+qr^x{(U{rElRf0Q6lSCIB$=ujJET`M|sXN6Gsa**iOI%znZWkdfG&?>)Njw6-oJ z&$LSX&%ORp`U+9pAL41iNfy~i3NSbsEHo$Da!YY+

xUN|6$sOVze+x2u!!Vae>t zw8`cno=92q0y&4^#49hohCRFYBH+LHn02KDtY^MA75Od}3**L{ufyzl(-H0sQwU(- z$jL^$@aiV)KYAKh%$s=d=BsD_aKe}oKNj1FC6n53o_g~)FTA|9U)fHCr|16=x^XuQ)O+$LRNrA}-+z+s5>3q~wmy5f?AA&}%l-b^b z_`B~Q{P^$1|8kQ1&y!Q6Gmxc{bk!WhDyB?O(!DNdEDM%L?oDA(4>-k!g^IIIffAExEb!Vw_ky26Gn^fAMeo0jW^KL+=UJ6-oc6E z^_e*V7g$<)2R75Jc$4B{uh)SU*Dj|GcbtR+iFgtlcOJ(2Ep<3~rUh3on)Jw>*UtM~ zRYh6GZ~yt@YkstT+rGbI&i|ybHMr}VS@3&RGOn?yS@HlUjyI@k-#Lgt{a3bNff`bf zl4hW3Qzu~B^a&Pc*;GSF2(hBu-$l#A55u2~!Rt_yP9<~7dV#uX4&wMLEpD0PgI-ny zvn*G63aPB%M9U;xhKup@8V&%Ecg6L{nYHKxABP)$xbf$sS~hb;30VBWkLsH!TLW~Fd6 zif3Nmj(vwt3l)FPv{C={_0Qh)RUpeg{{LUS_>emxEL}QJ=8`G;0GW9zfk<5)8lQd&rJXJC zSeVQ`(?Sm7q@dMCEb*B=D59bWT6qD501$B`Ud6Y>KDI*HCrLw$`#s5K;y^PV$#IX z$R`h(?JyLH;=!lZp`o=4mBo3;&-MNEfB(fN|3Z#oAMBYmn}2e+zUeDlb{#@~P5__3 zeHn`La#+-hPBe*ACmYBM*sGLwwZ8Sp3ju&>@dIR58C|%d!aOWrHecqK>*^OJ&WhF7 zqix+=C_PdqeF0nonck7?-O91QtHG2a_k(V!^aA$PM_#D;Dt^u^S!h)^0>gTj#*#z^%;= zcD2G(Q-x;Dnud`h%Hei#zD}pN(1k~ydj}m9&P*FyjS=MqKmFWYEBXS!p2H^|*!td) zFFpVIHWcOtaoysn7*SOWw^QL_OKS(VZrvlXx$1UOeCPh&|M>wx7jh9N6{k)ahl0X< z@d)I%Iezc#LiA7_^4?elM{kcR5ehp>Q6xDeNZCUx80mOsL4E)_%YzpNq@rNYP~b97 zT7md-4&VbVPW0uH+dmj=KaTg=_&!|Htk*%hJ)VnLKg^Ji*?i zn~Jr2+M{uF(tF_XUrFnJcPHa$%PqsH(oyK~=OPryPsjgU<4+|_)ws>}wZH z!i@3Nzg#kZ+L!IWl+_!Fes|5r-T(8UC*LCXB#23)Dluh3HG)2mT&Nxj1NQAdhM0^v zwn_L(0qEkYr7CRTH_YRX%S#JTGoo6?g>zP4yay&rbhaY!=mT(ebwJ~ZMBtc-0DwTi z$udWpl{a7m=fNL2UYG;|4i*UUk{6IN(;wh)1c1R()!{W50Kh!|{FS#4iqHqU{oNGz z4+Z1rC7OUKmFe$a!RDxx$I=_22+X!F7>(^B!kNZaB)LScYk)SeyVjoD zp;?-9F0E{ey&eF%+JY)et z)|kR!vj$65ht~%I0N(9=lV=J548|IYDnF)-%2MS(GwWWFb{5|4yL(|ak@2^8Bh?!b z8LtHE>XWzH5{*&(Z#TzrxR9j#*NKLb5vVV(MU*>Q#Vyy>I4+*b*ZTngF6p^SD&VdjNgl|gLE-lE z;@!UU)n_h=!p|SOY=Vwv_2jFevh;m>2sqV-6xl*tCjM$7{uw4$zAX_$FMaQTa@8H= z5qISj;8e*dv=o#f;q=ISNWMck$W11a$ji+ok9r)6it^N)LyN}Cw`(k(z?u5fveD|A zVHy9xY{^#ZmIgZt*9%KZkxL;wlj*pe-b?_tVfSIgV+IQHe7I)OluzGu)x6)?$LRAa zzhAZK&)T{}KYM3qorn`Gm|Ba9;(UcxoaKxrWQYN`FRFo|IB(Yf{AaD^rUmo!;3F@? zJs$lXifh9BiyCpU5#E+urQ;FzM<_0kH4~!c3u->t4dH)Rs@gRDJRD0O_f zZ9GPLz`WAyXMe!a69d|M5Nl~ivZu$2{S6TS>56g_P#j4uC0-_r+dAmy`m(V&T{;3W za`jVWY-zPR7PF?G%PPt+X6zWzw=}I0_nHhAi6cU<5s$|E<LO^YP;)@jSWRI(aSX&m85}u&isL=jNb01NO}Ly= zvEywN9@_^O%Y;bGsbrB8rE2KG#Jp6~94V{{pTKoOmrJ<1_N>=P$O~Ci?0L%YYi*{X;1e(Nt2@f0+Nz z14CtA1>K7-dc1D*bet-#ru#Z2lHtlQ4cRpP{s5}0Dp68aER%#Z(bcp@kFu0lq*o1Q zPn*!d?phPJ8kfqWX)f9TeLne_t7qMj2u?I~poPMiSS*Q8-?ZTGM^_jBdfLQsr_TFI zuW#Hl^NCkC?}&4oBDvn9DvD5&9}wX}joa^x7@S5z+;4uPrag!6eE@*;4sv0YJOQ3l zuCl4Dr0PVH+?a}kyAV9G8~)B#`v#TGe+c|s;-&%%dGe>Qrj)DSC+9i%RA=T0eJr=l!T%EN8zY9^sMzZfohUZuH|Odd<@7Z;bKs-_A$*X0dO>;_OFEVl|X z5l+{wFeE)+V*q!p<>rh1(cdRDkA%$psGH8Kt*Zye8(I-3(D6B4xMju6SvOoUZ)cxF z^grgCoA)lNJ92vCuDTNl5i-@37NWc;SB>;yqt#OgIMtv*)3iq!5A?DtYczGMao^y+ zYKXoXcRup*lN1u$6_vtknY`nM2SytIBUm5+~$xX&hJCr4L;u2kR83 z=tcQJK>$WU4xCbI8JY?~!wmq~;Nz!`$!;H~uc1=Q{~$|}&K!zb_XyL?c_OubycwyE z9wft2$sS-}HKOaDt4#Em(jAd#N@-j$ea*-ybYQUTGzK z{vemj#L(4~v@5%uBEj#psKTZthtGC4uszjKc`$k((YQgj6c@e>wI%cJ1`x#D3|*T08x2X~N5?-5Niov@cd z!0m8|$H2)Hr{!vKe4qt#L@?AS392r_A*u{C)Bu2Y@uanrCtDiCz}e{e@sFxo@BJ>x z`sfzBPgC)=D(k6g6+f<9$v4xY=fWx*OMeS9UfJmP){E$8iVR4Se?0Xk8K)2+AqH(` z^}r__ZiGBR)X@$f^7t)kyPAum>q?rdxU2@bg=O5;X3Zf`^?!EMgJk^NZ=>YDb*pS> zXV&IW*e zN401yQTFPFU3==!v=wpuP?Vb^`sLh=$F2qs87$24z~^;}da$lp(nNL#USD0%tjAQ; z#Q*@=$xTV9bo8dsOD>jESI1#e1!qz$Ck_GQt17*q4mR$UU?6eN{mMmMcjdz;?#>R#*i<|xi zvlx09puwi02O7pOJu?l{w80oK*fYkq+BVj{S*j|j_IOr%j$W4{;!P}3X&0eZX= z3}QN#L_U(lx%M8ED8{xOH8+z5ojnZZ)9C73iFmqQ@mR?5<}zR%k#InH(ji+>>NC=n zGx?e~(3|zAJN|h2<;rkvFi@^Y)_MR!{Qz3nX$+bAR+DTR0hE%6X-Rzoza9};{y zY=Apo8@Q_G$u}okq8Mwo3^jjLiu?i%4iu)*aq%QJpWQE9Yn(e_GEq?gmO=-r(x9XM z<$i#43vA{Hpm4xp4ns#VwHUaUm;CW)pY$c&Xsz(pdTomvZs046>D-jRR_>VAS)I6s zP;uKb^Us;h!y?zeIy8=}ta^@*>S9h%j;8y_VT9t;T2=!Vj@bee@71rp@h7zYqHLgktfeI9L3TV8xT*mDJ4W6grgJJVY-r5 zI-_x(gXuIb8FASJ_i$LFr~kmZL;-N<;?!MaN%*s*q=ZFF+J7q)`{yu8@&Bs6_WH*j zyk&2`Sb5j|cionozh{?K0B6qiha;ij2mk)NyZ-pdslgSD)@w~Cu(%^FtUPtvh)~c% zCKjYPCL|;Y^IL>pZh4c0^k5K<-I?A$PcaLB5V8K2LT9jBL zjzkfBdW{HOo2@CFObfM5;fcMt3vOEmZkW9Zr2t%gNMt*G3c!D8-daDLYkpTBV3fPc z_RGX9w;2FBW|k$z`ec1X0n|xgIMG)pp~}~}=1-w1kN>u6YMhril66!m936~ja3(_@ zKp?CQmZK>IT`6yO^({qb-wK36QF^TI4F%!fr^R~?OAgJ^2|w@rS(s}`t%f8k=Th!# z@KS)~rcQEG6OG@@hRl;1yK&`S9A~j_`9}zu2yS&Yr}?()%p8&#mwDTzy0)+ zyAGYbZ+LPRZK(v-^tOqhHT0jQNch{65gGNhkY*t7LqVaSR07eGPr~Ggli69OR!|>~ zH6Clyavq(>4+f4G-(g_CTW)ojzc2i=LsZX-ASjL*QCqO(^hqe=#@N|ryzmY-?A znN(A^p{o*f9i!nEoKAFLDi%XotWHoR@}LwB1AkU;+J;EH#ixu^Y|qN5Bh!LtSdAPr zq@K+yZ6?cI(=+Ir3Y$?3Dv8c8WQ~>)9oq6`rok#B8dFTu{3}6qSm8`39kJEJ}DGX?Di7HM$T)8h`?(ba1BCNBu z{9$KLU)0@XbA!*eO23<|3ukvbQ4Cf@KEV(}Q8EnnEt@CCo&JdQZaSEM_Br_px zP`MItaXg1<@@BTIUtGKE)-_+c|Mr_d^K$!k#dBXS*Pr~mZ$5S3_nz593LuSCO9D%~ zT4X{H8&!tpatM%4B$`=E{jyi|1{e>eUlwZ(OxJnjH-!RDUEWj# zkj^3#fRwBdjzn5P_1g{oxZ>z2cdtcxBro&ma8!e}D4D_s!%=h()7VzoZk1NLWfF4T?`gF7m}XW=Qx;oV3$`a*qESHs=C> zAuEPs!30L>{6)AM)n#l-P`diUWN4PJUWfHJ->$-9I9`IBja)n$Mw&wDpx5!Il2F1Z z{4!Z+X;>1`G6q(CHug&x>Bph7t&JI@YEKRf2?n4elfvTO_CNpJ&%W1^t#*xPwM@RxYQY{FFl=W>^VP5{FmA7EpA~k4(Zwx)g zOsSLEvh+yHd{7QANEw8giD-NXi6bwdZFm6j7+r&7Ng^dko5#HZ5%vPuRpZcsQC^H* zB#jI50_;pu#*4#be$liHZ&d)^_)D|i$rLEKO(GhzB-`(*5}d!m$1%#lgqxgnV=g|< z1)aWtdM=MDS$~QB=^4|7DvBg=HHoKPZ|+`&{>_n~A3_A@tT1X&B|+t^+Z4X$v0}{{ zY`^1fv}8I&A(%=R=LH#?-^SKIqJY0zmL)XcD-BrgoRTHxd^YuDFF8nm!}A2jvw8Ad z9Dx+G^`D?{;QTPf|Mc$zJ2qnDn!c~xzhlcMue`5US%X7U|I@BRr+@ux-+O)|k1LKx z16W0_bxSNpF^?;XAQ2A=-x<3hj&pT>08%%!~k$WkH7YH znL!wA&~4cJ9MXsPU{Q$Ysf9)91nJI4==CC;8?aRgIA~%f@>Xo}0&MOTXiL(K_gQBsVYTCQDm1phpfSG(5$dyqa92KUkG6_$W z9xe;rS5W|O@)}Yya>P)KH7ty~Aslpr7^N2qXnJ}^rZT%P_u$`p*S)xT+wEkPE9x|J zOS)9LEaAdr_kWI$>=pVIL5OP*KA1z*HJ2VtkhB(ZeSGJ^Kff?CC1s5Ds}`X<(?WZr8hY%Y zD}aM=FsPxISEmMRBD0!}6^^Uo_fowoF-*DC(1S=Ds_T!QR=PNV#QvRFK6H{|`-FrK zMgedLz~K^m17WCABD?oCDFLfJ1&b7y!+h)dwT$I&SZ{d&Z}_ESeMfhPzT8kxdtPW@ zGXFeehH>~Z=a1s##w6GLIqT0|e&pVhCCxV&_*3y9>AYCL3v|v8R>}P*<1thZU>2?h zpQ*E6s+4i-j<=EZze^~&cpA1DEyheek+4eqaoxY6Llp%IRv%298eI`HnE-F__hq~S zM*K}o=g8{2y7f0q*1v?KXU+<1abJ5H@4D-zUwPopt$(qAZN2(Bd3NaMj+`C*tAGCP z3pUr_m-c3`q`M8ta70`k&e*pnqcTXu*6oP%X~O-h**)NDjcu!LLrb+|@6lA$Ux#=vx&Y>3(dh}nAjzo|Oai4%Iu;Q>C6j~(73DBzxl^7J(z#lcC-#i0; z$OR}kHJ@=3TLLbepQ%~cRdg^$f>+W-W3DNgl64~9f`@+W16aFx6NRo-m0Y%<%H{NZ zn$BB>6acS=zGmBV=QXvio}}gYes8*MEh9@{+`mJHv5FZ6FOkqNp;o!#;KEoA1Eb@@ zy#3A{8=P&MR{Y{E8`u2x0(SN4>%#E#GIB3|<8S`IC;lyOOE_#{!}4A%B281SG~^;< z6o|C8w#W!^Gwuj5kY9Koc5ZIa{La>}N2Sqtf{Y9O@tBQiU2nd@!vCj7*94PS5c9PYK}mP!Cbnw;F3;&lY^nK*9dBeME#b; zRAd~TEmT^2?%1)n*7aQ;2Htvk;Fhuerrak5r8`U2{(=FdBQ2;}qsTPr`qUyoH&%B_W8|=|DsJU#;1WE5MI3B+O{sEA-5t{+@(wffZA9{NC;qUD`avtS+4eLn(tnTZQ z(pz05ry-L_lJSVP>aNzJCc0lZ)2V9IqMK46C6FzNf(cnwQ2EFL(@*;OVn2?f{#ASK|NDZqFE!A^Ij0B##@Ns_k^6ou2c%w?H}9BmFfiiWo| zzztbVuabY7o3UxK`f5@QODFv_?>;L4VX9DtN3?olIh9&hP+Gvy6)ei-f z`xPOtL3##k)iP{b%AE@EU{Ug1?2a~A$++&P_6VAqomW1}bEBpGO+;_4>${X?*Z0N; z>6P#+uDHNg~dX5%$K@b&-gL(MpCU6bednP_rX; z0iRY^G#m{UV(VYxc?6srD_7)Y_;p98b2vRP3U1nq#iNZ6KXA*j)|U7O@4bD?*@f)u zf)&7#v%@VU)bIb^(=YwklV^tG?3%A81#run#fsGzij{;*9hqblisQs?QZ8!+un-AS z?Ud^KTDgv~nHfQ31q>)7peDOo*(scR>~VCQJ&bO*hEOCb2|>2_>;*)vpo9SdamgUw z0UwG$Dj`(?@dOeP(X2WT>&qT%E8|0AzNG+e-12}xP-Qj2Z@|E2RU+3@0JegfTa4o& zS0CiD*3XZiK9Q61URkU?M961J`0JWGz|te{`HfD@l(BCzkAu@ioXwX7Xy#}Jo(dV9 zj#LL8{J?wh;h*@J!m2Pd)|_uwgMQL!Df^kRUAz{;QEOO%6ltkKAu`l>I$xx)xP+h? zkV{`j&JE+t;JC<4Ust;L?t5}1 zYe`QVHm_ZbZi=ZnzNs<+BE{KlEpbFC_Nlo#&o5d`zu|&*KtI=3lTR2TJi}939EF6k z6)!l29#s?vE+GHpqi7#Gi_Qp>g$9KViBW>gTM!JY>Ht??W#l-;Z9(Z6Ou!-~V0ETd zRY3C_Iwm)3YRx9_)JEs6RN;+Th9!$b%9@!&foAo_kM?sFOD(KoP2zol`I7rzr8u6! zJO!@#lV{Bt|EfvDIZ6Srr5z(n`_fbyyCw=4$W?Tm9%{rFTX}l@9e3P?PkrVWkmd%t zdfkKXax#yR=t+_RM#!qXQIjuY!6enXdLgXC^hf1#SrUH*iu1z^bEn6~W^!bhFXH0( z3>J5H;J#be4Rp4*thjso<^@yXyrT0=nkG(e{$GCi8&7`p@bQ6of`oi=ZyRn|y+{j* zO6IkYRc%eRDAb)!1e!d+LKJ{>LBi4mqO6?*n3|qNiEbDpuWb2!0CoC(yy4>P^E(mT z_Z<526LhB{68n=HppeAzItL>h|J%)JLp)U|kZwVsyA_S38iUT6VlSNZ{C{1BncJ`N z*17@9kNOMfBy)2#7L4bt6aXj5rt)y<+%&R9Nh-@=53mW8t5@O2KJpRV{lGgglbaT!0-d#IuOv!gW@~F& zuF)&w=@O>B5Dj3InVww4DukPR@)Qai--kWn{U^?&e|Q{ax~7}fEh~Kdy?1}3QmuVv z&B{f^h3@GqQUIq1$E|QM*s*i((eM0V?}^)n$8zY*wBXi_OVN>zljaLiY~<1g1O@UK z4uzY5Oq0BEul|-zzH=@KT7oyIR+!?5lmOjW1`$~rMj7NAN!l^{gC|hh`3xxp2VIK`NIMJoS>X{u*+X3E9sVMGSW-FY8vP7HY8yualOTvB~l99Nmq1mFki($rGaUR z6WH4@&0<{Q%VaY6;731#cf9LCRBBa;?LACC2{>25crs5c62A1>O>6SiKBso?ZC80G zj4R+|ILH1R;bF+;WGjU=0?38TULJazS}naLbX<(AO*1CL;9*b+QH$8r@sEk z&bL3g`zYE|DJ<>f%;RE2LP4QH<{J`E#Lz}s&{l;QMTP7xtPUV__fYLWhZV_?bO;7@n=lU~W$Pd1q+|dxax5f_u;faT z7ZdI4LajYX--i{gvZdM(pbwlJGH2nmr*Ey-ZyDT%C~D{u8T6MV%9(1K;{J&lG)AXU zC*#29rQmSJpF8|&DDjyzLuvI0@1WhF-vQ6%EgUC>F;Qbqe_LhRx#6clZa4}2yWab5 zy!$=xMMql(MV?|E(8*&*85ME;NhWM*0BY!_Hsb|jL4{;jV;-a#j;>*5dK&pMd%sMD zN1-nn!@Z{laCT${C3?I&lX&>ft?T~XPrmQ&W3O~SUzGxIYwm|1f9cTYzxl+AH%(0y zkWMCW$4#rzm5B>kCo}s5D9&zg<-X^jc8{7L@9I~jz!t{X3g((KxvcqSilhX}Dgk6W zs*{S}qg+Da_zBGHdLHiCW9X*$=TLxeAWur+Y5;E@6PbiHP)L5wzl-sd;RNhVLiG+r zBC0pR(XJhoHa3KlZ><}<8dj54+V*;CTt&%UsKDU{pUG)dDCV!bj+Cjh6xYj85A7uw zc%*0x4LFwtZCB0LYq&K@M&EJIU3lQV4`I=wKJhv&O*mrdPQ7@X zgg>2_Y^Pb;kZMKuMh8@tfrOUhzWl)hIRC^WNKcF+ zLsHCh*kzaq$N!|AVsvxDTqcwRVNkTTUE}Gk56ffa`;0n(2{mtsAnu z{r4!npe!s`oaj8DP=+&|heMXXI$J=I1(KNW3U#& zzN)1<^DK>0t*N%%zP?_3;%7dIMave``BoTw!#l`=9wC>%HJz5JybWOwhDISO*m6?= zT)kt~^7sX6n90qeSgxyvxL`n%;d@W?V}LOYbl#VBrw+8WM85dBfAjG#znVRLO{e+) z_=kV}=@VxM|E|a&3)+Nxw{67AMI9nBbw@FH3 zH()S*bD>nk)XcQNkU2qU8H5<4uX0&To;Zq;r=CF9)FjdYHBN{@9dZzNCKmvGF=ziw zR`~p#ToH|8N$~QV@XNVevv*K-j7O=8z0i54EZzUJjUdj|0~n`QE@*msDfu-NX-8*I z7vB4xhp>LbI%)Z>OQ)ZY-;!RdEz^o51Af>^yUmd`82rV$>GmL?_FZh zPj*_8ejy>ib#P{I43F(OLGK$x3mMzCSn!j7@av!a%B$Vi*K~d#e)6SH(?$OEHy__C znB>J>8EoCS42wJ4$aQJRMu#~RXio`K3h$dK+syA1P;s64!TZKMdCs>CGAa~{$j+!z zrxQ?uDSg|Z!$6xhviAVWFFb?r%mk8=7@|zo#>fPQ2{TfVt~VU8n`}b1Y9g|EvT7=Z zKst#4#d9um9`b}@?QS|c5y)5sR}+aa6?MaH_MN{GrxCp#%T#%;&}fltMli6@e?2T zZ?AU0U(>yNVeg5K$*J6DzWdBee^9JJ5^_6kS%X{FErV052^N|)RfZW*TN1+BtEkgl z4|t7MvEReJp_yGMnhf^XVt9-y$c(zR48B@F)aS24Ty2WSli zkclQGqst9K0nP&iI2^D9F&NMZLskSF^9h3xc>uxg3@n~B#C^^U#Rt!;Zs|@#W@UAC zQxg>Bn7PM45(>a-$SA67sRI0+d;wpL-)}#~o0P)5BW1qY@C1-6pHPk zu7jtBu=C()-VsE}u-?6G_3x&W(Z77(19wim+WmgbckZbd4&FPF%|HE($M%2+imqPX zhaESq!phzZ@}!OV1BZfP(vm5}lQC(Jgr&8eW#S!!+xBy!`LELQk}dFU8aGB1vIS8B zG6;ejex%k)H#ri)%;EhQ-T4fP$BrRJAp;LH5qNSSEW#cYSy$MAh)EU-{(!p&BNPtA z5zMrR5`Zr2c)jKgS37sjDj~GhGMw{o_NDsau05k-Qwg{p)YqH#$_krhs7&#GmfZb` z8C03omrP=%+CZ7TkRAZP;xBvU&;bzGWpM(HO;FRVl+H6LA4Ygd;(jlH%z0M{~z*-<8a7AvTE~ zxJ{-PqZH~C|8Y`~TO@6>qdX#tM~2gnGyP|A;hATU+y4?$g`CV|3)x|bse-~K!1+Ff z8szzh{J3}tk{6(V<1qv~Qm|W-6b^(npMWc6A+IN$6_OqoEuUzfd-rBtuSW=AmSZyP zh9E=Z`sF{y!jsU~$8)HWuyQX-g){ja_mdJRHmU;h;an1z(JVAOQj4VRr|bywZWIS1 zttbXnyPB=RKnxgSfxi9DTXDx7JJ8Y5A;~rlJ59HqtCM~iiu=P9+Cn1_7qV3KLW+cQ z*ot_u_gSOxB|DYHEQK{Z{)!D#jY64c_npLnQx`;bdfLy;1BGqc`ZO^`R=uf}@+`i32quEGLdj{J#EWy?dE2P7Utv-WsQt1}7wxu8dj8I^kucggmzq2AG89nb#9>H zqIo~x{0hLaUTe5x9A69mHnI5;wDJH*Sa@DvzKCjemJ~o9wR}n1Z%a(d!M*w zstodxQemKJS@}6+=|{qG422Vzwc;2L#zc6zjhrh5^%`?rMsUlv&A9E(?dYNS-(fHi z31zc2*CnBkpe5BJNk3Jtt83QYtM3F0xvR&Q8OkwR5BOx{;0&GP9DP214kx_1l)eAN z1-y9VEG9_VC87~$d2i>wkAC3Z&&6WV7gltpDzD`pUb9pB{DG4ncy{;UFP=Ozva(pM zV^L2A5AN6~SO6Zs!~++?0+DQ$da0Vu>bnHjf0E{1mSIlv{b;_Efgd~|Ax9fWn$r>2 zJfN6~cylFwZ(!=&0FFQX1l&_ck(!-Gm`9p%DbUru0^B_qP+f$olMvEVz|NsKi18?_ zwj@I7q>LYLkSAk>6dk&wlTvoWz3k<`S=W{N@~^%u-Fwjx=Ua`^cD)j?rRHVo&N}in zNH`n$GOXzw$}@TTz9_tST)!`oOJ1s~ett(YOF24}bF7-=Dfqpnf(cxRW-t;qQ+-QTUgv+9aE8l$EvY2TNpw7*`_-2pOlF#z z1n)+BP%IQk0p!FB3GvK8#=Xpz@%U|t5(^($+S~EFzwz@Q{PwlDhu7?= zKK0U3t6r@=xpUv?x9>gLk8~!1Eh`q`?rkd(kHloEFrSu4B#O57HUvTeo%mCm=#f3Z zbbHTDo;2HZeHZVlbRw7c>Wl%%=20jVy&hgi=EbQ}AG?i{17|QoUcl`By;2=W1k@}6 zNdg8G%8H3anP4O$h(V1eWZ~vvBb*l?;kP;F>rTN@njquH?6_ety{?Q_sR=2I0NsiRx#O3LMQz~ zp^&QgyUo7*h3tgnx-_mu?V);{`9r5BCs8UXK0zLMQ!Ul;!r`;nfAT!?#R_7v*!g5U z`p1hp(tq{ue(^)s1e1PEZB?mU`QrDVJ@`xCe&VHYk#0~XmB52{tjGH0eF)NqF=Gi^ z-9$@Lya1I&cf5IR2A$>c2I!#(>Nq&?`v4N^^K5~Dt=vP})GEb)rF?-bLsd_F)yjpf ziXD<{YWBhaPCxNDW)JQ|Y<30_dLAnW!YFtjUi^1wbt`Q|VQnMXBxceF|#wsOE4@FfDh3{DUGBcoqfVQ=2Ks z*lw}-j&k=|_<5LzW5@sjm}!;l1=Q%i)U5~x(rp-yXHW?-IY&SUJNZO$4?oBAo40Jh zJ@?!}LKYQ|PAtARtV6L_haw@QB;y~FYg5Kb!F?UCkMt@Z8P*(+R;pq2T8#70=ks(u z4Jn;7n)c+`5&Y}!!}NF&sbq|qvc6QWJHPT*pa1lNT74IE3$EpHpiNtSW^nAczw_kY zpV_(RBtlUeJ#8tx@9kT$q_>kkWK9H_!4u&a_wMV7LeMNOx?9S`NAu5>e`cD6CK-fD zq`3OVF;<#G4%@Bk#1a2KAQ@IZa8rXrIJ0vXCSKZw`1mj)ZkfJ<(8zF*eHUfGt;Ep) z;|5&u2Dm~X14=nbNH@uDiA!#P=MQjC0fz()Ls)sudWIAL#x)5}*Y)Na!k0H$2&t)9 zDO-VQE}=m4b!{3#On=BV|Mks44mEY@ReUN9;*kuo@H?oID)cZ{6su^E#jlRd$jB}h zj7r@Rh%R&a73r+-*sdCk(J-F_o;%6HK0!i1nap4+*@7x}e7dT;l;5{OuN9-vZquf9 z*uHHGx;i>gZB)dQuyv1sYbk;Oo0UF!egQ7`X%LW%=k~G~3sZxJG}qQ$eiCMILmRpM zTw3HV)+i~Y{;>&s=c&E8IFXmnvu;HBe$g$3sw=7EV2aL2OFnW!$MIXPUX`YQ$K;kc!$W zu9r$96DI2ED`u3EG<`%=0&nW#ATI3Qjp;ovqA@avM7=C^eoMC^2Q{YvvkFBSG^Be8 z!Zw5*CQx$_;N~Hok-)Z&B5FAnhRv_pJ)N5a^*GZ{9xliDHd69Y2Z2olqE9t+n zblJ5@rs;7Xz^7<^FXy?c`T>ui<5em>+9{A#2^3Ud+yzH4Gz^MN9CHXM|U1vcl^}Q zUmiR;a9^of6Ly|=?%064ZeA3+ z++BM?ui+7BKs7hPZu0G^ownv4U(4iLnpVz`ZZ=)+SH4`U88x$`CX{XD>N-5^qCnP= zV&QtFj!LO4qv9$|48tHF_V9Rgyzv;|YLXaNhRN2*%2y&J{ABfKl5MEQlc?K_=HxIV zD9ln8d4Zjo3|6mOf$dvwl8kfHwuppQH`fz*Ojt#9Y-hp%;&b6C)3tGsTT+6 zzcDmsnq1ORZLBh7oAXOt7B_p&{VJR*+jZz1p5A=|`C1tX3Og2ewLjI>nflCUe&V4M zuVSmOxL&t#_3!@W>6O#j*)xaF3?WN5b>;GIJg{RkZd%bN&`juooq19avz4-Bd2QXB z?V9wjs|DP1{ml(GKRcH|iY*^^JiBf2Xb3H#kld<9K>b}%PYOnawLl(cpWBU#FYZFM z|2#s4DTFxr168lJbh3y`gPb7bvS5r(Y>-@m2wN`A*b?S3<(W7vvMK>C50M+^a)VJM zD#^$uH=-d*h0G+hG{n^im!m(Qf0C{7ZyUbP?j1At@{gIlSm=7WsWg7Z9ls}VrN6oA zGKC+;v$EA?kWE>+{EgWH34RUrQcVWNGN`BIsNRxFqbBjbZD0CwENHcG45e5LiitK9 z((NcDQm6&Po{-AqZpQ7mrLl3-T5P>#gLtBqN)=v7Qg`n087k7_oVThwR~M8f--Y3f zutX`iCWoML296F}*}H5ZqYKaNZ~j@64h=_rL){p!#D z*n&9zUgfR0_N)Km$o6uj_R|0J^=B|KF)1BX+cvMk$KJUEfr#BaOmwoi!)anBFWq{M zThr8P_8bq&%yU;J%TZtU%U{0n6gVVElTfyk8&%hkU0XMjIJ$_Q zFH)sRI6@^2arf}KzUDS=+Z{Lcp-VO=rBp0DAw@}yF%EB`NM=oC$p38++I?R|mso{$nQT-yuEl^=r zKxoC<(@7HWgx5d7*IKSw`0mqt@#3K~a?ZQjl6e1vck)@g^=(^LTvONIyXM#Hz+4=j zh&oQ={&NG9-~HO7Kfs02DRj4GuzlkSeDodL&~&CKUMtlxF_p*oOaZ}=cJX}>&L&>k z7Qlq$cQs+cm6kb#5pvU+o1K|cLSc0nq?cSbn(!M`^H~&zhH!4z9$eV98=QNkN0U}^LcUdV=crxO!-%;c+z+(tJJ zU2TcMf~!4PRbCVniKTK5&`Hx;mBNoy99M%JF; zwB+tPbgye1>$4(Y7%y2wP8OF1%kRiEo{GyId^$bsI+7O>UCr!JY(?2KBPCmlCs0av zqT11idNPGNg&hNzWdyM zTo{>_q~9%@SI%tNxaxEF+`RHtcls@4T^CPs=iW2Fx%<$mU)^)$Ob<6WEa^?*-FI!r zEgM#f6=lX#-sI_g31`obVz#KzjkZawcaGdE5aik=_fCL<;v(U=I;%3#eAFu+vX zb<>0|`8H>Q(VPQ$WIw+9)FE6P9g{r3x)qB@HmzIw z#Sgt>>z};dvUz+QOt3tX2Jgf9Jp-sLF0Wp4uU0PUL`Qo{m1XKm zvGDr`St#ugg(XEyT^z>1{{5KPzZcbu1F$Ge2vyWn79NEXkXo+pBy%AIBa9zl#Sj)i zk*yR$K!*=phNPR$NkV}ZlXqZ8LxL~_laB-xu*ou?Tf9n3V^KU&_4+5wnFB7h(pS6b zmpp&oWLnSh(BZbHEG%Q;n>he=O%3UglrkF$J>&K{vFk8d2bc6XzGq%LuKLh>ai2Sr zcJQBYtk08q8y0lk-O;bDGyQVg8Zz3=jkJ=mC*ZVoqTbnydZr5v@&e>(+@i}~2D4Gc z<5<$ug|+KfA(@U!&W10srbDWbtrEB#ijGar;_To!#wM~t=n>FxWC>Em&MZJoEK>~h zdqc_r;`0@!aB%73F05M8Bc7oOA452Ceh^>({tM_IoF*@!hGl(S6DyYV{FjdQ^cOz- zj&1eVTQ;v-F6mp3?C!icHt}2iLzBNaJerMjtaaD+HF)paw_#~tCyFIy^|?TB^mISY z4~(Ep7J{?xwx0QJ=^D7HXS*H}&Hqt+fvIKiV9G_~8_F7&0X}W11Xe8VmiOk)Ki5@< zQT~p8&kVtAy-K-B44)Z5|DL_b9o&!b_!v;g(&4OX;ZS3n`0oR@@&$sLf}Cp)oFCxc z0{#RcODhTT25hD!=g-CE#JGkS)4y(%gg+J&#o$P2VtZE5a(y4sHNYNo-d?WQ*j&bo zFw=EkZn@1f43oh&mL1K;OtJb>2WOX>Gx=oMT`u2c3j*HZncEEDVFh1ftKV?ttL!#} zo~!Dpu#Q!F!*|~-fJp+YbV8ADGH}TlCZVvmQcp?0qX1` ztG{9ydb>N2N+(2FJM7X+1gH8$0+K_tF>rANXZuGmN!MJbFeNPAfzA279ti7dg5*Kk zEzc`bF@IgA0xw_Ih1IK;AVCJEVJUBbWC8#B%zo_Je}X=rn{7$Nt))GkU+V5?{iC1# z$lJ%Shg@Da1@Mi3-DQnUPp_TI7JhqleDsy!Tub2)NVwP)Td}kg%a`_1OctfM z&=wLC$5!24GG;u)6l4{Qo;ion0|${kbq2G;0|-q|!p>#Mq?ELaXsJW0Fl5S=*R91N z!I9Xa6v9R^SPFhDbY)CnN(z8O1?ZjwP8JI5P*7Y5u^Oxl1&VCyV7}1jvI)C++v6p@ zE~fx2UsBI%M!&LsdJMIMSe$sHd%~8Mt)$IZ z5Sy9{85qOKy&Cfg7+{j6vgaO#pYIXB7b!!xB?F|}V6}C@>FPnfqfs!=KN}v<5SeTSgMKB;nnc1O$l!x;al3W;?z?pNyn9eF>tt0}W8i$%R zUWy&)s>>fMX>W?XT5d64xoilOwj%1aO1Hb9KZ{EPM}mR=k0*|#g4X2 zpr|Xzz4(~J9P9k&XSA7Q(PiEV}Lom6@ptQ!d?b3DE~7zLx%=(&>Y=qY^fP< z4l}uiuzKYZ^!2o(ud9QUl8sVLkv@v!E>l>zrMZsWo5rxCYQ9XAG&deCB zMpZfiZMK4z;fvElNu?)UamR6JzzD-Ij8agZ0t1RTKf$$Oc^+Fdh8o-4krd!ykvqXe zDL@j4N+B>gMiX0Zd7X4-6E5euniT3~_f6*@T-Q*z>rrVe>~&WOWQB#jDi+n@BwM)( zl&gZN=cJtwwXnsnIntRaRJq| zql*XPp~2K#ET|22y%E}%mXK(4De^@6l_ta!#JW^nPs7*3xZ z#4OL9)RUnMC!Gqti~>--`!9#{y99};lh0g1ut}q?TD}N3ZCs764hlExJiab0^Zg!w z{ve*)bqLvPAsdPW|Cz4z-;)BUkph_g&7XUJ?Rv@N^)4sN`s^3}+iiWFt&g6(Fq)ns zYq7Mq8+YBd3HRT%2?-|L0EBC1XmkPx4xGe=kx5i4j>OVdU|t*Xl|G!S=Mm_!PlDFc z!xnjQvWIVOBpgLYTZ(Sf3M^mLDa4Qb9_)Px>4l}3S{Qv+t(H+L6fkn|C?-!FNB%-T zY7?Wt%oOZV3J-YL6f@6SI*#{*QY9Dzx~D)84YoR%VQDt91chiz9>G;S1l+U|Vr)T( zED8M;w;56*=uyRO2dOX8}oVtKamEaZ^bTF3V! z_+sgq`I#Q$uDm)Y`nb+6R^HW#JWG(Cf~MmMH*Vc)8?yAg7D}as-aEt;?P=KU z6q>bm!0qlOcfTEhR0dW{i^||@kBgJUF|wvzogL`zYbU25Mus9HABzWo8b5{&iY1Op zoo8C$*zxli9?7CuttcgJxWz5o^N^%~0p)3$65q??GcC`15*l*4#xUKNC5t++b<0`_ zMQrhQ0y5g`DH8r?cOS;s1(!F+z!ghr9G3xhSf{4e(f@(m=M%b2Uu$H+;d=)dmd5(U7DT6 z)c6#}PoBlh@uR2>oJQ@$2{`2<>6n^FU*_lpraAS#G?4@g0ZZWs!m4U4p$Shh5{o4s zggWT9PFh(e#9)`54mQJ%8@i0;3jQFVnyhrW(0^?Ga9+!&02Jub5y-8}wePxe^SN~A zl{ni$=wYQ=*okA?BIQuy4;LibDHFVh;dp|u} zAa{Qdr%qiY44cE0ybb{-xu1`uY770?d#z6Clqn@c(}44}a;$Z9`jBjV<#np@&_uEGg44w;+!_->`N$mM`zdqTV*iQ>etW78W^(t|WH2 zUY#AwAv-|IY48GaCr_X_HcB4B7~Gj@I6T6fs|HrU3rP(8NkM=OWjWUpY_Gz{p#X;p z%vdZ`=y1GnLcRpE?nqfO5RQnuEVC%sLkcQlQ?W>TdQQ{qx;i|u^z4^XE2k3MyP&hr$v_VP6xp+ElLzVt`G^!GPH4$bGiVT-Kq7oOgA z^j98!Vo%E`Z34vbOtnl3y5kZS7X zgVxXrVj-=vl3t|OVL}GBy32U<`AuukOP)!Fya6uXK_{l_T*j#fRmm=*LPyd|n4X%% z3@d|Er%*X}2G!vUs85cm4mYWZSIK>@Hj{=>(_iOUVz14VJ%XT`iexpUv57qZg;-P9 ztcIOhnxR-9Ts_Q0MyXpGIU&E$lva+8YprH8kz;Aaq)Uzrv0&>ixOJ^u#llMqEzp3W z+AwUkiqc(h8x2(raU36%S;J%b&`a+;c`8iW8jL03wxkg0>OpAPTEy0^L$Iw?!VXq) z99r0per*z1?#GWO;z+k>}1j!YmsK90)N1gb;BC=6eOlbc3; zYz&RbDN+Pwa@(OSveR@UJ#R%SP@43_vYRopzGeR2cLf|$#ZIBP(v2l1((!T-u1bJf z+A~mZGF>MNg+SGuliN&(g?6QcTTZubSZpj=FY#{9&v8v?DPR`WVpG zf!OjDXj!}zPK1;zx%q);5_U8ucnHNAAy*-<6^e(DY)vAWObR`=C~Md9Cg<8_kcZ4} zaHJYDOoF!i#bY>jdH|Jr6+Zt^ua}GI=P$L(wxALHk7_&wKhB{BUFv2g!`-n7J$)Uh zmTRIQI2_n_^gO=%*e+Zg9#c6RCdLVdKVby}|MaCl{KXr}BXvU+0I#93$#&ArpFMoy z;_rUtTQ87Rty1h8#QGJzc+Wd-!`8J+FkP++c_-uXr>3)bYUcqwx$6iL(F7fax+W3v zCAF-Dp||`?7-T)-M@u>p9i1R-BR6x?x@EX^>ss`6q)@ClBJ65Pt;$%d3_4pnmAha; zs?5w_^2}+>oH>X31ce4eL#U3E5-8?H*@?Ae08G6m7DTLyt{5nbtdt8ZHPzSyIl0Yn zM1??lexXTknqC>NoCj||9N)qB$GZMz9n-a_o@DtV2o?Lf9@@|Ky^hss+SPrE)RBSX< z2~`9iN-(+qB1RT?WGssp51ho2Qv)(qt6bF$L1=PInF&J+SxWh;Fh@CS-frk;)G=Es zk=5Uddv4z>aPxpxo@u&nCiMK?Q+sgo>_rs{NmT+rMKAjBm;dauh3hMAm;Zb>d<~6H zc2{eSUq5*4;&1Fea02HB$0UwjPa5^E+c)91TUMi1anu>6gE2lii5K=B!_&KuiJQn7 za$9D1s5WCx*1?ZQU&ux{CKK#qcVl;zUy^QGCY{8x#hqBStQWU#T0<^gOk7W9IjYOk z9VMiK2e9O@I+X@Wxg09_EK1p|5LuSV3z$878l{WztcBJbM zFx@oc3iyLr8uo19y8i6Fv22=UrU}w9jA&+hL34(^_nG~zydJ>H#|NP6*&gc>+&M}^ zye5jx!MOsi7%;B`PvM~uEf9|&+`=TP8N?PZLvq6g*c9ip0thnZfs=iSlzc`z;7Vx0 zfUIE17RoL5zIard9SKMXsM-q5dg$g3ThO_`(HCIW@c2|mBpm+JuYBXF(wPgRAD@~n zwQzj5W_d4u>>amb!|G*HuHh^zcl1qXXYj}~2XN%%fW%cSbYZTMOM{Q01~;~80o`1h z*wa%091k-&xO8(hyn&DHtts4o(>knN)`MQU;T;s~F-b^?G47mwW(HeJwG2tg&Q@c` zIP1)Ab2UGU;)RPSUc89PY!20FQUDYpR48O{xF>>RTKcz^BZW~ZDRiB{TcNn}Y}FEN zNj^Zsp|vLf!?I*xyN+q0b}w;w=kJKEg#?D1QNG+J{grf3Hk9x+R24vmqww4W@{j_N zm{|D$Tltm@LhTt5{&0$7{GJ}fR;@&kg`Nakyrzcwd&$w*4e{<+@IySxo#!(I6`=~} zfQ)i>T;9dPy7u7#z09NlJYCXI5lkE$X#s>M^6 zc`Qe91a!5x()BFCO%$T^cBEwp3ZuSQQ83(9MF;8vfgSgBw#o5$f(7qIW(8BEA@ zAm!QHdKj#cZ-E(GzHxI4Obn}iGRZ_E`@3ZhffUPnHP?spEf)eDTJue z?;D(8@_h#LT{BWQ_&bA+M6jM>4Ij!%+c4xjL7@kYUr(Z7U*tQPN_iS-31mleJhfa?BAS4XDmY zTh;XgmU6uZ2FJ1g@EM%DI3lDSCEhPb&wvQ1>A~I%PVNuzaztteRNh30H4 ze;BV);*s1G3ch{EX0rav#npFp;*n902M(XZw;$b!@#(DKBRboXrH*vVmnnSt-0y$( zV>dkJpTFLa3gEZD_|H}(99SI=+P{}C)jxjp+yJ@RAuR9f#J#lfw{K;w8%D8I6@K=7 zp$rNe@Y24M5(hFsCg{0!thv+7%{Y@>qQIN0P*wWYWnB$D(A(QxvBs zqy`WAnT4H&KTIxtkc2zH!(H0R+P9|Zk3(|!eMtxTS^5nm{89g^TAr@aqp5jB(K>AP z>*{e=b?Dg=8U)3w;u#H0&~c)F5JN+g7#f?v@bDyZ+;GHg*Sbwx8nZnXXtTeLw%&7< zU$fic@&e&MBm8=dB4mDn^=p@6$JVu2y`&q7L`(=u6Qmq-#R~QwJdI~}9l@y!BQi~B z!^*{oMeKi|bMkqoVV(Z`ul)FR!S}zC^@dacyng>bf6Z=fiQh(>{CnpH$KG?|%%DJ3 z*YdED+cshQ&1=xxnjjB=pRMBb^B2ajd*3OX=^sX(1R)$$2gub>Pggh1SiZY#ss{=K zKlipP>F|3Gx?HEX&Cw(ea>z)C!m%*=C^T3^N}#v54P9MrG8=&pi11=?9)R1PrF^I| z-sT{h*JQW1ZYd1DWW^bGP%5I5C6Az3qR@e?9e?GEl!^X8cAC+yWNqn0FDBYxEh}xjgmr0ASgpI#gu!a+swpU z=otzUFj#tigJtPy!n(&mKi`$gp~4RYHKzi9<%(6Z@I_2b&fqwIO8fu-9|%cAK~%!< z6wVHhV`6MtIP?{mNqr{UR(T6k0lAdNKzl%*TcBNfK{Q;N8EGa~RUbb$@G$sj)v_Mk zPHzA5r9CP_hx4cpU=&fU;O-MfAW=; zrLNO@!zut?U;LYg1HE1C_t>`kCx=cB+;;5ju(X!0T-=R2wr{|Wn^&WQEs?FEtYm>k zCbJY1p2YcqQK431nP&8u@#Ssbr&c)vH80+fcABOdlMtITv(P8}P4`+sh54ZHpL0_W z^U9^uNi1F5Bl8e?Ix~nyL(&BniG-AAP;WqSqc*&z6Ca1koZDl%;~LVG(@^gv-FS{J zIjYRKX#OWtceFKTn5@M1>_xad*1aK+Z!X`Bj7(r;d>R86M=?G%t3XY9RF`QJ_g5t> z^M)FJ49g$G`$xsS1z1&C)G!QUjAM8A*g3Xhfn6X-D1v}u5rTk~3r@TQ~4wvR9@V!H*KY|l$PYV*%qmD=V#*S^*zIK6w2F+|^`~8Rymxg5SzxdjzZO21JqmSfS6i@51iIeG}+M?vJ zSwWQQ?We8gO4^<}lj>ynTwFYEX+)-v?)=^KNo?YCr1yEv%FFq1>S4&0nl;LK{fV=G z_x)_t$+o2S#?^Vof3$IO+Z^q+(@K0iYpZwmIUSZ|s&4x|JRgajFO$6Uhjr}TW!7Sj zw^Tc=wWq6vr^Vy$gk7#cVFQlx9 z>pZcS)&5ba<%t(ISuU~W{60rFngH9JJ%L?!mu53C-e>CJof}c@qst|FFL1dCSHHtq zbRu27cKPJ^x}6RE{h1ew<%Yff*s|tPl&;O&GLt7`%yFsW(S2f;v5JmQnuOalnd!Sv zzZD!+TyJSHZf!k>#p|5JBf64y(OtKCVE;Pq-(#yw3$&dTl@`f<4wA6vy?kDMW(o`6 z=fg`_9~!LW3B7)-(PA|0+yooMj>rVdF#vZay!`YJD`!347ANq6sxi`A;8G9b(ToY?cZjdS4 zFT&#bU@HjLwLSqE>&x|=-ka9WB6)IoD|VWj>Q?kwKU)}7)HV>gquK9sDzoUr(4}v? zij_Wjj_Kb>+`eAG{?S^uc^B`Vlx#ioZblyS$ut2&C34e?#9M)#U1h7!``tO8!dO19 z^gefyd4bc`Ezv?UyRPqiyY|iNU`O9Tk9>}B`g(tH26va=5tp>MJaVHrfgaNn&W+f^sSF~nsc@}99|%<^teS>i~Py0L3V$T z$*RKcW0C_-%syu$3on;yGux~1`fMJ0Dy^dyb7yh-`UQIzUQY6JidrLO|8btAVESEQ zrMEzd_8%Dk&Cw|_P?AIY&Eb{twKnsQzr3e@`Hyj4XThho7j|tua)4#w{MwSUS9@wF zjrz;YKC86_moBOVT`{AfD*us^YbSeMi#QKGOc=Fir>kG6VNl>}%b; zNoVD*hx_zrKg_p|D-(a9hkBO@y`G>#_L}?2`Hx%=>eLRq)1Q`E5T~)1ng@9RN^lGhTqd9+-8 zmMwNRJMoS8sRN$J!%N@qR+f4#x_97h(JEQt&@stE>?+r69>*Wn`T1!=byk+e3y2$>nOzTL( zEjhh=Tlf4fke623o0LO_nn7=oP49}VPn;slj7KbyjVc_t=uAf$?KlrSq8YiJbMCsM z8>-^<(#Q3OZ`AHLAT=6mOF+lEoXXOz2RsBrYQpw&d)2h7FX>+-b?uH3*W+WXl}C$@ zx_dR;D~^zmzMidUeEV1)Bj1A|15Y7a=HGhhm=K}+jH)Xl5?|+`; z)!3JKL_qM(J9cT~ee!by)er9=r#&N&?J>pgpsLEOo^R&i&Pvj{z}>KBrnGY?>o&XB z7eBK+I&g{Jvc`X-zvkPV$_4#bC|ZZ#Y-cM^=$ZVuv4@UX@Zv?+D;c-5miN?aUzO;t zzf3tCw|lpS^v$Jfo)s8Jpa9#2p3Ya7-j9=Lnq1{F3#nS^%d*Xj0j79lB~ivIoqu5 zXr$OV-oA?;S0$$@*B-H18~h>j7WZk5mFy7<6j*DWX5MgKJ809KVqZ7WyvaJT_!diA z#DgMlQsM1%LCtvEu&%<_Ako1(G;sfX{_jfMA-u!U;_tyZU+b=F*M2UKHuFkz#sseY zFH%f6Z{k0bRLRs0avENpOy+wcuYYnA>C(1v`B@{9_l@o{M^2bLJ2p`${(e^V6I0Jc zA#-b^!IHcC!M(mxSsyEJx1i$364Gz@7xk{NZ#qM-c#eg=XNa9~(cTYU4oA5+&e^-D zVb*htKetKv@RuHZEynTtg@Tw3wuS5pL#;ev79_b;)icA-Y`jw#9y&2;JZe~Kv`t1} z{ckJJ3Cyy1H_uUB$60fvaKQbtjGWLO3nexi?uSx$-$x|=zAVP9C5BRd@qqjp-OiBZ zr+Mm_V^dEm?yzqdZ<#rFOiL=ESh031exrlg_*_@OcE0CYm-WPX!F$xA%&*={pF z{`!1>k;FvyUb?`^TJhLEEuq7MbH;S7`44nHb7$79jB7l0Q=-jBdK%Pbf~5_8DkR(z}{u@k^XJ zy{GQU(VK$n&s~aNvSscPpEI-Df4h*jV&V92_m8Ytc(kfHz*?D|OH_jWrg5`0Ka=`> z#dSC6Io4F%^F868IQyZE`;E%;cQGx@QVXz-ax3JR(INIi?IOMX!Bz7a94Au)*Vs@5yLtjo%8xqiijX<; z;pA=|v2|S52bb@O9XqesYQOGA{VVT6%PaKVvXV_Twp%=hpF!`0_3A9H!^d3rOzgF; zuNC8sT#XwZukL#;S3aowbatcUeUtJ+X8)}(J%#IEn9M4$mr~dg|0IVlrYZ7v472Nt zj1aMC z&)uYQQohz>-rcvCReaR$Ot$1Xd#KhuJ6OFqd}7ZnCA*&Q?~Dv97%A$i z@}CsvkG(6eP-J<7{>)geKmLQ6H|gikj?d>h&^3`3^(ms~UN88#YH9A1=FJ-&4&CV8 zA>6I)J+kt#!H4o8qltu*_L^!E&X0sWHfzO+wXI^cS+@~dY=^5AcCGLj>ne$PIy`VX zp-3*eWVw>@$CP+}h2b?KZ6=)OFVAUSl(j%-aO3$Ce`uXgZWwwK{OHxQy<7)cm&csf zwf8LeINwA`H#U5YW;*u*{49l{yV9NVr~7$bz33Me_;6h)s^nY5`F!D_#;rxSexLZr z)nR-u@}{YrI`{oli%s}xcM>VlcCr1i#&p>&dCT@ zd!8Rr4vkc24!-ewb-~M)buXjcmn$hM3@~OTy)BO#R6P6crNp+~8V$}j#MYN4Y(>jouy6>D<1tRs&~C;$*_lD>8qxbzRIU&I%il} z7Ktb|c2&o`2nA!`Q@d^&t>mbRv`FTA$M!T-Y_;s$6-!#W)3_d&hCL${G~<@$OT5R- z)X&l_9FTNg>moI)f014-CFxJ0XM2}#yfjm9iT3Ql3c0f6K2MYWjS3i?RqQA0Rq{vW zJm`-Q8?$_UTd42mBHL!x4X2KEhs1P-RLS?3s5()s7aSS6e`+zGnD@PW^JIt4g+Z>5 zrSmQtdN(fPERt%QIhVx2S-x}A+>h#^3kvy;G?>j6G;*`B?Hf9=@ZGwD&&F>@Pxy*v zaMPL04c^C^ofH^gxt&K@qQ%h3@jC01fJ2%R#ujT=dKimtcG7q&5pHZGd$)ecLd=bQ zF8X_&QJ%v~9;54*m<#>iR!H4^E+JjZieH!+jn^=~DaF^(qP#BptZ!RLY)Mg-d|glG zCr^_Y=!zZScvs=EJyztN!Rv3=l^VU;J@@#nyIMOcmT$lC zYFl8`mB(!MO2@U%J~3LZlysA;CDyiUZWhz>m>28GB7XAMmmL(cFiN}|8!XEICXRE< zsxHPMK8f7{`()HKHqW>BT%Db9Q6~_6^sCpW8&(^6+FDurv?6`dl`_|bzyE^}mNs&Q?e?O{qD;QkU5sx9^VhDmHZ<{DKKHfw zv)L6^heWlu8hp6cQC@f;S|?+x_OcxZm0ys}_|L6fkjKq&I$y^8{_D=D;$g{_uyp&j z_fADmmJUyn8Fy$ogsmKz8-ib9bq%2$%9B|qB?s(S`RHo`p8DL03sNHWu690o z{=u%fMa*xxUHm0q=tVwyk+s-e2PU=+iG%jK=oLj$6REqEeBTd+cVB!fK9&$?PkwuD za9nwp`rNj@z*)B_%hi&$UstKBFjy&ZO=PR?u5Fzv!WT3t5z96zZk!>w&EVFxBdlkZ zEPLv3Xs5aK&43FE3ygdhy)X587J2U;f1F;jWb}OZD|hzn9*jDq{Q9P7a^N*`8e{o7 z_AAFNFWTR^UZJh(n}nQ2%4Vi%cv!AExa*{_#hQ`))HRmQ_d$%w;-b;4ULVonR| zJLW(8<{q-sjC(l0)4yM6yT<*4{N?5o&8m#KDOtMXQwm^g}C31IAq3dSiM$U?tRzw`MN9y4U6`yKNmixb?rCIm^^*t zdYq753qJS>u=tuy}2a*w?HnTYg;5LFD!JW5Ge2?1#&cv=dc)x>&m>o8t#F#7JV%mi&w`r% zwk=O$6!Ij0AK-Ci8PJ=c92`$%bVL`*Kq|xAmz2upEX8d@6W+5zR(BrkI42=Vc9%*R zGB_4dH$1{*6?te!CEeR*XP(q2^$XA1u%_HlW>)`gkfdI$gn> zrG4YU3!P`hu7)Z(zHMt5d|n!f#dB7bi=5j`4zLi|96~v>N@=X~Szlmoymi(pHYeYG zNu7azWIG3JohwLMbk}#*(b#q56Jh($9BgOeq)-~2JHk479HPb|4&RFm&|49odAY)y zRjkTy9KQzY17laZQq~DZmt>XieTZKJRrte*MSgIdUZ?KuTN#zf(i|ns51U=vgnAs8 zj|CpSw)1f=W9E6O0DViH`O+p8@8i<)82n{cyB{4I$>ZL!ZMmS;PJzoL29_E0))$VR zR4j_td3NZ;+iHGLlxtdB*2tOM)Avv`#WYb%O2q1PsCW3$>j%je2Rz*@#MpOoog=A* z{7zr%FgND&!QX}xi_ei(Eq)|_Vg98#I?9R5w|o-TF%Iz2F;vcV5({W7-F`dQ>GdPV zn3#~Np@uVAr&4?ao$p-HUerEJ4tUuH2TM)vFS!(7 zzh`r$lGV)Y{Cl@9ZYlnaue;{X>bKIvYw~9b9VwMRV|#mDeC9^ijdaPMF7}()6-i__ ztxR^~jJ&wWH)S$6uS8&@;`p|~27zI@ipaIIyXwcDL_Wx&FOSFnY_{&?8>gmtWAn=` z{Ub{rcgkk(Cwt`855K&|!_>F<74Y6x45T zeJWwaco)dZk5x@0qkzO!meGuyrxGfd-l=z=Gm)O*BqK}Gk=WK%~pAa z`Q_|$zQO!L>(^MP7Kdd^buX@bzxV$B5KD9N&eqMHg|}@|tDl_6nVIywb?L%VyE^t_ z0nV9WiZ#ET%}nq=$5Pm`V8^^8haS!!`Ml3@qbk$Z?CJ?Fi4M`^Kjy9l*Q1}jQu1V? zH1in#7+U@O(oW@w-zD8b7p&GlcxhQ_=;==JU9JnOE0|+VLjqQ8Ac>XgDZch_J$0w3 zZ?O4R#pGaelh1zNN4j)NH4bsi^wVVzWl-MWH!PT#f4z=XQ#e6}lZ%7HU3uNU_3IDC z-&auiETAMyH?UIT=>e%ALUT9bUit*3K3*XJj6XKk$dhnjcZ>t;= z5`W*>YsR3FsKz82asN@+wMW_oYZXK0?_E3N${sEC1uR$NLU^P_4?8Z{vRdsx>#hoN zo&QP6#moBNe@t%j6A|gZwkYHD+KDqa>lCgWo}%6pac>a|~D$8b6m$9!|ki)xJ z#kqNjqQco5)=X<{w<*5f{-U>NtB;(h?4;$Q4)JIfe$$$Ro6eu+Z62b$@pE7ZyDeAK za97e%QSzTH%RI#Xef9lu==Y;EXU(Y_S`H{sbzhlSC(0Q9?FBcr%_{R>WB`F$- zydeq9QcH!B*xc_4-r+Fk*LxlBZ@-4&?S0+qYKGevH(oCG zO~};VAah}s%1N7t%Ub*BGL+Qk)jQuiqh&6$Apes@FZ%}*e~sPBEf=;wv0J(BbV%#d z*M%~(HYm7@Y9ubbzVxwxLQvtyJPU6<I?KvSv-nn6s|)lz(B^qM9w(o3r!r*zJnM?kjW_**Tm(ZmEH-|{ zCcO55=;jR<`8HZzypea^>HtUmu3m}lP1VC!HI}VXT4t0Ux@_NA-0Qe^&(|!w%w*@i zs#I>nn_0F;cDcqIAF((d6dA3)zFaEyv5b6UeSvy)mfnVUq_T>YhdlP4(N=#iE_wpT zJLIxV4zfVUMZaU#_I0(PFVwdZI-L8bL%j5|$HV&u zFGD7s;7N#QAw|KVu(@EVVp; zUh%BZ>}^X#pI`qYch9FMD}I|RYNe2+c4+&pg?kP^pbHS%UMR6i<6fBn-^&@vkGq$t zu0C{F+J}^GB!4>P> z36us&-jn4;_pkeg9Fp)GGgW{832eQZ={o%;#QHy4pQao66nfTK+K*FP1+okN56F1>BIdcmT2gIzoN)vnmwW_xF(O|e#0TgZGXZcUWK&R4rT z)~~$fH%O{XDHeESw{P-k@8i?{Z)64;iY529_K!%gT&H6{VL@&=!_0Sm^BH|rs}v5B z&2L853+;I4Xx)&eJH3oSy>X9ep1KFiLp{}vkf+@uJ&1#7Ws^;zQj>8}*7;?(ovv=` z?24Dl*)}29<^FIYQta{^iB%nA=Qji?w$?4`TEEu3&^PL>wa)E~whC|Mor|PH<;A3H zOIzjA1@kCROXqL%yr99TI#2aUpOMy4k=L9n9xgh;mZH=V)h*+Q3*;Ex4&f9P!#!EHEnm!VS`$GiA0Un7gwbZ3PP3mWqJ_QuL}WUY!(a0|UyS(M{8-k2Y* z?t6YhtJWd*CYLlFJRZwQS1f)N<~u?6Od37d^Q}YX!D=oKCaGH0vF=+1|xAsvHh5qOKEUhB)EVpm!P4sx@ zEW4dS?;ag)(LdBK`OqfncyOrq3x{mqyy!=l=iCv9T=Ve!!_GIsI$8U6*!v2!wk|b) z!1L#*9Aiw)D@GA1crI|U zwfTb`H8M+|Rrwz9HmDZn7&4B0Th!&&thUt3WX6XVE8h+teZ73{e(QBi8o{=t!#0_m z1`w_6=*KAJ)bQxBLE;U$%%wZ7&Cs2_T+Lk8;1lj}`{eE8tH(WZ=7v%1$J5H}Ys(_9 z@fRs@n!1`klG1_Eqq1`!k~1Ugd%{!~H0K zjoZwAZDq}w^ZB&nZF!P>BT6D2j-J8-6v1wP+ zqFx>z9%bY|)nlGwbFg2EJqXGt=RzRvsC~jEMu*4s%Pg0Cm<3eaw$ssV#@_%82s4OV zbc+|yok=~xKf4ePAqXJQQ=i0>|AQl&6g)R2(EdnXjJHZ&lzT{;pG8h)usx8R^&raj z1H?LLQ_thwj3L-UJtxRg!#&#FOeHbU`8>(je(wJPN&i@7gr_ZiYN*HFNGHRO5%zi& z5q3Ib2_9yU7v%*t88OgWk_N4%6zHhTf$o}oXf4ZtO1w@9bB7pLQ}8#_058M$6F#4n zD}rrxKBk7c?Tz%Xp#Mk2|Bnw8k>lyhGvXK{oD72kEIy1zxtc>MIT{9K95k8CsNm2hN?Z{0E zTN&+UYK7l$n#_z2g0jqHXs#@P&cMBI~&TW?-J)F=?Rb; z<^$fQ8k0e`x>hNXzAOJ9S^eGX@qYFfgKa-m=BLC!2_*?~;zOagqlF3s-R&^k*F`<= zYHfu73Pe4bv4IFdkd+Vx=`kVTWvo^i?P+=OJ0kuEKRRnGXGFQ1OU3)yj;19c2%PDW zUXuh3p8AUaX-o_c4=}`f+nQ&Q0w?m4!@uGnWMzuylQ7g?jdV{!URD)oYb63Fw;wQF z^ni00JmEZ(4}vch&f)nvCQmqf-W{&r^a5ewP;jzKfs&j8Xltm(c6UH!KKUz->FvNV z2ib8!6Q;6HUj7&Mhd3CCrG9&w(g~44UN?iZbQCaM@Hi{x?T=!IdU&r_4+?s9KLB3WuLHSH^&s)S8h9S(!7q$0N1_CziLBqX5tzjGtH{nvSO&O zD1y4Od@3~Jd3${g)Rfi3OR*@pb|VUIvSuRPRUoTP(2Jn^rTmU|T3e>tMQz)c=OmSD zfRi_u+8>v%cz~Lm6NI_Bz-V6&v^UgXpAfhUs8C;Ch`5Wu(^#d-+f04w-?bsa)zpd{ z83-LsH8|HaeuajLVn~T4!+maFq&)#RcuGJ@wRVcf1U>%-Xl=x2r~0TK#M2$5q?t*yaFX4E8hT4 z775^QX9peC6cj_GY^tSF!lbuzkBYByot*L2FeRq#%v{);gZKl!UKyYFXSjMJ8SZeFgOtiNzUwvoJGuEgx@mnv?Z+veJQYWIdRhWXN`+vkri1f; zFx2IyK}SsmjCQtAX)8=2ft$YKXiB92URoan+3FdE*cm}naXw6RwZl+L0~931f~T1U zu-=J*+iWH9O!|ww|0oB)qVM0_n?}E^PCf7lRDs~*EYMU90S_B%Xux%>sVD~qk*5B} zI;bnifgl@w@c68vPS9VJl`_lQM6EK;(++jrO2EY*daxvU+JLNtGtM)4C^yw0hjss* z%o{tlfLCbeU%)M}1MIxpK;O0*6!m}6U(?#~Qm!8Eux9`dZ#Y=!8$n8lC)8)g!zhkv z8g0q`F5qpVURjVuo|WM5cqGVL2PhFi(1kMJi?o+hQX$ga892F8frY&iUc4rFkM#cy zKM5LpddFdMa`G#Tj7|Unv}@gXpOo4Q>c)+KTMvPQ;M3iEC2;X_AiR5J240r>P?MQ} zwnQ0~{=uet$VWXd*!mNsgn1qbveT1Gj|zlhaxxJ2`f#2vLHfO2Qc-S7fsMQ7+kEpk z^b_s!i|G1FD?ziaRWp@NE%PRbP3eX4@u{|TbdQ0dUCYng@TDJw#B1R4wK(9qYYXOT zZ=e))-s;>eDt$ydYVf=$H5TH%tmOPHwVbMPUMi!Isq)i`YgZ@gCAy!Gb}n2iAN@PI z_XzIzDgCrQi%jhKdcVDM3{;K&+7Gm~o0unVvgDv%;s)B%Vt_INEjafObXR6ksI<0J zmqN6wv6HWvW^!_PC=?_oKz%_j^_lvTA`liS2d)P-@Z?qP*Y$=*%g@SxqF==j$KT*L z84HW+{!1Uw)-_^HXX7q|3(S6?BJ}|RalBUMPw|+L69Up>qaobUFgMcKWZcir2C_)e zRN9F)rbWlYGm$3X=BFe_Lt|r;pkabC^g}(gIgalMF$PE=`rHi)QFl!8bEL{Q z!CykgL!BJK&-^1qI2lpz5p5#cN8F3^a)S42gTVcu7TE9A0N2A>)PHMnEYy7k-p92d zfa|3o6>7oM8f}AV^Us_2jUXse2aiOj;4zlAPT!9aIn^ed+v>gp(RXzq{I(9*@7JKd zk_e*0e$ZA`3JJdUFw)vYrI9G(d^{n++X^TlPLLDjOPzNJ+KDwF%GDNBGzWm2uNGME z*8D5b(QW&V{wFUQ{_@^ulke$&`Ks|R&(QF(AYMY>l9UPu7#oF1R}1R=Nze#`eGudA z0ZG0#kR9$0733)DHDYce=FkuabI{c3hX(?6)cWsm)WSajLI3pQXY^ZIqyJ=DABnvD zXZq#jNz`int@OXrNcd@jogAqA53w~IFHQ`_XU3toz5>^Y5(uy{1`~^Zc=YUlm;RvO z-mmnJj7$R0!>RgdJpWp95Pe<^SFa_(=g(92o*%Ab;~lNkF$#U%;AUnDah?_s?P8pq zM+!vxC!xQ!7K^|AvS+cprFo|1uo;yrQypZHHaQ{OQ9mHv{_;lGugsdiLT*Rasw z5*X}mg)nDxDs2M-M`J4GP$I0?t@AjAcFKzVK|ig@o=8vSexATz>Ut~e$9NQ9#S+F2>khqfBN zfY0?~f7yVWTN6mhpbSyvvF2~b@B{ujNKBgYWzm`t9?=H@LA{V)Fa#45Q@YRa@C5ky z_5jDdU(-&s=LSnQ`UwhPxTg(Jzeg8SH;fNm{>=(^0e`ndFtuofd%RQl{*M2KpW7ijXXvMpo-qjFk$qrl-T{xE)c;au zX#GIwyexN8AuF{MiqQv@ALB)3%TQk%jA9!K%%Q$X;O5>oHJAQh z(f?IGkw2W(aF;U!yllN7CCD9h{V?R`D9U|1)h|?qGzMB|juxjyf3+W5D)Z=*{A~ls zVZP9XcG^&H7ZtkD7ETEA15!*Km|L}e8O#5?meKm+-}0SUYl*()KwX9PZW-unhC!Ua zJCMWu(HB&W|IfG`I$O}UjX*(LCC$?X6QltQRE( zkdvAT2?-rwXxsw#Q5T|(XBvG}{9on{8tp_$yZ?_R($2+$^xv;Wxk-lj058Z*j)Q8% z-PwY^pfAvfHb9iC*;s0r=YE3b9}jO+HQju20<{UImqiy*k&HsgdLS7y} zuY>1e^&l&QeHi*(KZLPx?MrQ})=XF7JOeg3Wwou148&?gmpuR$rBU(w78{{tw(KocU3D56hy9wP& z`dt&emaT`+x`~jT5Ca2U%|PIw`E3cmaZO{PMvFM^kT_|a|##Q68u7SAb~oS zl6n)UX*HvbT?k=bkr*?}#rdTP3e)1g(oVF2m~%So%b+MZbj(%zHP5eTo_=q5pdaHG zHs)EeeiNmciQm;p)LW4n3AM!;I3J@-R<=P#MkkO+UEm+s4)%_%)N!u$sTnl2o8g0Y z3w+XV!E3FkkF>9Op#jL+)RBL(om|ouEA@&VR&S^Od-*n#6Z=<#b;E>b$L{ zYDTQ5wG_$QX1uyE3-Y49{?Zq;wosx1ATKo@s*2EWUtWU#`(kQbr563cwdKW7S5XR8 zXrJb#CP18@%U|lD(M`nF2wVw%4&#p6GD5$i@88}_339p^?x0_p850cY5q^*v?gb?Y zA%EK^v^M>ll16u|hc%>!`(bQ03_>tgn;hu){~SM^-oD(V@Rd;*zeaszG9}m(^5P?~ zf5WMLP0;XfX#MdS;yprN$-uZoT9`M|tvgBbw6Mw~1^=(cuW9WlOefJ7r^Pb*o2fdJ z+)PK416t}y*iYm5=sj7-Q)mQ2({B4CF;y1 z1v2KR#Qu+DokruoDI?u2>5~GTsQDYgRv#;nZxb=@Rw!EmP)Lr4%G?Z`Q}Qr=Qb>i` zqCD!gLX`dV$N-2zSqZe#nFzAdszAB?m>%JU`5R{c=XC$9ZJ38LHznBRe1N5x*KPMEzuL^&BkguN~mqMQsM4)aq2Ei`icOjX^9XVbzw&ZmZX{BkY*8NMH{0T4Mv z(rhq{U)&(dYC5_(L`kBfV<1W;%pbyXl6X;3nhih9K}UC9nhhWSR&J7J>n46Ll4h$W z$~oUk67icsnoWr)>Hk_1m+9!F+5Z13l?cQ?p^HRZN4l$ta$0+6?WDFJ+fCyGjW1L_ z!8g8r0{-;D>PSesrTRn#u^hxC;L_lkGA=REF zY|3uTJ!-1Rqh2G<`_Qf*?`=jGL=XCk`e6dk>k27AiS$JuwV6X&q|e{RzJEqvjECjX zq#);-3{n_G;rv9*_eB0jNlG}zcMG7Wxdu8gPTh?*UmxZs5Ha5V);j2GEQ7X^DZd*s z1~MakaK6PHr%?AA)N79Z4A+m>FxTo#esXAU9Qt@^>kfgx0rfTv20=k?JJ{Idz&qJ! z%;SgvIk^}xGff9d+LRBBz>7goYBBX^64F9kFwPLrYp*HwOB&*Q?GBfw#|+^dMO_~W z{K>(tP+e95+8^WK#w~xif;kNA_sPKfBpV(+&xHq1vha5bT)rL#w^;l^PbV1~D(a}H z`)Uim(m{#vhKy*RHe2wauA@wj{fmV z%$vY`kMD9Nrhd!np#S_$IqKjkaGxg%T&!YIM2Y;lF9-S+h`N&kohy@qoczKk%qk~q` zXra-jWY`3<8eQ=8MJaq#@_ zi2*d`VSZ>u2~=iNa9y?-%}$P5OAc~;QHk~!5eFh-iH@ILFyE;NMBh!t52v@w%()fX zyT+ime;j)H#-Rhxo7+YqyKn$(J=>_VL3^IoCsImH@PIE1KB*W&NfOQ<80#S7O}Vkb zKn`+xQJ5I)NyPSv7-m5#k^5GH_B|1|C*+!lm3_~5ayI6J;!#;QOuhFBp&~OKiV$~Ac0v(B6M?@RdGJcA0r;Ly#od2~ zKRFZgQ>Wo4@O?0Cf>Dgi5iu4E*Vbt?OvU>6pH%_RJwG4^IAH&mf8{}0T1e0#P0= zP!Q`!jWtnYX&&ZK7~@TSkH}HT4);OdLJx59p?~CMEyj>>EF(OVB<7YWh)I}ge`&=q zh+w=3$vJobZhkM_&HWclW~3Z%!P=B~$SgE}n0GIKr=T z@p2T@R5U^+=6@1xCGZDXYD21@9rZn2T#)~+U}QRm_5KwvjgG&=PsA38gMxl<+OxEh zXvei1F&KX8#n^{6wiV|h1aD(CNbs_lY7oAg8{-Q$cAe-;nWCNc{`B%^__=s+?d_YO z;EXYFdze%yVQ^Qs-9E1r~q9}72s$~!5I9MzkWJi+WC+8 z*|}<|etx3T#->rY&sX;s{I}W5L02aqYKk&ZSE#1qC-R}a&9yu;!dzd}<|a(hg!!<} z##ZoAxB06tiH4UbUx;FU6~@wtqZjj9(kO$_);0!1LlY1a+YbUln1h4Q(SYVVyUCgl zDGBu$J0{{~QwRF%Ak;zsMO$^j#w0H@Oh8BejSXPljvIKnm%x)3e~n=hZ6ji*(}9RL z5j>#bq?I(>L_AVJAO&@?V91W~n?gR;556WUqv=t8R6Ugv;^Nnd{yV~l(cRhr(S9Ld zYu^H#D8sb+{!2;4O_kv(zqqxbKahN!s5%>gqbffWf^BuF>kqL87kQNn!{+&FkKfAlF8IpoL zCU6hMF#nP%XTBLxDof zNosAV|LT)&#hgTULnUn*URqh1oxC(F#;39ebv{DZC14QaHcj>Y5ERl4Qg5-J3BNPZ z{^@}2r2Qshu7t1i)$4jN)FGokDhJvyHvY{Y-h};No$F<+JfDVldYS0&aJV2Tbf_df zo{FE~1>raDY-xeK+)j)Ec7XbaCJ=sE54?hPRK5@~L?QHL6ZENSHi3ab3B-k^qOY$E z@{^;e?-O-o$A<$s%)QN0@ddHP=5LR1C!;gPso}jjD60ey1~50cs}0wEBA!rJ4`s!z zkeb{GVWCan>)QZco^{~uSpi`|#gI+Tr{XOlM^I&%8qdPGXgccClt|AeOC{l7>fbb? z68#*GqHm*yjJ~BG_b3o_WRSvvh<6laq);Ir^Dl{O1f9h51l`nlEb4o?aUoRu!|ucD zeYE=jO<9;6xirqp(jm#;3CNiHN!0sKK#Z-aHcvuvax}(?y@{BULq@dUU-a#NLj&E2;}H55v!CGT7cIG|buf zAMte6RnbSeTZmDj1BUYAL%yt-Xim1(U^)T%8HUi$K)^sJ^fq9ADB5jA>;U&L;9iJ; zp?F_AvHGf#pY|E#63GB5FCVam?{NiWz#`LB@0|#tDw4q zuwh4`p^!W^wh&h?DFE}TjOBjD7~H=iT%DhW?@UtZ?r9wWBcp0~Dq03o?;Ak&1LoIZ z&Xn9ow9k|<1}I(%uOumu98*HYLwyPVROhAPo-DnG({aT6JM1sZN**F?WP+xGtQHU! zEd^=i7Em&1`pzb%**~fnKT`aJcHpZjur*7eRZlI8(&LA`OjP#JaFD!hLz;0M_oEI# zj>(3{Ps-rEPA3rdEX@{C(EVl)P3iX-SHt_7W<4OQ*aHTd{xFUQy)&x1$~FWEPEkG%Be1n^d}yW*y5W$Sod(g0ex#!F7?dYPsbrH(*$BKTp=UE7wYn|pg09{DST|ztFjVP2s^D2{rxH`wYXR3n|(^-Ng>uv z*kD9{qygq`6ZUCo)zJ4iKD7Y{XB;GAE;f-9Ne&B!>g=QxN<=_6Q9qHR$}3O_(kkEV zE*ekrOTX1m(Cm*fP~vb2==frD)q^_b3Uc!nV4j%+)utr!{&GoS{c&E7K;)kh^$TD= z3}NFDwi5wFuB*6wJ!Iui`D@;(qs^{R54z?=UJgJ^QZMcysHcLgRtx3_R)Y2C0ID5L z*o|S17MPQ22EDbYw?#*Qu=vmO`;wBU@?eSlIYLj9dfPvq=v0AA*X-RSHClD`k;)qK-=Xu1zkPOqQ!ZY}8QPvwT%+7mVj@y?WPc>7L1 zgolu+`OHKgSZk~Hds=+L!7&JBdFi$OQWQc9!?qPyQ_jRjCl{W)IvjP?xeSg zD&O?FiF3>WpwEf*)fj85B8Cq2D5JzcZACp~P+GyyuL!$t2_%?mChox9~S_}~cpdLT!sWjg;QPOnMI1fum33eMo z-`@*bUB4=0JS{Od$t*M}z;!Yg_g<7{lE2eIi8Z$XV}rQ~(U2PKF`4LV7aHed`;Y7U zk2qsJ%=d>o8fjt7J}o)Ot&be$h4Z2p?muwu3w8LM5@@ZXg}Iu)tap-5k!hH26H_(a z93~PK7?_mk=&6ACnEnmWo+r^UQ0u6sTSTpssQWppW}C5+sqY5N!n41|n-=4>%?STR zPYZYY%oyuwX`3DESDzOj2zd#C7}xfyjdr)N$9A8>>VA48`q?kYPYiX=jtQXJ8-&e4 z=>JsPgYdPNU@SK~5sFeGoUu<9Os^!y%X&d^Y6Lmi*P8mgr)xUASEAs&os7048O$-y zq_(V)Dp$FY?zn#VCpv3O&!N?kpB(AjkLzy%B_G5jC?F38k1}A+hQTmszITOw)FbK&vnIox zjZemV+u3KwMWcT{4*h&neoD2^Q?yQv1o*l?LCdlm6xG_GG%XeRQGn~Xy=^urtU4nm z65h(Te$fx6^cmt^pYTqw#2hc;AoeQ}x`Ptt!}~eKQvIWaNzpZlejd~{^r=`gyi!E} zqEbC|ttQ@a^X~*{)u}j;lTQc8XyTfw)B+z=BB?%Cl9vmPKOgFzjmOWw_i+*L8(=;w zF<(;8G0&OE6(-h06Jw0YqklNk%^qs<$koK2mDg_zsdFK1ex%k)hb#d~Oi)dFs0$`U4}+s6`uK5vBi_HqI~6aYBE~=Bl1*RUtpRq7f6J=FEo2>K;zON!yMG5Wh`^Cfld_~tJn=4rwoVT8+SGv?;km*zvDtu9rbyK9Ra zVPpt%?OMRj;fsF-pZ_+u*Pwr)7A(!mpda_o_jR-pdz>w3@|PX$v!J;+om>n4nt1$3X>BNDamw?QvfF%lPeH z + + + + + @@ -106,10 +111,12 @@ + - - + + + diff --git a/packages/Delphi_XE3/JPLib.dpk b/packages/Delphi_XE3/JPLib.dpk index e8d24aa..1bf5ab0 100644 --- a/packages/Delphi_XE3/JPLib.dpk +++ b/packages/Delphi_XE3/JPLib.dpk @@ -39,10 +39,6 @@ requires contains // BASE - {$IFDEF FPC} - JPL.FileSearcher in '..\..\Base\JPL.FileSearcher.pas', - JPL.JsonHelpers in '..\..\Base\JPL.JsonHelpers.pas', - {$ENDIF} JPL.CmdLineParser in '..\..\Base\JPL.CmdLineParser.pas', JPL.Console.ColorParser in '..\..\Base\JPL.Console.ColorParser.pas', JPL.Console in '..\..\Base\JPL.Console.pas', @@ -52,11 +48,16 @@ contains JPL.Dialogs in '..\..\Base\JPL.Dialogs.pas', JPL.Files in '..\..\Base\JPL.Files.pas', JPL.FileSearch in '..\..\Base\JPL.FileSearch.pas', + JPL.IniFile in '..\..\Base\JPL.IniFile.pas', + JPL.LangMgr in '..\..\Base\JPL.LangMgr.pas', JPL.Language in '..\..\Base\JPL.Language.pas', JPL.Math in '..\..\Base\JPL.Math.pas', + JPL.MemIniFile in '..\..\Base\JPL.MemIniFile.pas', + JPL.RTTI in '..\..\Base\JPL.RTTI.pas', JPL.StrHash in '..\..\Base\JPL.StrHash.pas', JPL.Strings in '..\..\Base\JPL.Strings.pas', JPL.Strings.Ext in '..\..\Base\JPL.Strings.Ext.pas', + JPL.Units in '..\..\Base\JPL.Units.pas', JPL.Utils in '..\..\Base\JPL.Utils.pas', JPL.Win.Dialogs in '..\..\Base\JPL.Win.Dialogs.pas', JPL.Win.FileSystem in '..\..\Base\JPL.Win.FileSystem.pas', @@ -77,12 +78,15 @@ contains JPL.UPX in '..\..\Binary\JPL.UPX.pas', // Containers + JPL.Win.FileIcons in '..\..\Containers\JPL.Win.FileIcons.pas', JPL.StrList in '..\..\Containers\JPL.StrList.pas', // Graphics - JPL.Colors in '..\..\Graphics\JPL.Colors.pas', - JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', JPL.ColorArrays in '..\..\Graphics\JPL.ColorArrays.pas', + JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', + JPL.Colors.List in '..\..\Graphics\JPL.Colors.List.pas', + JPL.Colors in '..\..\Graphics\JPL.Colors.pas', + // Logging JPL.SimpleLogger in '..\..\Logging\JPL.SimpleLogger.pas', diff --git a/packages/Delphi_XE3/JPLib.dproj b/packages/Delphi_XE3/JPLib.dproj index f2e4775..61b03a1 100644 --- a/packages/Delphi_XE3/JPLib.dproj +++ b/packages/Delphi_XE3/JPLib.dproj @@ -104,11 +104,16 @@ + + + + + @@ -125,10 +130,12 @@ + - - + + + diff --git a/packages/Delphi_XE4/JPLib.dpk b/packages/Delphi_XE4/JPLib.dpk index b08a290..0fb076e 100644 --- a/packages/Delphi_XE4/JPLib.dpk +++ b/packages/Delphi_XE4/JPLib.dpk @@ -39,10 +39,6 @@ requires contains // BASE - {$IFDEF FPC} - JPL.FileSearcher in '..\..\Base\JPL.FileSearcher.pas', - JPL.JsonHelpers in '..\..\Base\JPL.JsonHelpers.pas', - {$ENDIF} JPL.CmdLineParser in '..\..\Base\JPL.CmdLineParser.pas', JPL.Console.ColorParser in '..\..\Base\JPL.Console.ColorParser.pas', JPL.Console in '..\..\Base\JPL.Console.pas', @@ -52,11 +48,16 @@ contains JPL.Dialogs in '..\..\Base\JPL.Dialogs.pas', JPL.Files in '..\..\Base\JPL.Files.pas', JPL.FileSearch in '..\..\Base\JPL.FileSearch.pas', + JPL.IniFile in '..\..\Base\JPL.IniFile.pas', + JPL.LangMgr in '..\..\Base\JPL.LangMgr.pas', JPL.Language in '..\..\Base\JPL.Language.pas', JPL.Math in '..\..\Base\JPL.Math.pas', + JPL.MemIniFile in '..\..\Base\JPL.MemIniFile.pas', + JPL.RTTI in '..\..\Base\JPL.RTTI.pas', JPL.StrHash in '..\..\Base\JPL.StrHash.pas', JPL.Strings in '..\..\Base\JPL.Strings.pas', JPL.Strings.Ext in '..\..\Base\JPL.Strings.Ext.pas', + JPL.Units in '..\..\Base\JPL.Units.pas', JPL.Utils in '..\..\Base\JPL.Utils.pas', JPL.Win.Dialogs in '..\..\Base\JPL.Win.Dialogs.pas', JPL.Win.FileSystem in '..\..\Base\JPL.Win.FileSystem.pas', @@ -77,12 +78,15 @@ contains JPL.UPX in '..\..\Binary\JPL.UPX.pas', // Containers + JPL.Win.FileIcons in '..\..\Containers\JPL.Win.FileIcons.pas', JPL.StrList in '..\..\Containers\JPL.StrList.pas', // Graphics - JPL.Colors in '..\..\Graphics\JPL.Colors.pas', - JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', JPL.ColorArrays in '..\..\Graphics\JPL.ColorArrays.pas', + JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', + JPL.Colors.List in '..\..\Graphics\JPL.Colors.List.pas', + JPL.Colors in '..\..\Graphics\JPL.Colors.pas', + // Logging JPL.SimpleLogger in '..\..\Logging\JPL.SimpleLogger.pas', diff --git a/packages/Delphi_XE4/JPLib.dproj b/packages/Delphi_XE4/JPLib.dproj index 2e2a099..7911c5a 100644 --- a/packages/Delphi_XE4/JPLib.dproj +++ b/packages/Delphi_XE4/JPLib.dproj @@ -104,11 +104,16 @@ + + + + + @@ -125,10 +130,12 @@ + - - + + + diff --git a/packages/Delphi_XE5/JPLib.dpk b/packages/Delphi_XE5/JPLib.dpk index 2fff64f..19bc0dc 100644 --- a/packages/Delphi_XE5/JPLib.dpk +++ b/packages/Delphi_XE5/JPLib.dpk @@ -39,10 +39,6 @@ requires contains // BASE - {$IFDEF FPC} - JPL.FileSearcher in '..\..\Base\JPL.FileSearcher.pas', - JPL.JsonHelpers in '..\..\Base\JPL.JsonHelpers.pas', - {$ENDIF} JPL.CmdLineParser in '..\..\Base\JPL.CmdLineParser.pas', JPL.Console.ColorParser in '..\..\Base\JPL.Console.ColorParser.pas', JPL.Console in '..\..\Base\JPL.Console.pas', @@ -52,11 +48,16 @@ contains JPL.Dialogs in '..\..\Base\JPL.Dialogs.pas', JPL.Files in '..\..\Base\JPL.Files.pas', JPL.FileSearch in '..\..\Base\JPL.FileSearch.pas', + JPL.IniFile in '..\..\Base\JPL.IniFile.pas', + JPL.LangMgr in '..\..\Base\JPL.LangMgr.pas', JPL.Language in '..\..\Base\JPL.Language.pas', JPL.Math in '..\..\Base\JPL.Math.pas', + JPL.MemIniFile in '..\..\Base\JPL.MemIniFile.pas', + JPL.RTTI in '..\..\Base\JPL.RTTI.pas', JPL.StrHash in '..\..\Base\JPL.StrHash.pas', JPL.Strings in '..\..\Base\JPL.Strings.pas', JPL.Strings.Ext in '..\..\Base\JPL.Strings.Ext.pas', + JPL.Units in '..\..\Base\JPL.Units.pas', JPL.Utils in '..\..\Base\JPL.Utils.pas', JPL.Win.Dialogs in '..\..\Base\JPL.Win.Dialogs.pas', JPL.Win.FileSystem in '..\..\Base\JPL.Win.FileSystem.pas', @@ -77,12 +78,15 @@ contains JPL.UPX in '..\..\Binary\JPL.UPX.pas', // Containers + JPL.Win.FileIcons in '..\..\Containers\JPL.Win.FileIcons.pas', JPL.StrList in '..\..\Containers\JPL.StrList.pas', // Graphics - JPL.Colors in '..\..\Graphics\JPL.Colors.pas', - JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', JPL.ColorArrays in '..\..\Graphics\JPL.ColorArrays.pas', + JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', + JPL.Colors.List in '..\..\Graphics\JPL.Colors.List.pas', + JPL.Colors in '..\..\Graphics\JPL.Colors.pas', + // Logging JPL.SimpleLogger in '..\..\Logging\JPL.SimpleLogger.pas', diff --git a/packages/Delphi_XE5/JPLib.dproj b/packages/Delphi_XE5/JPLib.dproj index a414879..6ea51b1 100644 --- a/packages/Delphi_XE5/JPLib.dproj +++ b/packages/Delphi_XE5/JPLib.dproj @@ -105,11 +105,16 @@ + + + + + @@ -126,10 +131,12 @@ + - - + + + diff --git a/packages/Delphi_XE6/JPLib.dpk b/packages/Delphi_XE6/JPLib.dpk index dc539dc..db90fb6 100644 --- a/packages/Delphi_XE6/JPLib.dpk +++ b/packages/Delphi_XE6/JPLib.dpk @@ -39,10 +39,6 @@ requires contains // BASE - {$IFDEF FPC} - JPL.FileSearcher in '..\..\Base\JPL.FileSearcher.pas', - JPL.JsonHelpers in '..\..\Base\JPL.JsonHelpers.pas', - {$ENDIF} JPL.CmdLineParser in '..\..\Base\JPL.CmdLineParser.pas', JPL.Console.ColorParser in '..\..\Base\JPL.Console.ColorParser.pas', JPL.Console in '..\..\Base\JPL.Console.pas', @@ -52,11 +48,16 @@ contains JPL.Dialogs in '..\..\Base\JPL.Dialogs.pas', JPL.Files in '..\..\Base\JPL.Files.pas', JPL.FileSearch in '..\..\Base\JPL.FileSearch.pas', + JPL.IniFile in '..\..\Base\JPL.IniFile.pas', + JPL.LangMgr in '..\..\Base\JPL.LangMgr.pas', JPL.Language in '..\..\Base\JPL.Language.pas', JPL.Math in '..\..\Base\JPL.Math.pas', + JPL.MemIniFile in '..\..\Base\JPL.MemIniFile.pas', + JPL.RTTI in '..\..\Base\JPL.RTTI.pas', JPL.StrHash in '..\..\Base\JPL.StrHash.pas', JPL.Strings in '..\..\Base\JPL.Strings.pas', JPL.Strings.Ext in '..\..\Base\JPL.Strings.Ext.pas', + JPL.Units in '..\..\Base\JPL.Units.pas', JPL.Utils in '..\..\Base\JPL.Utils.pas', JPL.Win.Dialogs in '..\..\Base\JPL.Win.Dialogs.pas', JPL.Win.FileSystem in '..\..\Base\JPL.Win.FileSystem.pas', @@ -77,12 +78,15 @@ contains JPL.UPX in '..\..\Binary\JPL.UPX.pas', // Containers + JPL.Win.FileIcons in '..\..\Containers\JPL.Win.FileIcons.pas', JPL.StrList in '..\..\Containers\JPL.StrList.pas', // Graphics - JPL.Colors in '..\..\Graphics\JPL.Colors.pas', - JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', JPL.ColorArrays in '..\..\Graphics\JPL.ColorArrays.pas', + JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', + JPL.Colors.List in '..\..\Graphics\JPL.Colors.List.pas', + JPL.Colors in '..\..\Graphics\JPL.Colors.pas', + // Logging JPL.SimpleLogger in '..\..\Logging\JPL.SimpleLogger.pas', diff --git a/packages/Delphi_XE6/JPLib.dproj b/packages/Delphi_XE6/JPLib.dproj index 0a3ed34..5350b24 100644 --- a/packages/Delphi_XE6/JPLib.dproj +++ b/packages/Delphi_XE6/JPLib.dproj @@ -105,11 +105,16 @@ + + + + + @@ -126,10 +131,12 @@ + - - + + + diff --git a/packages/Delphi_XE7/JPLib.dpk b/packages/Delphi_XE7/JPLib.dpk index 74bbc39..0d4b64d 100644 --- a/packages/Delphi_XE7/JPLib.dpk +++ b/packages/Delphi_XE7/JPLib.dpk @@ -39,10 +39,6 @@ requires contains // BASE - {$IFDEF FPC} - JPL.FileSearcher in '..\..\Base\JPL.FileSearcher.pas', - JPL.JsonHelpers in '..\..\Base\JPL.JsonHelpers.pas', - {$ENDIF} JPL.CmdLineParser in '..\..\Base\JPL.CmdLineParser.pas', JPL.Console.ColorParser in '..\..\Base\JPL.Console.ColorParser.pas', JPL.Console in '..\..\Base\JPL.Console.pas', @@ -52,11 +48,16 @@ contains JPL.Dialogs in '..\..\Base\JPL.Dialogs.pas', JPL.Files in '..\..\Base\JPL.Files.pas', JPL.FileSearch in '..\..\Base\JPL.FileSearch.pas', + JPL.IniFile in '..\..\Base\JPL.IniFile.pas', + JPL.LangMgr in '..\..\Base\JPL.LangMgr.pas', JPL.Language in '..\..\Base\JPL.Language.pas', JPL.Math in '..\..\Base\JPL.Math.pas', + JPL.MemIniFile in '..\..\Base\JPL.MemIniFile.pas', + JPL.RTTI in '..\..\Base\JPL.RTTI.pas', JPL.StrHash in '..\..\Base\JPL.StrHash.pas', JPL.Strings in '..\..\Base\JPL.Strings.pas', JPL.Strings.Ext in '..\..\Base\JPL.Strings.Ext.pas', + JPL.Units in '..\..\Base\JPL.Units.pas', JPL.Utils in '..\..\Base\JPL.Utils.pas', JPL.Win.Dialogs in '..\..\Base\JPL.Win.Dialogs.pas', JPL.Win.FileSystem in '..\..\Base\JPL.Win.FileSystem.pas', @@ -77,12 +78,15 @@ contains JPL.UPX in '..\..\Binary\JPL.UPX.pas', // Containers + JPL.Win.FileIcons in '..\..\Containers\JPL.Win.FileIcons.pas', JPL.StrList in '..\..\Containers\JPL.StrList.pas', // Graphics - JPL.Colors in '..\..\Graphics\JPL.Colors.pas', - JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', JPL.ColorArrays in '..\..\Graphics\JPL.ColorArrays.pas', + JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', + JPL.Colors.List in '..\..\Graphics\JPL.Colors.List.pas', + JPL.Colors in '..\..\Graphics\JPL.Colors.pas', + // Logging JPL.SimpleLogger in '..\..\Logging\JPL.SimpleLogger.pas', diff --git a/packages/Delphi_XE7/JPLib.dproj b/packages/Delphi_XE7/JPLib.dproj index b7a86cf..466c43b 100644 --- a/packages/Delphi_XE7/JPLib.dproj +++ b/packages/Delphi_XE7/JPLib.dproj @@ -28,12 +28,25 @@ Base true + + true + Cfg_1 + true + true + + + true + Cfg_1 + true + true + true Base true + JPLib JPLib Runtime Package false false @@ -46,7 +59,6 @@ true true true - JPLib CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= 1033 @@ -67,6 +79,12 @@ false 0 + + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + + + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + DEBUG;$(DCC_Define) true @@ -87,11 +105,16 @@ + + + + + @@ -108,10 +131,12 @@ + - - + + + diff --git a/packages/Delphi_XE8/JPLib.dpk b/packages/Delphi_XE8/JPLib.dpk index 3bd5427..3188e9c 100644 --- a/packages/Delphi_XE8/JPLib.dpk +++ b/packages/Delphi_XE8/JPLib.dpk @@ -39,10 +39,6 @@ requires contains // BASE - {$IFDEF FPC} - JPL.FileSearcher in '..\..\Base\JPL.FileSearcher.pas', - JPL.JsonHelpers in '..\..\Base\JPL.JsonHelpers.pas', - {$ENDIF} JPL.CmdLineParser in '..\..\Base\JPL.CmdLineParser.pas', JPL.Console.ColorParser in '..\..\Base\JPL.Console.ColorParser.pas', JPL.Console in '..\..\Base\JPL.Console.pas', @@ -52,11 +48,16 @@ contains JPL.Dialogs in '..\..\Base\JPL.Dialogs.pas', JPL.Files in '..\..\Base\JPL.Files.pas', JPL.FileSearch in '..\..\Base\JPL.FileSearch.pas', + JPL.IniFile in '..\..\Base\JPL.IniFile.pas', + JPL.LangMgr in '..\..\Base\JPL.LangMgr.pas', JPL.Language in '..\..\Base\JPL.Language.pas', JPL.Math in '..\..\Base\JPL.Math.pas', + JPL.MemIniFile in '..\..\Base\JPL.MemIniFile.pas', + JPL.RTTI in '..\..\Base\JPL.RTTI.pas', JPL.StrHash in '..\..\Base\JPL.StrHash.pas', JPL.Strings in '..\..\Base\JPL.Strings.pas', JPL.Strings.Ext in '..\..\Base\JPL.Strings.Ext.pas', + JPL.Units in '..\..\Base\JPL.Units.pas', JPL.Utils in '..\..\Base\JPL.Utils.pas', JPL.Win.Dialogs in '..\..\Base\JPL.Win.Dialogs.pas', JPL.Win.FileSystem in '..\..\Base\JPL.Win.FileSystem.pas', @@ -77,12 +78,15 @@ contains JPL.UPX in '..\..\Binary\JPL.UPX.pas', // Containers + JPL.Win.FileIcons in '..\..\Containers\JPL.Win.FileIcons.pas', JPL.StrList in '..\..\Containers\JPL.StrList.pas', // Graphics - JPL.Colors in '..\..\Graphics\JPL.Colors.pas', - JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', JPL.ColorArrays in '..\..\Graphics\JPL.ColorArrays.pas', + JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', + JPL.Colors.List in '..\..\Graphics\JPL.Colors.List.pas', + JPL.Colors in '..\..\Graphics\JPL.Colors.pas', + // Logging JPL.SimpleLogger in '..\..\Logging\JPL.SimpleLogger.pas', diff --git a/packages/Lazarus/jplib.lpk b/packages/Lazarus/jplib.lpk index f23c9f8..8426e88 100644 --- a/packages/Lazarus/jplib.lpk +++ b/packages/Lazarus/jplib.lpk @@ -14,7 +14,7 @@ - + @@ -56,112 +56,129 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + - + - + - + + + + - + + <_ExternHelp Items="Count"/> + diff --git a/packages/Lazarus/jplib.pas b/packages/Lazarus/jplib.pas index e7fd0ce..2b4fe89 100644 --- a/packages/Lazarus/jplib.pas +++ b/packages/Lazarus/jplib.pas @@ -4,17 +4,15 @@ unit jplib; +{$warn 5023 off : no warning about unused units} interface uses - JPL.CmdLineParser, JPL.Console.ColorParser, JPL.Console, JPL.ConsoleApp, - JPL.Conversion, JPL.DateTime, JPL.Dialogs, JPL.Files, JPL.FileSearch, - JPL.FileSearcher, JPL.JsonHelpers, JPL.Language, JPL.Math, JPL.MemIniFile, - JPL.RTTI, JPL.StrHash, JPL.Strings.Ext, JPL.Strings, JPL.Units, JPL.Utils, - JPL.Win.Dialogs, JPL.Win.FileSystem, JPL.Win.Shortcuts, JPL.Win.System, - JPL.Win.VersionInfo, JPL.StrList, JPL.ColorArrays, JPL.Colors.ColorClass, - JPL.Colors.List, JPL.Colors, JPL.SimpleLogger, JPL.TimeLogger, - LazarusPackageIntf; + JPL.CmdLineParser, JPL.Console.ColorParser, JPL.Console, JPL.ConsoleApp, JPL.Conversion, JPL.DateTime, JPL.Dialogs, JPL.Files, + JPL.FileSearch, JPL.FileSearcher, JPL.IniFile, JPL.JsonHelpers, JPL.Language, JPL.Math, JPL.MemIniFile, JPL.RTTI, JPL.StrHash, + JPL.Strings.Ext, JPL.Strings, JPL.Units, JPL.Utils, JPL.Win.Dialogs, JPL.Win.FileSystem, JPL.Win.Processes, JPL.Win.Shortcuts, + JPL.Win.System, JPL.Win.VersionInfo, JPL.StrList, JPL.Win.FileIcons, JPL.ColorArrays, JPL.Colors.ColorClass, JPL.Colors.List, + JPL.Colors, JPL.SimpleLogger, JPL.TimeLogger, LazarusPackageIntf; implementation diff --git a/packages/_DpkGen/JPLib_TEMPLATE.dpk b/packages/_DpkGen/JPLib_TEMPLATE.dpk index e148d95..cb48966 100644 --- a/packages/_DpkGen/JPLib_TEMPLATE.dpk +++ b/packages/_DpkGen/JPLib_TEMPLATE.dpk @@ -39,10 +39,6 @@ requires contains // BASE - {$IFDEF FPC} - JPL.FileSearcher in '..\..\Base\JPL.FileSearcher.pas', - JPL.JsonHelpers in '..\..\Base\JPL.JsonHelpers.pas', - {$ENDIF} JPL.CmdLineParser in '..\..\Base\JPL.CmdLineParser.pas', JPL.Console.ColorParser in '..\..\Base\JPL.Console.ColorParser.pas', JPL.Console in '..\..\Base\JPL.Console.pas', @@ -52,11 +48,16 @@ contains JPL.Dialogs in '..\..\Base\JPL.Dialogs.pas', JPL.Files in '..\..\Base\JPL.Files.pas', JPL.FileSearch in '..\..\Base\JPL.FileSearch.pas', + JPL.IniFile in '..\..\Base\JPL.IniFile.pas', + JPL.LangMgr in '..\..\Base\JPL.LangMgr.pas', JPL.Language in '..\..\Base\JPL.Language.pas', JPL.Math in '..\..\Base\JPL.Math.pas', + JPL.MemIniFile in '..\..\Base\JPL.MemIniFile.pas', + JPL.RTTI in '..\..\Base\JPL.RTTI.pas', JPL.StrHash in '..\..\Base\JPL.StrHash.pas', JPL.Strings in '..\..\Base\JPL.Strings.pas', JPL.Strings.Ext in '..\..\Base\JPL.Strings.Ext.pas', + JPL.Units in '..\..\Base\JPL.Units.pas', JPL.Utils in '..\..\Base\JPL.Utils.pas', JPL.Win.Dialogs in '..\..\Base\JPL.Win.Dialogs.pas', JPL.Win.FileSystem in '..\..\Base\JPL.Win.FileSystem.pas', @@ -77,12 +78,15 @@ contains JPL.UPX in '..\..\Binary\JPL.UPX.pas', // Containers + JPL.Win.FileIcons in '..\..\Containers\JPL.Win.FileIcons.pas', JPL.StrList in '..\..\Containers\JPL.StrList.pas', // Graphics - JPL.Colors in '..\..\Graphics\JPL.Colors.pas', - JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', JPL.ColorArrays in '..\..\Graphics\JPL.ColorArrays.pas', + JPL.Colors.ColorClass in '..\..\Graphics\JPL.Colors.ColorClass.pas', + JPL.Colors.List in '..\..\Graphics\JPL.Colors.List.pas', + JPL.Colors in '..\..\Graphics\JPL.Colors.pas', + // Logging JPL.SimpleLogger in '..\..\Logging\JPL.SimpleLogger.pas', diff --git a/packages/_DpkGen/Readme.md b/packages/_DpkGen/Readme.md new file mode 100644 index 0000000..2d0c9b9 --- /dev/null +++ b/packages/_DpkGen/Readme.md @@ -0,0 +1,203 @@ +# Info + +To execute the `generate_packages.bat` file, you need: +1. **DpkGen** from http://www.pazera-software.com/products/dpk-generator/ +1. **StrRep** http://www.pazera-software.com/files/StrRep.exe (source below). + +```pascal +program StrRep; + +// Disable extended RTTI +{$IF CompilerVersion >= 21.0} // >= Delphi 2010 + {$WEAKLINKRTTI ON} + {$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])} +{$IFEND} + +{$SetPEFlags 1} // IMAGE_FILE_RELOCS_STRIPPED +{$SetPEFlags $20} // IMAGE_FILE_LARGE_ADDRESS_AWARE + +{$APPTYPE CONSOLE} +{$R *.res} + +uses + Windows, + SysUtils, StrUtils, Classes, + JPL.Console, JPL.FileSearch // <-- https://github.com/jackdp/JPLib/tree/master/Base + ; + + +var + MyName: string; + fName: string; + s, s2, sOld, sNew: string; + slFileContent, slFileNames, slFileMasks, slTemp: TStringList; + x, i: integer; + rf: TReplaceFlags; + bIgnoreCase: Boolean; + xSub: Byte; + xReplaceCount, xModifiedFiles: integer; + + +function StrToBool(s: string): Boolean; +begin + s := Trim(AnsiUpperCase(s)); + if (s = 'TRUE') or (s = 'T') or (s = 'TAK') or (s = 'YES') or (s = 'Y') or (s = '1') then Result := True + else Result := False; +end; + +procedure ShowInfo; +begin + Writeln(MyName, ' replaces occurrences of the substring specified by OldPattern with the substring specified by NewPattern in the given file/files.'); + Writeln; + TConsole.WriteTaggedTextLine( + 'Usage: ' + MyName + + ' FileNames OldPattern NewPattern' + + ' | xSub | IgnoreCase | First/All' + ); + TConsole.WriteTaggedTextLine(' FileNames - Comma separated list of file names and/or file masks.'); + TConsole.WriteTaggedTextLine(' OldPattern - Old string.'); + TConsole.WriteTaggedTextLine(' NewPattern - New string.'); + TConsole.WriteTaggedTextLine(' xSub - Recurse to xSub subdirectory (default: 0).'); + TConsole.WriteTaggedTextLine(' IgnoreCase - Ignore character case: True|Yes|1 or False (default: False).'); + TConsole.WriteTaggedTextLine(' First/All - Replace First or All occurences (default: First).'); + Writeln; + TConsole.WriteTaggedTextLine( + 'Example: ' + MyName + + ' "*.txt,file.ini,long file name.xml" "old string"' + + ' "new string" 0 true' + + ' all' + ); +end; + +begin + + MyName := ExtractFileName(ParamStr(0)); + + fName := ParamStr(1); + + if ParamCount < 3 then + begin + ShowInfo; + Exit; + end; + + sOld := ParamStr(2); + sOld := StringReplace(sOld, '"', '"', [rfReplaceAll]); + sNew := ParamStr(3); + sNew := StringReplace(sNew, '"', '"', [rfReplaceAll]); + + xSub := 0; + if ParamCount >= 4 then + try + xSub := StrToInt(ParamStr(4)); + except + end; + + TConsole.WriteTaggedTextLine('Replace: ' + sOld + ' with ' + sNew + ''); + Writeln('Recurse depth (xSub): ', xSub); + + + rf := []; + + bIgnoreCase := StrToBool(ParamStr(5)); + if bIgnoreCase then rf := rf + [rfIgnoreCase]; + + s := UpperCase(ParamStr(6)); + if (s = 'ALL') then rf := rf + [rfReplaceAll]; + + + slFileNames := TStringList.Create; + slFileContent := TStringList.Create; + slFileMasks := TStringList.Create; + slTemp := TStringList.Create; + + try + + + s := ParamStr(1); + x := Pos(',', s); + if x > 0 then + while x <> 0 do + begin + s2 := Copy(s, 1, x - 1); + s2 := Trim(s2); + slFileMasks.Add(s2); + s := Trim(Copy(s, x + 1, Length(s))); + x := Pos(',', s); + end; + + if s <> '' then slFileMasks.Add(Trim(s)); + + for i := 0 to slFileMasks.Count - 1 do + slFileMasks[i] := ExpandFileName(slFileMasks[i]); + + + for i := 0 to slFileMasks.Count - 1 do + begin + slTemp.Clear; + s := slFileMasks[i]; + JPGetFileList(ExtractFileName(s), ExtractFileDir(s), slTemp, xSub, False); + slFileNames.AddStrings(slTemp); + end; + + slFileNames.Sort; + + xModifiedFiles := 0; + xReplaceCount := 0; + + for x := 0 to slFileNames.Count - 1 do + begin + + fName := slFileNames[x]; + TConsole.WriteTaggedText('Processing file: ' + fName + ''); + + slFileContent.LoadFromFile(fName); + + for i := 0 to slFileContent.Count - 1 do + begin + + s := slFileContent[i]; + + if bIgnoreCase then + begin + if not AnsiContainsText(s, sOld) then Continue; + end + else + begin + if not AnsiContainsStr(s, sOld) then Continue; + end; + + Inc(xReplaceCount); + + s := StringReplace(s, sOld, sNew, rf); + slFileContent[i] := s; + + end; + + if xReplaceCount > 0 then + begin + Inc(xModifiedFiles); + slFileContent.SaveToFile(fName); + TConsole.WriteTaggedTextLine(' - file modified!'); + end + else + Writeln(''); + + + end; // for x + + + finally + slFileContent.Free; + slFileNames.Free; + slFileMasks.Free; + slTemp.Free; + end; + + + Writeln('Modified files: ', xModifiedFiles); + Writeln('Done'); + +end. + +``` \ No newline at end of file diff --git a/packages/_DpkGen/generate_packages.bat b/packages/_DpkGen/generate_packages.bat index 9f815c9..e9ef3b9 100644 --- a/packages/_DpkGen/generate_packages.bat +++ b/packages/_DpkGen/generate_packages.bat @@ -5,7 +5,7 @@ set Desc="JPLib Runtime Package" set BaseOutDir=..\Delphi set ShortDpkName=JPLib.dpk -for %%x in (XE2,XE3,XE4,XE5,XE6,XE7,XE8) do ( +for %%x in (2009,2010,XE,XE2,XE3,XE4,XE5,XE6,XE7,XE8) do ( DpkGen -t %Template% -d %Desc% -o %BaseOutDir%_%%x\%ShortDpkName% -s %%x ) @@ -13,3 +13,8 @@ DpkGen -t %Template% -d %Desc% -o %BaseOutDir%_10.0_Seattle\%ShortDpkName% -s Se DpkGen -t %Template% -d %Desc% -o %BaseOutDir%_10.1_Berlin\%ShortDpkName% -s Berlin DpkGen -t %Template% -d %Desc% -o %BaseOutDir%_10.2_Tokyo\%ShortDpkName% -s Tokyo DpkGen -t %Template% -d %Desc% -o %BaseOutDir%_10.3_Rio\%ShortDpkName% -s Rio + + +StrRep.exe "..\Delphi_2009\%ShortDpkName%" "JPL.LangMgr" "//JPL.LangMgr" 0 true first +StrRep.exe "..\Delphi_2009\%ShortDpkName%" "JPL.RTTI" "//JPL.RTTI" 0 true first +