From: <tom...@us...> - 2021-07-26 11:16:15
|
Revision: 3562 http://sourceforge.net/p/gexperts/code/3562 Author: tommiprami Date: 2021-07-26 11:16:12 +0000 (Mon, 26 Jul 2021) Log Message: ----------- - Inlined method must be implemented before it is called Modified Paths: -------------- trunk/ExternalSource/dzlib/u_dzConvertUtils.pas trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas trunk/ExternalSource/dzlib/u_dzStringUtils.pas Modified: trunk/ExternalSource/dzlib/u_dzConvertUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzConvertUtils.pas 2021-07-25 15:13:36 UTC (rev 3561) +++ trunk/ExternalSource/dzlib/u_dzConvertUtils.pas 2021-07-26 11:16:12 UTC (rev 3562) @@ -664,11 +664,7 @@ Result := '0' + Result; end; -function ReduceToByte(const _Value: Integer): Byte; -begin - Result := ReduceToUInt8(_Value); -end; - +// Inlined method must be implemented before it is called function ReduceToUInt8(const _Value: Integer): UInt8; begin if _Value < 0 then @@ -679,6 +675,11 @@ Result := _Value; end; +function ReduceToByte(const _Value: Integer): Byte; +begin + Result := ReduceToUInt8(_Value); +end; + function ReduceToInt8(const _Value: Integer): Int8; begin if _Value < MinInt8 then Modified: trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2021-07-25 15:13:36 UTC (rev 3561) +++ trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2021-07-26 11:16:12 UTC (rev 3562) @@ -1119,6 +1119,12 @@ _Canvas.Polygon([_Tip, Point(BaselineLeft, BaselineY), Point(BaselineRight, BaselineY)]); end; +// Inlined method must be iomplemented before it is called +function GetFastLuminance(_Red, _Green, _Blue: Byte): Byte; +begin + Result := Round(0.299 * _Red + 0.587 * _Green + 0.114 * _Blue); +end; + function TdzRgbTriple_GetFastLuminance(const _Triple: TdzRgbTriple): Byte; begin Result := GetFastLuminance(_Triple.Red, _Triple.Green, _Triple.Blue); @@ -1132,11 +1138,6 @@ _Triple.Blue := GetBValue(_Color); end; -function GetFastLuminance(_Red, _Green, _Blue: Byte): Byte; -begin - Result := Round(0.299 * _Red + 0.587 * _Green + 0.114 * _Blue); -end; - procedure GetRgbHls(_Red, _Green, _Blue: Byte; out _Hls: THlsRec); begin ColorRGBToHLS(RGB(_Red, _Green, _Blue), _Hls.Hue, _Hls.Luminance, _Hls.Saturation); @@ -1174,6 +1175,12 @@ {$IFDEF SUPPORTS_ENHANCED_RECORDS} { TdzRgbTriple } +// Inlined method must be iomplemented before it is called +function TdzRgbTriple.GetFastLuminance: Byte; +begin + Result := Round(0.299 * Red + 0.587 * Green + 0.114 * Blue); +end; + function TdzRgbTriple.GetBrightness(_Channel: TRgbBrightnessChannelEnum): Byte; begin case _Channel of @@ -1221,11 +1228,6 @@ Blue := _Value; end; -function TdzRgbTriple.GetFastLuminance: Byte; -begin - Result := Round(0.299 * Red + 0.587 * Green + 0.114 * Blue); -end; - class function TdzRgbTriple.GetFastLuminance(_Red, _Green, _Blue: Byte): Byte; begin Result := Round(0.299 * _Red + 0.587 * _Green + 0.114 * _Blue); @@ -1411,6 +1413,8 @@ Hue: Word; Saturation: Word; begin + Result := 0; + GetHls(Hue, Result, Saturation) end; @@ -1897,6 +1901,18 @@ end; end; +// Inlined method muist be implemented before it is used +function TryCalcEllipsePoints(_x0, _y0, _a, _b, _x: Extended; out _y1, _y2: Extended): Boolean; +var + y: Extended; +begin + Result := TryCalcEllipsePoint(_a, _b, _x - _x0, y); + if Result then begin + _y1 := -y + _y0; + _y2 := y + _y0; + end; +end; + procedure TBitmap_BlurEllipse(_bmp: TBitmap; _Left, _Top, _Right, _Bottom: Integer; _Passes: Integer); var x, y: Integer; @@ -2015,17 +2031,6 @@ _y := _b * Sqrt(sq); end; -function TryCalcEllipsePoints(_x0, _y0, _a, _b, _x: Extended; out _y1, _y2: Extended): Boolean; -var - y: Extended; -begin - Result := TryCalcEllipsePoint(_a, _b, _x - _x0, y); - if Result then begin - _y1 := -y + _y0; - _y2 := y + _y0; - end; -end; - procedure TBitmap24_FilterPixels(_SrcBmp, _DstBmp: TBitmap; _Callback: TPixel24FilterCallback); const BytesPerPixel = 3; @@ -2640,6 +2645,18 @@ end; end; +// Inlined method must be iomplemented before it is called +function AddToPtr(const _Ptr: Pointer; _Offset: NativeInt): Pointer; +begin + Result := Pointer(NativeInt(_Ptr) + _Offset); +end; + +// Inlined method must be iomplemented before it is called +function PtrDiff(const _Ptr1, _Ptr2: Pointer): NativeInt; +begin + Result := NativeInt(_Ptr1) - NativeInt(_Ptr2); +end; + procedure TBitmap8_Sharpen(_SrcBmp, _DstBmp: TBitmap; const _AlphaMap: TSingleMatrix); type PPixel = PByte; @@ -2965,16 +2982,6 @@ _Rop); end; -function AddToPtr(const _Ptr: Pointer; _Offset: NativeInt): Pointer; -begin - Result := Pointer(NativeInt(_Ptr) + _Offset); -end; - -function PtrDiff(const _Ptr1, _Ptr2: Pointer): NativeInt; -begin - Result := NativeInt(_Ptr1) - NativeInt(_Ptr2); -end; - function TBitmap8_TryCalcAverage(_bmp: TBitmap; _LowCutoff, _HighCutoff: Byte; out _Average: Byte): Boolean; const Modified: trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas 2021-07-25 15:13:36 UTC (rev 3561) +++ trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas 2021-07-26 11:16:12 UTC (rev 3562) @@ -161,6 +161,14 @@ { TNullableTimespan } +// Inlined method must be implemented before called +procedure TNullableTimespan.SetDaysAndMicroseconds(_FullDays: Int64; _MicroSeconds: Int64); +begin + FFullDays := _FullDays; + FMicroSeconds := _MicroSeconds; + FIsValid := GetNullableTypesFlagInterface; +end; + procedure TNullableTimespan.AssignDays(_Days: Double); begin SetDaysAndMicroseconds(Trunc(_Days), Round(Frac(_Days) / OneMicrosecond)); @@ -638,13 +646,6 @@ raise EInvalidValue.Create(_('NullableTimespan value is invalid')); end; -procedure TNullableTimespan.SetDaysAndMicroseconds(_FullDays: Int64; _MicroSeconds: Int64); -begin - FFullDays := _FullDays; - FMicroSeconds := _MicroSeconds; - FIsValid := GetNullableTypesFlagInterface; -end; - function TNullableTimespan.InDays: Double; begin if not TryGetDays(Result) then Modified: trunk/ExternalSource/dzlib/u_dzStringUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzStringUtils.pas 2021-07-25 15:13:36 UTC (rev 3561) +++ trunk/ExternalSource/dzlib/u_dzStringUtils.pas 2021-07-26 11:16:12 UTC (rev 3562) @@ -527,6 +527,12 @@ Result := RemoveSuffixIfMatching(_s, _Suffix); end; +// Inlined functions must be implemented before it is used. +function UEndsWith(const _End, _s: string): Boolean; +begin + Result := AnsiEndsText(_End, _s); +end; + function RemoveSuffixIfMatching(const _s, _Suffix: string): string; begin if UEndsWith(_Suffix, _s) then @@ -1406,11 +1412,6 @@ Result := AnsiEndsStr(_End, RightStr(_s, Length(_End))); end; -function UEndsWith(const _End, _s: string): Boolean; -begin - Result := AnsiEndsText(_End, _s); -end; - function UnquoteString(const _s: string; _Quote: Char): string; var Len: Integer; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tw...@us...> - 2021-08-02 10:04:49
|
Revision: 3571 http://sourceforge.net/p/gexperts/code/3571 Author: twm Date: 2021-08-02 10:04:46 +0000 (Mon, 02 Aug 2021) Log Message: ----------- synced with latest sources from dzlib Modified Paths: -------------- trunk/ExternalSource/dzlib/u_dzFileUtils.pas trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas trunk/ExternalSource/dzlib/u_dzStopwatch.pas trunk/ExternalSource/dzlib/u_dzStringArrayUtils.pas trunk/ExternalSource/dzlib/u_dzVariantUtils.pas trunk/ExternalSource/dzlib/u_dzVclUtils.pas Modified: trunk/ExternalSource/dzlib/u_dzFileUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzFileUtils.pas 2021-08-02 09:30:05 UTC (rev 3570) +++ trunk/ExternalSource/dzlib/u_dzFileUtils.pas 2021-08-02 10:04:46 UTC (rev 3571) @@ -742,7 +742,9 @@ /// @param Mask is the filename mask to match /// @param Filename is the name of the file which has been found, only valid if result <> mfNotFound /// @returns mfNotFound, if no file was found, or mfDirectory, mfFile or mfSpecial - /// describing the type of the file which has been found </summary> + /// describing the type of the file which has been found. + /// @NOTE: If there are multiple matches, the file name returned is not deterministic. + /// On an NTFS volume it is the last one in the NTFS sort order but that's not guaranteed. </summary> class function FindMatchingFile(const _Mask: string; out _Filename: string): TMatchingFileResult; overload; class function FindMatchingFile(const _Mask: string): TMatchingFileResult; overload; @@ -1059,7 +1061,7 @@ /// replaces the drive part of the path with the given NewDrive. </summary> procedure ReplaceDrive(const _NewDrive: string); ///<summary> - /// Replaces the directory part with the given NewDir </summary> + /// Replaces the directory part (including the drive) with the given NewDir </summary> procedure ReplaceDirectory(const _NewDir: string); ///<summary> /// Replaces filename and extension(s) with the given filename </summary> Modified: trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2021-08-02 09:30:05 UTC (rev 3570) +++ trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2021-08-02 10:04:46 UTC (rev 3571) @@ -1413,8 +1413,6 @@ Hue: Word; Saturation: Word; begin - Result := 0; - GetHls(Hue, Result, Saturation) end; Modified: trunk/ExternalSource/dzlib/u_dzStopwatch.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzStopwatch.pas 2021-08-02 09:30:05 UTC (rev 3570) +++ trunk/ExternalSource/dzlib/u_dzStopwatch.pas 2021-08-02 10:04:46 UTC (rev 3571) @@ -12,14 +12,13 @@ type TStopwatch = record -{$IFDEF DELPHI2007_UP} -// enhanced record support in Delphi 2006 was not stable +{$IFDEF SUPPORTS_ENHANCED_RECORDS} private {$ENDIF} FElapsedTicks: Int64; FIsRunning: Boolean; FStartTicks: Int64; -{$IFDEF DELPHI2007_UP} +{$IFDEF SUPPORTS_ENHANCED_RECORDS} function GetElapsedDateTimeTicks: Int64; public class function Create: TStopwatch; static; @@ -67,7 +66,7 @@ gblIsHighResolution: Boolean; gblTickFrequency: Double; -{$IFDEF DELPHI2007_UP} +{$IFDEF SUPPORTS_ENHANCED_RECORDS} { TStopwatch } class function TStopwatch.Create: TStopwatch; @@ -248,7 +247,7 @@ end; end; -{$IFDEF DELPHI2007_UP} +{$IFDEF SUPPORTS_ENHANCED_RECORDS} procedure Test; var Stopwatch: TStopwatch; Modified: trunk/ExternalSource/dzlib/u_dzStringArrayUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzStringArrayUtils.pas 2021-08-02 09:30:05 UTC (rev 3570) +++ trunk/ExternalSource/dzlib/u_dzStringArrayUtils.pas 2021-08-02 10:04:46 UTC (rev 3571) @@ -34,6 +34,16 @@ procedure TStrings_AssignStringArray(_st: TStrings; _arr: TStringArray); procedure TStrings_AppendStringArray(_st: TStrings; _arr: TStringArray); +///<summary> +/// Concatenate strings from index FromIdx to ToIdx in the array to a string, using the given separator +/// @param arr is the source array +/// @param Separator is a string which will used to separate the array items +/// @param FromIdx is the starting index, default is 0 +/// @param ToIdx is the end index, can be negative meaning Length - ToIdx, so -1 means Length-1 +/// @returns the concatenated string </summary> +//function TStringArray_ToString(const _arr: TStringArray; const _Separator: string; +// _FromIdx: Integer = 0; _ToIdx: Integer = -1): string; + implementation uses @@ -45,7 +55,7 @@ len: Integer; begin len := Length(_arr); - Setlength(Result, len); + SetLength(Result, len); for i := 0 to len - 1 do Result[i] := _arr[i]; end; @@ -72,7 +82,7 @@ i: Integer; begin cnt := _st.Count; - Setlength(Result, cnt); + SetLength(Result, cnt); for i := 0 to cnt - 1 do Result[i] := _st[i]; end; @@ -128,7 +138,7 @@ if _Index >= len - _Count then begin // delete from the end - Setlength(_arr, _Index); + SetLength(_arr, _Index); Exit; //==> end; @@ -135,7 +145,7 @@ for i := _Index to len - _Count - 1 do begin _arr[i] := _arr[i + _Count]; end; - Setlength(_arr, len - _Count); + SetLength(_arr, len - _Count); end; function TStringArray_Contains(const _arr: TStringArray; const _s: string; out _Idx: Integer): Boolean; @@ -166,7 +176,7 @@ begin Len1 := Length(_Arr1); Len2 := Length(_Arr2); - Setlength(Result, Len1 + Len2); + SetLength(Result, Len1 + Len2); for i := 0 to Len1 - 1 do Result[i] := _Arr1[i]; for i := 0 to Len2 - 1 do @@ -178,7 +188,7 @@ len: Integer; begin len := Length(_arr); - Setlength(_arr, len + 1); + SetLength(_arr, len + 1); _arr[len] := _Value; end; Modified: trunk/ExternalSource/dzlib/u_dzVariantUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzVariantUtils.pas 2021-08-02 09:30:05 UTC (rev 3570) +++ trunk/ExternalSource/dzlib/u_dzVariantUtils.pas 2021-08-02 10:04:46 UTC (rev 3571) @@ -171,7 +171,7 @@ /// @returns the extended value of v or the Default if v can not be converted </summary> function Var2Ext(const _v: Variant; const _Default: Extended): Extended; -{$IF Declared(TryStrToDateTime)} +{$IF Declared(TryStr2DateTime)} ///<summary> Converts a variant to a TDateTime. /// Raises an exception if v can not be converted. /// @param v Variant value to convert @@ -427,10 +427,10 @@ Result := _NullValue; end; -{$IF Declared(TryStrToDateTime)} +{$IF Declared(TryStr2DateTime)} function Var2DateTimeEx(const _v: Variant; const _Source: string): TDateTime; const - EXPECTED = 'Date'; // do not translate + EXPECTED = 'DateTime'; // do not translate begin if VarIsNull(_v) then raise EVarIsNull.CreateFmt(_('Variant is Null, should be %s: %s'), [EXPECTED, _Source]); @@ -437,7 +437,7 @@ if VarIsEmpty(_v) then raise EVarIsEmpty.CreateFmt(_('Variant is Empty, should be %s: %s'), [EXPECTED, _Source]); if VarIsStr(_v) then begin - if not TryStrToDateTime(_v, Result) then + if not TryStr2DateTime(_v, Result) then raise EVariantConvertError.CreateFmt(_('Variant can not be converted to %s: %s'), [EXPECTED, _Source]); end else begin try Modified: trunk/ExternalSource/dzlib/u_dzVclUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2021-08-02 09:30:05 UTC (rev 3570) +++ trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2021-08-02 10:04:46 UTC (rev 3571) @@ -164,9 +164,13 @@ /// False, if all columns fit without scrolling /// @note that the default is to use the first 10 rows. </summary> function TGrid_Resize(_Grid: TCustomGrid): Boolean; overload; +function TGrid_Resize(_Grid: TCustomGrid; out _RequiredSize: Integer): Boolean; overload; function TGrid_Resize(_Grid: TCustomGrid; _Options: TResizeOptionSet; _RowOffset: Integer = -1): Boolean; overload; +function TGrid_Resize(_Grid: TCustomGrid; _Options: TResizeOptionSet; _RowOffset: Integer; out _RequiredSize: Integer): Boolean; overload; function TGrid_Resize(_Grid: TCustomGrid; _Options: TResizeOptionSet; const _ConstantCols: array of Integer; _RowOffset: Integer = -1): Boolean; overload; +function TGrid_Resize(_Grid: TCustomGrid; _Options: TResizeOptionSet; + const _ConstantCols: array of Integer; _RowOffset: Integer; out _RequiredSize: Integer): Boolean; overload; ///<summary> Resizes the columns of a TDbGrid to fit their contents /// @param Grid is the TCustomDbGrid to work on @@ -2691,14 +2695,32 @@ Result := TGrid_Resize(_Grid, [roUseFirstRows], [], -1); end; +function TGrid_Resize(_Grid: TCustomGrid; out _RequiredSize: Integer): Boolean; +begin + Result := TGrid_Resize(_Grid, [roUseFirstRows], [], -1, _RequiredSize); +end; + function TGrid_Resize(_Grid: TCustomGrid; _Options: TResizeOptionSet; _RowOffset: Integer): Boolean; begin Result := TGrid_Resize(_Grid, _Options, [], _RowOffset); end; +function TGrid_Resize(_Grid: TCustomGrid; _Options: TResizeOptionSet; _RowOffset: Integer; out _RequiredSize: Integer): Boolean; +begin + Result := TGrid_Resize(_Grid, _Options, [], _RowOffset, _RequiredSize); +end; + function TGrid_Resize(_Grid: TCustomGrid; _Options: TResizeOptionSet; const _ConstantCols: array of Integer; _RowOffset: Integer): Boolean; var + RequiredSize: Integer; +begin + Result := TGrid_Resize(_Grid, _Options, _ConstantCols, _RowOffset, RequiredSize); +end; + +function TGrid_Resize(_Grid: TCustomGrid; _Options: TResizeOptionSet; + const _ConstantCols: array of Integer; _RowOffset: Integer; out _RequiredSize: Integer): Boolean; +var Col, Row: Integer; Grid: TGridHack; MinWidth: Integer; @@ -2707,7 +2729,6 @@ MaxRow: Integer; ColWidths: array of Integer; FirstRow: Integer; - SumWidths: Integer; Additional: Integer; begin Grid := TGridHack(_Grid); @@ -2729,9 +2750,9 @@ FirstRow := MaxRow - 10; end; - SumWidths := MaxCol; // one spare pixel per column + _RequiredSize := MaxCol; // one spare pixel per column if goVertLine in Grid.Options then - Inc(SumWidths, Grid.GridLineWidth); + Inc(_RequiredSize, Grid.GridLineWidth); for Col := MinCol to MaxCol do begin if ArrayContains(Col, _ConstantCols) then @@ -2774,26 +2795,26 @@ ColWidths[Col] := MinWidth; end; - Inc(SumWidths, MinWidth); + Inc(_RequiredSize, MinWidth); end; - if SumWidths >= Grid.ClientWidth then begin + if _RequiredSize >= Grid.ClientWidth then begin Result := True; end else begin Result := False; if (roUseGridWidth in _Options) and (Length(_ConstantCols) < MaxCol + 1) then begin - Additional := (Grid.ClientWidth - SumWidths) div (MaxCol + 1 - Length(_ConstantCols)); + Additional := (Grid.ClientWidth - _RequiredSize) div (MaxCol + 1 - Length(_ConstantCols)); for Col := MinCol to MaxCol do begin if not ArrayContains(Col, _ConstantCols) then begin Inc(ColWidths[Col], Additional); - Inc(SumWidths, Additional); + Inc(_RequiredSize, Additional); end; end; - if SumWidths < Grid.ClientWidth then begin + if _RequiredSize < Grid.ClientWidth then begin Col := MaxCol; while ArrayContains(Col, _ConstantCols) do Dec(Col); - Inc(ColWidths[Col], Grid.ClientWidth - SumWidths); + Inc(ColWidths[Col], Grid.ClientWidth - _RequiredSize); end; end; end; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tw...@us...> - 2021-08-14 16:07:14
|
Revision: 3580 http://sourceforge.net/p/gexperts/code/3580 Author: twm Date: 2021-08-14 16:07:11 +0000 (Sat, 14 Aug 2021) Log Message: ----------- updated to latest version from OSDN Modified Paths: -------------- trunk/ExternalSource/dzlib/dzlib.inc trunk/ExternalSource/dzlib/u_dzClassUtils.pas trunk/ExternalSource/dzlib/u_dzTranslator.pas trunk/ExternalSource/dzlib/u_dzTypes.pas Modified: trunk/ExternalSource/dzlib/dzlib.inc =================================================================== --- trunk/ExternalSource/dzlib/dzlib.inc 2021-08-14 13:25:21 UTC (rev 3579) +++ trunk/ExternalSource/dzlib/dzlib.inc 2021-08-14 16:07:11 UTC (rev 3580) @@ -99,6 +99,12 @@ {$DEFINE HAS_INTTOHEX_FUNCTION_UINT64} {$ENDIF} +{$IFDEF DELPHI2009_UP} + {.I know that it exists in $IFDEF GX_DELPHI_TOKYO_UP} + {$DEFINE CUSTOMINIFILE_HAS_READSUBSECTIONS} +{$ENDIF} + + {$IFOPT T+} {$DEFINE TYPEDADDRESS_IS_ON} {$ENDIF} Modified: trunk/ExternalSource/dzlib/u_dzClassUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzClassUtils.pas 2021-08-14 13:25:21 UTC (rev 3579) +++ trunk/ExternalSource/dzlib/u_dzClassUtils.pas 2021-08-14 16:07:11 UTC (rev 3580) @@ -64,7 +64,6 @@ function TStringList_CreateFrom(const _sa: array of string; _SortHandling: TStringListSortHandling = sshNoSorting): TStringList; overload; - ///<summary> /// Creates a TStringList /// @param SortHandling defines how the properties Sorted and Dupplicates are set </summary> @@ -459,6 +458,20 @@ inline; {$ENDIF} +procedure TMemIniFile_ReadSubSections(_Ini: TMemIniFile; const _Section: string; _Sections: TStrings); +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} +procedure TRegistryIniFile_ReadSubSections(_Ini: TRegistryIniFile; const _Section: string; _Sections: TStrings); +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} + +procedure TCustomIniFile_ReadSubSections(_Ini: TCustomIniFile; const _Section: string; _Sections: TStrings); +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} + type TIniSection = class private @@ -1655,6 +1668,77 @@ end; end; +{$IFDEF CUSTOMINIFILE_HAS_READSUBSECTIONS} +procedure TMemIniFile_ReadSubSections(_Ini: TMemIniFile; const _Section: string; _Sections: TStrings); +begin + _Ini.ReadSubSections(_Section, _Sections, False); +end; +{$ELSE} +procedure TMemIniFile_ReadSubSections(_Ini: TMemIniFile; const _Section: string; _Sections: TStrings); +var + i: Integer; + Len: Integer; + s: string; +begin + _Ini.ReadSections(_Section, _Sections); + Len := Length(_Section); + if Len = 0 then begin + // we only want top level sections, that is those that do not contain a '\' + for i := _Sections.Count - 1 downto 0 do begin + if Pos('\', _Sections[i]) > 0 then + _Sections.Delete(i); + end; + end else begin + for i := _Sections.Count - 1 downto 0 do begin + s := TailStr(_Sections[i], Len + 2); + if (s = '') or (Pos('\', s) > 0) then + _Sections.Delete(i) + else begin + _Sections[i] := s; + end; + end; + end; +end; +{$ENDIF} + +{$IFDEF CUSTOMINIFILE_HAS_READSUBSECTIONS} +procedure TRegistryIniFile_ReadSubSections(_Ini: TRegistryIniFile; const _Section: string; _Sections: TStrings); +begin + _Ini.ReadSubSections(_Section, _Sections, False); +end; +{$ELSE} +procedure TRegistryIniFile_ReadSubSections(_Ini: TRegistryIniFile; const _Section: string; _Sections: TStrings); +var + Reg: TRegistry; +begin + if _Section = '' then begin + _Ini.ReadSections(_Sections); + Exit; //==> + end; + + _Sections.Clear; + Reg := TRegistry.Create; + try + Reg.RootKey := _Ini.RegIniFile.RootKey; + if not Reg.OpenKeyReadOnly(_Ini.Filename + '\' + _Section) then + Exit; //==> + + Reg.GetKeyNames(_Sections); + finally + FreeAndNil(Reg); + end; +end; +{$ENDIF} + +procedure TCustomIniFile_ReadSubSections(_Ini: TCustomIniFile; const _Section: string; _Sections: TStrings); +begin + if _Ini is TMemIniFile then + TMemIniFile_ReadSubSections(TMemIniFile(_Ini), _Section, _Sections) + else if _Ini is TRegistryIniFile then + TRegistryIniFile_ReadSubSections(TRegistryIniFile(_Ini), _Section, _Sections) + else + raise EdzException.CreateFmt(_('Only implemented for TMemIniFile and TRegistryIniFile but not %s'), [_Ini.ClassName]); +end; { TStringsUpdateInt } constructor TStringsUpdateInt.Create(_Strings: TStrings); Modified: trunk/ExternalSource/dzlib/u_dzTranslator.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzTranslator.pas 2021-08-14 13:25:21 UTC (rev 3579) +++ trunk/ExternalSource/dzlib/u_dzTranslator.pas 2021-08-14 16:07:11 UTC (rev 3580) @@ -267,7 +267,7 @@ begin {$IFDEF gnugettext} Result := gnugettext.GetCurrentLocaleName; -{$ESLE} +{$ELSE} Result := ''; {$ENDIF} end; Modified: trunk/ExternalSource/dzlib/u_dzTypes.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzTypes.pas 2021-08-14 13:25:21 UTC (rev 3579) +++ trunk/ExternalSource/dzlib/u_dzTypes.pas 2021-08-14 16:07:11 UTC (rev 3580) @@ -68,6 +68,13 @@ {$IF not declared(NativeUInt) or (SizeOf(Pointer) <> SizeOf(NativeUInt))} NativeUInt = UInt32; {$IFEND} +{$IF not declared(IntPtr))} +{$IF SizeOf(Pointer)=4} + IntPtr = Int32; +{$ELSE} + IntPtr = Int64; +{$IFEND} +{$IFEND} {$IF not declared(UIntPtr)} {$IF SizeOf(Pointer)=4} UIntPtr = UInt32; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tw...@us...> - 2021-08-14 16:39:11
|
Revision: 3582 http://sourceforge.net/p/gexperts/code/3582 Author: twm Date: 2021-08-14 16:39:08 +0000 (Sat, 14 Aug 2021) Log Message: ----------- update dzlib again Modified Paths: -------------- trunk/ExternalSource/dzlib/dzlib.inc trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas Modified: trunk/ExternalSource/dzlib/dzlib.inc =================================================================== --- trunk/ExternalSource/dzlib/dzlib.inc 2021-08-14 16:22:28 UTC (rev 3581) +++ trunk/ExternalSource/dzlib/dzlib.inc 2021-08-14 16:39:08 UTC (rev 3582) @@ -53,6 +53,9 @@ {$IFDEF DELPHI2007_UP} {$DEFINE HAS_INTTOHEX_FUNCTION} +{$ELSE} +// Support for enhanced records didn't work very well in Delphi 2006 +{$UNDEF SUPPORTS_ENHANCED_RECORDS} {$ENDIF} // The following cond. defines address errors in various Delphi versions regarding the declaration @@ -99,8 +102,7 @@ {$DEFINE HAS_INTTOHEX_FUNCTION_UINT64} {$ENDIF} -{$IFDEF DELPHI2009_UP} - {.I know that it exists in $IFDEF GX_DELPHI_TOKYO_UP} +{$IFDEF DELPHI2010_UP} {$DEFINE CUSTOMINIFILE_HAS_READSUBSECTIONS} {$ENDIF} Modified: trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas 2021-08-14 16:22:28 UTC (rev 3581) +++ trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas 2021-08-14 16:39:08 UTC (rev 3582) @@ -4,7 +4,7 @@ interface -{$IFNDEF DELPHI2007_UP} +{$IFNDEF SUPPORTS_ENHANCED_RECORDS} {$IFNDEF NO_DELPHI2007UP_HINT} {$MESSAGE HINT 'Delphi <2007 not supported'} {$ENDIF} @@ -141,11 +141,11 @@ type TdzNullableTimespan = TNullableTimespan deprecated; -{$ENDIF DELPHI2007_UP} +{$ENDIF SUPPORTS_ENHANCED_RECORDS} implementation -{$IFDEF DELPHI2007_UP} +{$IFDEF SUPPORTS_ENHANCED_RECORDS} uses Math, @@ -718,6 +718,6 @@ Result := FFullDays * MicrosecondsPerDay + FMicroSeconds; end; -{$ENDIF DELPHI2007_UP} +{$ENDIF SUPPORTS_ENHANCED_RECORDS} end. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tw...@us...> - 2021-10-01 15:53:10
|
Revision: 3636 http://sourceforge.net/p/gexperts/code/3636 Author: twm Date: 2021-10-01 15:53:08 +0000 (Fri, 01 Oct 2021) Log Message: ----------- * updated to latest version from dzlib * added some more units from dzlib Modified Paths: -------------- trunk/ExternalSource/dzlib/u_dzClassUtils.pas trunk/ExternalSource/dzlib/u_dzOsUtils.pas trunk/ExternalSource/dzlib/u_dzVclUtils.pas Added Paths: ----------- trunk/ExternalSource/dzlib/u_dzAdvancedObject.pas trunk/ExternalSource/dzlib/u_dzDpiScaleUtils.pas trunk/ExternalSource/dzlib/u_dzTypInfo.pas Added: trunk/ExternalSource/dzlib/u_dzAdvancedObject.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzAdvancedObject.pas (rev 0) +++ trunk/ExternalSource/dzlib/u_dzAdvancedObject.pas 2021-10-01 15:53:08 UTC (rev 3636) @@ -0,0 +1,626 @@ +unit u_dzAdvancedObject; + +{$INCLUDE 'dzlib.inc'} + +interface + +{$IFNDEF DELPHI2007_UP} +{$IFNDEF NO_DELPHI2007UP_HINT} +{$MESSAGE HINT 'Delphi <2007 not supported'} +{$ENDIF} +{$ELSE} + +uses + Classes, + TypInfo, + u_dzTypes, + u_dzTranslator; + +type + EPropertyNotFound = class(EdzException) + + end; + +type +{$M+} + ///<summary> + /// Advanced object class with helper functions to access published properties (of descendants) </summary> + TAdvancedObject = class + public + type + TStringArray = array of string; + public + function HasProperty(const _Name: string; out _Type: TTypeKind): Boolean; overload; + class function HasProperty(_Instance: TObject; const _Name: string; out _Type: TTypeKind): Boolean; overload; + + function HasEnumProperty(const _Name: string): Boolean; overload; + class function HasEnumProperty(_Instance: TObject; const _Name: string): Boolean; overload; + + function HasStringProperty(const _Name: string): Boolean; overload; + class function HasStringProperty(_Instance: TObject; const _Name: string): Boolean; overload; + + function HasFloatProperty(const _Name: string): Boolean; overload; + class function HasFloatProperty(_Instance: TObject; const _Name: string): Boolean; overload; + + function HasIntProperty(const _Name: string): Boolean; overload; + class function HasIntProperty(_Instance: TObject; const _Name: string): Boolean; overload; + + function HasObjectProperty(const _Name: string): Boolean; overload; + class function HasObjectProperty(_Instance: TObject; const _Name: string): Boolean; overload; + + function HasEventProperty(const _Name: string): Boolean; overload; + class function HasEventProperty(_Instance: TObject; const _Name: string): Boolean; overload; + + ///<summary> + /// Calls HasEnumProperty and raises an exception if that call returns false </summary> + class procedure CheckHasEnumProperty(_Instance: TObject; const _Name: string); + + ///<summary> + /// Calls HasIntProperty and raises an exception if that call returns false </summary> + class procedure CheckHasIntProperty(_Instance: TObject; const _Name: string); + + ///<summary> + /// Access a string property + /// @param Name is the name of the property + /// @param Value is the value of the property, only valid if Result is true + /// @returns true, if the property exists and is a string property + /// false if it either doesn't exist or has a different type </summary> + function TryGetStringProperty(const _Name: string; out _Value: string): Boolean; overload; + class function TryGetStringProperty(_Instance: TObject; const _Name: string; out _Value: string): Boolean; overload; + function GetStringProperty(const _Name: string; const _Default: string): string; overload; + class function GetStringProperty(_Instance: TObject; const _Name: string; const _Default: string): string; overload; + function GetStringProperty(const _Name: string): string; overload; + class function GetStringProperty(_Instance: TObject; const _Name: string): string; overload; + ///<summary> + /// Sets a string property, returns true on success + /// @param Name is the name of the property to set + /// @param Value is the value to set the property to + /// @returns true, if the property could be set + /// false otherwise </summary> + function SetStringProperty(const _Name: string; const _Value: string): Boolean; overload; + class function SetStringProperty(_Instance: TObject; const _Name: string; const _Value: string): Boolean; overload; + + ///<summary> + /// Access a boolean property + /// @param Name is the name of the property + /// @param Value is the value of the property, only valid if Result is true + /// @returns true, if the property exists and is an enum(!) property + /// false if it either doesn't exist or has a different type + /// Note: It is not possible to distinguish between Boolean and any other enum type + /// So, this will Get or Set any enum property. </summary> + function TryGetBoolProperty(const _Name: string; out _Value: Boolean): Boolean; overload; + class function TryGetBoolProperty(_Instance: TObject; const _Name: string; out _Value: Boolean): Boolean; overload; + function GetBoolProperty(const _Name: string): Boolean; overload; + class function GetBoolProperty(_Instance: TObject; const _Name: string): Boolean; overload; + function SetBoolProperty(const _Name: string; _Value: Boolean): Boolean; overload; + class function SetBoolProperty(_Instance: TObject; const _Name: string; _Value: Boolean): Boolean; overload; + + ///<summary> + /// Access a float property + /// @param Name is the name of the property + /// @param Value is the value of the property, only valid if Result is true + /// @returns true, if the property exists and is a float property + /// false if it either doesn't exist or has a different type </summary> +{$IFDEF SUPPORTS_EXTENDED} + function TryGetFloatProperty(const _Name: string; out _Value: Extended): Boolean; overload; +{$ENDIF} + function TryGetFloatProperty(const _Name: string; out _Value: Double): Boolean; overload; + function TryGetFloatProperty(const _Name: string; out _Value: Single): Boolean; overload; +{$IFDEF SUPPORTS_EXTENDED} + function GetFloatProperty(const _Name: string; const _Default: Extended): Extended; overload; + function GetFloatProperty(const _Name: string): Extended; overload; +{$ELSE} + function GetFloatProperty(const _Name: string; const _Default: Double): Double; overload; + function GetFloatProperty(const _Name: string): Double; overload; +{$ENDIF} + + ///<summary> + /// Access an integer property + /// @param Name is the name of the property + /// @param Value is the value of the property, only valid if Result is true + /// @returns true, if the property exists and is an integer property + /// false if it either doesn't exist or has a different type </summary> + function TryGetIntProperty(const _Name: string; out _Value: Integer): Boolean; overload; + class function TryGetIntProperty(_Instance: TObject; const _Name: string; out _Value: Integer): Boolean; overload; + function GetIntProperty(const _Name: string): Integer; overload; + class function GetIntProperty(_Instance: TObject; const _Name: string): Integer; overload; + function SetIntProperty(const _Name: string; _Value: Integer): Boolean; overload; + class function SetIntProperty(_Instance: TObject; const _Name: string; _Value: Integer): Boolean; overload; + + ///<summary> + /// Access an enum property + /// @param Name is the name of the property + /// @param Value is the value of the property, only valid if Result is true + /// Note: The value must be type cast to the appropriate enum type + /// @returns true, if the property exists and is an enum property + /// false if it either doesn't exist or has a different type </summary> + function TryGetEnumProperty(const _Name: string; out _Value: Integer): Boolean; overload; + class function TryGetEnumProperty(_Instance: TObject; const _Name: string; out _Value: Integer): Boolean; overload; + function GetEnumProperty(const _Name: string): Integer; overload; + class function GetEnumProperty(_Instance: TObject; const _Name: string): Integer; overload; + function SetEnumProperty(const _Name: string; _Value: Integer): Boolean; overload; + class function SetEnumProperty(_Instance: TObject; const _Name: string; _Value: Integer): Boolean; overload; + + ///<summary> + /// Access an object reference property + /// @param Name is the name of the property + /// @param Value is the value of the property, only valid if Result is true + /// @returns true, if the property exists and is an object reference property + /// false if it either doesn't exist or has a different type </summary> + function TryGetObjectProperty(const _Name: string; out _Value: TObject): Boolean; overload; + class function TryGetObjectProperty(_Instance: TObject; const _Name: string; out _Value: TObject): Boolean; overload; + function GetObjectProperty(const _Name: string; _Default: TObject): TObject; overload; + class function GetObjectProperty(_Instance: TObject; const _Name: string; _Default: TObject): TObject; overload; + function GetObjectProperty(const _Name: string): TObject; overload; + class function GetObjectProperty(_Instance: TObject; const _Name: string): TObject; overload; + + ///<summary> + /// Access an event property + /// @param Name is the name of the property + /// @param Value is the value of the property, only valid if Result is true + /// @returns true, if the property exists and is an event property + /// false if it either doesn't exist or has a different type </summary> + function TryGetEventProperty(const _Name: string; out _Value: TMethod): Boolean; + function GetEventProperty(const _Name: string; _Default: TMethod): TMethod; overload; + function GetEventProperty(const _Name: string): TMethod; overload; + + ///<summary> + /// Sets an event property, returns true on success </summary> + function SetEventProperty(const _Name: string; _Value: TMethod): Boolean; overload; + class function SetEventProperty(_Instance: TObject; const _Name: string; _Value: TMethod): Boolean; overload; + + function GetProperties: TStringArray; + + function TryGetEnumValues(const _Name: string; _sl: TStrings): Boolean; overload; + class function TryGetEnumValues(_Instance: TObject; const _Name: string; _sl: TStrings): Boolean; overload; + procedure GetEnumValues(const _Name: string; _sl: TStrings); overload; + class procedure GetEnumValues(_Instance: TObject; const _Name: string; _sl: TStrings); overload; + end; +{$M-} +{$ENDIF DELPHI2007_UP} + +implementation + +{$IFDEF DELPHI2007_UP} + +uses + u_dzTypInfo; + +{ TAdvancedObject } + +function TAdvancedObject.GetEventProperty(const _Name: string; _Default: TMethod): TMethod; +begin + Result := u_dzTypInfo.GetEventProperty(Self, _Name, _Default); +end; + +class procedure TAdvancedObject.CheckHasEnumProperty(_Instance: TObject; const _Name: string); +begin + if not HasEnumProperty(_Instance, _Name) then + raise EPropertyNotFound.CreateFmt(dzlibGetText('Class "%s" has no published %s property "%s".'), + [_Instance.ClassName, 'Enum', _Name]); +end; + +class procedure TAdvancedObject.CheckHasIntProperty(_Instance: TObject; const _Name: string); +begin + if not HasIntProperty(_Instance, _Name) then + raise EPropertyNotFound.CreateFmt(dzlibGetText('Class "%s" has no published %s property "%s".'), + [_Instance.ClassName, 'Integer', _Name]); +end; + +function TAdvancedObject.GetBoolProperty(const _Name: string): Boolean; +begin + Result := GetBoolProperty(Self, _Name); +end; + +class function TAdvancedObject.GetBoolProperty(_Instance: TObject; const _Name: string): Boolean; +begin + if not TryGetBoolProperty(_Instance, _Name, Result) then + raise EPropertyNotFound.CreateFmt(dzlibGetText('Class "%s" has no published %s property "%s".'), + [_Instance.ClassName, 'Enum', _Name]); +end; + +class function TAdvancedObject.GetEnumProperty(_Instance: TObject; const _Name: string): Integer; +begin + if not TryGetEnumProperty(_Instance, _Name, Result) then + raise EPropertyNotFound.CreateFmt(dzlibGetText('Class "%s" has no published %s property "%s".'), + [_Instance.ClassName, 'Enum', _Name]); +end; + +function TAdvancedObject.GetEnumProperty(const _Name: string): Integer; +begin + Result := GetEnumProperty(Self, _Name); +end; + +function TAdvancedObject.GetEventProperty(const _Name: string): TMethod; +begin + Result := u_dzTypInfo.GetEventProperty(Self, _Name); +end; + +function TAdvancedObject.SetEventProperty(const _Name: string; _Value: TMethod): Boolean; +begin + Result := SetEventProperty(Self, _Name, _Value); +end; + +class function TAdvancedObject.SetBoolProperty(_Instance: TObject; const _Name: string; + _Value: Boolean): Boolean; +var + PropInfo: PPropInfo; + Value: NativeInt; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkEnumeration); + if Result then begin + Value := NativeInt(_Value); + TypInfo.SetOrdProp(_Instance, PropInfo, Value); + end; +end; + +function TAdvancedObject.SetBoolProperty(const _Name: string; _Value: Boolean): Boolean; +begin + Result := SetBoolProperty(Self, _Name, _Value); +end; + +class function TAdvancedObject.SetEnumProperty(_Instance: TObject; const _Name: string; + _Value: Integer): Boolean; +var + PropInfo: PPropInfo; + Value: NativeInt; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkEnumeration); + if Result then begin + Value := NativeInt(_Value); + TypInfo.SetOrdProp(_Instance, PropInfo, Value); + end; +end; + +function TAdvancedObject.SetEnumProperty(const _Name: string; _Value: Integer): Boolean; +begin + Result := SetEnumProperty(Self, _Name, _Value); +end; + +class function TAdvancedObject.SetEventProperty(_Instance: TObject; const _Name: string; + _Value: TMethod): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkMethod); + if Result then + TypInfo.SetMethodProp(_Instance, PropInfo, _Value); +end; + +function TAdvancedObject.SetIntProperty(const _Name: string; _Value: Integer): Boolean; +begin + Result := SetIntProperty(Self, _Name, _Value); +end; + +class function TAdvancedObject.SetIntProperty(_Instance: TObject; const _Name: string; + _Value: Integer): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkInteger); + if Result then + TypInfo.SetOrdProp(_Instance, PropInfo, _Value); +end; + +{$IFDEF SUPPORTS_EXTENDED} +function TAdvancedObject.GetFloatProperty(const _Name: string; const _Default: Extended): Extended; +begin + Result := u_dzTypInfo.GetFloatProperty(Self, _Name, _Default); +end; + +function TAdvancedObject.GetFloatProperty(const _Name: string): Extended; +begin + Result := u_dzTypInfo.GetFloatProperty(Self, _Name); +end; +{$ELSE} +function TAdvancedObject.GetFloatProperty(const _Name: string; const _Default: Double): Double; overload; +begin + Result := u_dzTypInfo.GetFloatProperty(Self, _Name, _Default); +end; + +function TAdvancedObject.GetFloatProperty(const _Name: string): Double; overload; +begin + Result := u_dzTypInfo.GetFloatProperty(Self, _Name); +end; +{$ENDIF} + +function TAdvancedObject.GetIntProperty(const _Name: string): Integer; +begin + Result := GetIntProperty(Self, _Name); +end; + +class function TAdvancedObject.GetIntProperty(_Instance: TObject; const _Name: string): Integer; +begin + if not TryGetIntProperty(_Instance, _Name, Result) then + raise EPropertyNotFound.CreateFmt(dzlibGetText('Class "%s" has no published %s property "%s".'), + [_Instance.ClassName, 'Integer', _Name]); +end; + +class function TAdvancedObject.GetObjectProperty(_Instance: TObject; const _Name: string; + _Default: TObject): TObject; +begin + Result := u_dzTypInfo.GetObjectProperty(_Instance, _Name, _Default); +end; + +function TAdvancedObject.GetObjectProperty(const _Name: string; _Default: TObject): TObject; +begin + Result := GetObjectProperty(Self, _Name, _Default); +end; + +class function TAdvancedObject.GetObjectProperty(_Instance: TObject; const _Name: string): TObject; +begin + Result := u_dzTypInfo.GetObjectProperty(_Instance, _Name); +end; + +function TAdvancedObject.GetObjectProperty(const _Name: string): TObject; +begin + Result := GetObjectProperty(Self, _Name); +end; + +function TAdvancedObject.GetStringProperty(const _Name, _Default: string): string; +begin + Result := u_dzTypInfo.GetStringProperty(Self, _Name, _Default); +end; + +class function TAdvancedObject.GetStringProperty(_Instance: TObject; const _Name, _Default: string): string; +begin + if not TryGetStringProperty(_Instance, _Name, Result) then + Result := _Default; +end; + +class function TAdvancedObject.GetStringProperty(_Instance: TObject; const _Name: string): string; +begin + if not TryGetStringProperty(_Instance, _Name, Result) then + raise EPropertyNotFound.CreateFmt(dzlibGetText('Class "%s" has no published %s property "%s".'), + [_Instance.ClassName, 'String', _Name]); +end; + +function TAdvancedObject.GetStringProperty(const _Name: string): string; +begin + Result := u_dzTypInfo.GetStringProperty(Self, _Name); +end; + +function TAdvancedObject.HasEventProperty(const _Name: string): Boolean; +begin + Result := HasEventProperty(Self, _Name); +end; + +function TAdvancedObject.HasEnumProperty(const _Name: string): Boolean; +begin + Result := HasEnumProperty(Self, _Name); +end; + +class function TAdvancedObject.HasEnumProperty(_Instance: TObject; const _Name: string): Boolean; +var + Kind: TTypeKind; +begin + Result := HasProperty(_Instance, _Name, Kind) and (Kind = tkEnumeration); +end; + +class function TAdvancedObject.HasEventProperty(_Instance: TObject; const _Name: string): Boolean; +var + Kind: TTypeKind; +begin + Result := HasProperty(_Instance, _Name, Kind) and (Kind = tkMethod); +end; + +class function TAdvancedObject.HasFloatProperty(_Instance: TObject; const _Name: string): Boolean; +var + Kind: TTypeKind; +begin + Result := HasProperty(_Instance, _Name, Kind) and (Kind in FLOAT_PROPERTY_TYPES); +end; + +function TAdvancedObject.HasFloatProperty(const _Name: string): Boolean; +begin + Result := HasFloatProperty(Self, _Name); +end; + +class function TAdvancedObject.HasIntProperty(_Instance: TObject; const _Name: string): Boolean; +var + Kind: TTypeKind; +begin + Result := HasProperty(_Instance, _Name, Kind) and (Kind = tkInteger); +end; + +function TAdvancedObject.HasIntProperty(const _Name: string): Boolean; +begin + Result := HasIntProperty(Self, _Name); +end; + +class function TAdvancedObject.HasObjectProperty(_Instance: TObject; const _Name: string): Boolean; +var + Kind: TTypeKind; +begin + Result := HasProperty(_Instance, _Name, Kind) and (Kind = tkClass); +end; + +function TAdvancedObject.HasObjectProperty(const _Name: string): Boolean; +begin + Result := HasObjectProperty(Self, _Name); +end; + +class function TAdvancedObject.HasProperty(_Instance: TObject; const _Name: string; + out _Type: TTypeKind): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo); + if Result then + _Type := PropInfo.PropType^.Kind; +end; + +function TAdvancedObject.HasProperty(const _Name: string; out _Type: TTypeKind): Boolean; +begin + Result := HasProperty(Self, _Name, _Type); +end; + +class function TAdvancedObject.HasStringProperty(_Instance: TObject; const _Name: string): Boolean; +var + Kind: TTypeKind; +begin + Result := HasProperty(_Instance, _Name, Kind) and (Kind in STRING_PROPERTY_TYPES); +end; + +function TAdvancedObject.HasStringProperty(const _Name: string): Boolean; +begin + Result := HasStringProperty(_Name); +end; + +class function TAdvancedObject.SetStringProperty(_Instance: TObject; const _Name, _Value: string): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind in STRING_PROPERTY_TYPES); + if Result then + TypInfo.SetStrProp(_Instance, PropInfo, _Value); +end; + +function TAdvancedObject.SetStringProperty(const _Name, _Value: string): Boolean; +begin + Result := SetStringProperty(Self, _Name, _Value); +end; + +class function TAdvancedObject.TryGetBoolProperty(_Instance: TObject; const _Name: string; + out _Value: Boolean): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkEnumeration); + if Result then + _Value := GetOrdProp(_Instance, PropInfo) <> 0; +end; + +function TAdvancedObject.TryGetBoolProperty(const _Name: string; out _Value: Boolean): Boolean; +begin + Result := TryGetBoolProperty(Self, _Name, _Value); +end; + +class function TAdvancedObject.TryGetEnumProperty(_Instance: TObject; const _Name: string; + out _Value: Integer): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkEnumeration); + if Result then + _Value := GetOrdProp(_Instance, PropInfo); +end; + +function TAdvancedObject.TryGetEnumProperty(const _Name: string; out _Value: Integer): Boolean; +begin + Result := TryGetEnumProperty(Self, _Name, _Value); +end; + +function TAdvancedObject.TryGetEventProperty(const _Name: string; out _Value: TMethod): Boolean; +begin + Result := u_dzTypInfo.TryGetEventProperty(Self, _Name, _Value); +end; + +{$IFDEF SUPPORTS_EXTENDED} +function TAdvancedObject.TryGetFloatProperty(const _Name: string; out _Value: Extended): Boolean; +begin + Result := u_dzTypInfo.TryGetFloatProperty(Self, _Name, _Value); +end; +{$ENDIF} + +function TAdvancedObject.TryGetFloatProperty(const _Name: string; out _Value: Double): Boolean; +begin + Result := u_dzTypInfo.TryGetFloatProperty(Self, _Name, _Value); +end; + +function TAdvancedObject.TryGetFloatProperty(const _Name: string; out _Value: Single): Boolean; +begin + Result := u_dzTypInfo.TryGetFloatProperty(Self, _Name, _Value); +end; + +class function TAdvancedObject.TryGetIntProperty(_Instance: TObject; const _Name: string; + out _Value: Integer): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkInteger); + if Result then + _Value := GetOrdProp(_Instance, PropInfo); +end; + +function TAdvancedObject.TryGetIntProperty(const _Name: string; out _Value: Integer): Boolean; +begin + Result := TryGetIntProperty(Self, _Name, _Value); +end; + +class function TAdvancedObject.TryGetObjectProperty(_Instance: TObject; const _Name: string; + out _Value: TObject): Boolean; +begin + Result := u_dzTypInfo.TryGetObjectProperty(_Instance, _Name, _Value); +end; + +function TAdvancedObject.TryGetObjectProperty(const _Name: string; out _Value: TObject): Boolean; +begin + Result := TryGetObjectProperty(Self, _Name, _Value); +end; + +class function TAdvancedObject.TryGetStringProperty(_Instance: TObject; const _Name: string; + out _Value: string): Boolean; +begin + Result := u_dzTypInfo.TryGetStringProperty(_Instance, _Name, _Value); +end; + +function TAdvancedObject.TryGetStringProperty(const _Name: string; out _Value: string): Boolean; +begin + Result := TryGetStringProperty(Self, _Name, _Value); +end; + +function TAdvancedObject.GetProperties: TStringArray; +var + Props: PPropList; + cnt: Integer; + i: Integer; + PropInfo: PPropInfo; +begin + cnt := GetPropList(Self, Props); + try + SetLength(Result, cnt); + for i := 0 to cnt - 1 do begin + PropInfo := Props^[i]; + Result[i] := String(PropInfo.Name); + end; + finally + FreeMem(Props); + end; +end; + +class function TAdvancedObject.TryGetEnumValues(_Instance: TObject; const _Name: string; + _sl: TStrings): Boolean; +begin + Result := u_dzTypInfo.TryGetEnumValues(_Instance, _Name, _sl); +end; + +function TAdvancedObject.TryGetEnumValues(const _Name: string; _sl: TStrings): Boolean; +begin + Result := TryGetEnumValues(Self, _Name, _sl); +end; + +class procedure TAdvancedObject.GetEnumValues(_Instance: TObject; const _Name: string; + _sl: TStrings); +begin + u_dzTypInfo.GetEnumValues(_Instance, _Name, _sl); +end; + +procedure TAdvancedObject.GetEnumValues(const _Name: string; _sl: TStrings); +begin + GetEnumValues(Self, _Name, _sl); +end; + +{$ENDIF DELPHI2007_UP} + +end. + Modified: trunk/ExternalSource/dzlib/u_dzClassUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzClassUtils.pas 2021-09-30 15:34:25 UTC (rev 3635) +++ trunk/ExternalSource/dzlib/u_dzClassUtils.pas 2021-10-01 15:53:08 UTC (rev 3636) @@ -58,7 +58,7 @@ ///<summary> /// Creates a TStringList from the given array of string. /// @NOTE: This function is deprecated, se the overload with a SortHandling parameter </summary> -function TStringList_CreateFrom(const _sa: array of string; _Sorted: Boolean = False): TStringList; overload; deprecated; +function TStringList_CreateFrom(const _sa: array of string; _Sorted: Boolean): TStringList; overload; deprecated; ///<summary> /// Creates a TStringList from the given array of string. </summary> function TStringList_CreateFrom(const _sa: array of string; @@ -435,6 +435,15 @@ /// <summary> /// Reads the given section from the given .INI file and returns all its keys as a TStrings /// (This is short for opening the file, calling Ini.ReadSection and closing it.) +/// @returns false, if the section does not exist. </summary> +function TIniFile_TryReadSectionKeys(const _Filename, _Section: string; _sl: TStrings): Boolean; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} + +/// <summary> +/// Reads the given section from the given .INI file and returns all its keys as a TStrings +/// (This is short for opening the file, calling Ini.ReadSection and closing it.) /// @raises Exception if the section does not exist. </summary> procedure TIniFile_ReadSectionKeys(const _Filename, _Section: string; _sl: TStrings); {$IFDEF SUPPORTS_INLINE} @@ -1625,24 +1634,32 @@ end; end; -procedure TIniFile_ReadSectionKeys(const _Filename, _Section: string; _sl: TStrings); +function TIniFile_TryReadSectionKeys(const _Filename, _Section: string; _sl: TStrings): Boolean; var Ini: TMemIniFile; - ErrStr: string; begin Ini := TMemIniFile.Create(_Filename); try - if not Ini.SectionExists(_Section) then begin - ErrStr := Format(_('Section "%s" does not exist in ini file'), [_Section]) - + ' ' + _Filename; - raise Exception.Create(ErrStr); + Result := Ini.SectionExists(_Section); + if Result then begin + Ini.ReadSection(_Section, _sl); end; - Ini.ReadSection(_Section, _sl); finally FreeAndNil(Ini); end; end; +procedure TIniFile_ReadSectionKeys(const _Filename, _Section: string; _sl: TStrings); +var + ErrStr: string; +begin + if not TIniFile_TryReadSectionKeys(_Filename, _Section, _sl) then begin + ErrStr := Format(_('Section "%s" does not exist in ini file'), [_Section]) + + ' ' + _Filename; + raise Exception.Create(ErrStr); + end; +end; + function TIniFile_TryReadSectionValues(const _Filename, _Section: string; _sl: TStrings): Boolean; var Ini: TMemIniFile; @@ -1690,10 +1707,10 @@ end; end else begin for i := _Sections.Count - 1 downto 0 do begin - s := _Sections[i]; + s := _Sections[i]; if not SameText(Copy(s, 1, Len), _Section) or (Copy(s, Len + 1, 1) <> '\') then _Sections.Delete(i) - else begin + else begin s := TailStr(s, Len + 2); if (s = '') or (Pos('\', s) > 0) then _Sections.Delete(i) @@ -2239,7 +2256,7 @@ end; end; -function TStringList_CreateFrom(const _sa: array of string; _Sorted: Boolean = False): TStringList; +function TStringList_CreateFrom(const _sa: array of string; _Sorted: Boolean): TStringList; var SortHandling: TStringListSortHandling; begin Added: trunk/ExternalSource/dzlib/u_dzDpiScaleUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzDpiScaleUtils.pas (rev 0) +++ trunk/ExternalSource/dzlib/u_dzDpiScaleUtils.pas 2021-10-01 15:53:08 UTC (rev 3636) @@ -0,0 +1,245 @@ +unit u_dzDpiScaleUtils; + +interface + +uses + Windows, + SysUtils, + Classes, + Graphics, + Forms, + Controls, + Types; + +type + TDpiScaler = record + private + FDesignDpi: Integer; + FCurrentDpi: Integer; + public + procedure Init(_frm: TCustomForm); overload; inline; + procedure Init(_Dpi: Integer); overload; inline; + procedure Init(_DesignDpi, _CurrentDpi: Integer); overload; inline; + procedure SetCurrentDpi(_frm: TCustomForm); overload; inline; + procedure SetCurrentDpi(_Dpi: Integer); overload; inline; + function Calc(_Value: Integer): Integer; overload; inline; + function Calc(const _Value: TRect): TRect; overload; inline; + end; + +type + TCtrlDpiScaler = record + Ctrl: TControl; + BoundsRect: TRect; + FontSize: Integer; + procedure Assign(_ctrl: TControl); + procedure ApplyScale(const _Scaler: TDpiScaler); + procedure ResizeFont(const _Scaler: TDpiScaler); + end; + + TFormDpiScaler = class + private + DesignDPI: Integer; + Width, Height: Integer; + FontSize: Integer; + FFrm: TForm; + CtrlParams: array of TCtrlDpiScaler; + procedure AddControls(_ctrl: TWinControl); + public + constructor Create(_frm: TForm); + procedure ApplyScale(const _Scaler: TDpiScaler); + procedure ApplyDpi(_NewDpi: Integer; _NewBounds: PRect); + end; + +implementation + +uses + u_dzAdvancedObject, + u_dzVclUtils; + +{ TDpiScaler } + +function TDpiScaler.Calc(_Value: Integer): Integer; +begin + Result := MulDiv(_Value, FCurrentDpi, FDesignDpi); +end; + +function TDpiScaler.Calc(const _Value: TRect): TRect; +begin + Result.Left := Calc(_Value.Left); + Result.Top := Calc(_Value.Top); + Result.Right := Calc(_Value.Right); + Result.Bottom := Calc(_Value.Bottom); +end; + +procedure TDpiScaler.Init(_Dpi: Integer); +begin + FDesignDpi := _Dpi; + FCurrentDpi := _Dpi; +end; + +procedure TDpiScaler.Init(_DesignDpi, _CurrentDpi: Integer); +begin + FDesignDpi := _DesignDpi; + FCurrentDpi := _CurrentDpi; +end; + +procedure TDpiScaler.Init(_frm: TCustomForm); +begin + if not Assigned(_frm) then begin + FDesignDpi := 96; + FCurrentDpi := 96; + end else begin +// todo: adjust as needed +{$IFDEF DELPHIX_TOKYO_UP} + FDesignDpi := TForm_GetDesignDPI(TForm(_frm)); + FCurrentDpi := TScreen_GetDpiForForm(_frm); +{$ELSE ~DELPHIX_TOKYO_UP} + FDesignDpi := TForm(_frm).PixelsPerInch; + FCurrentDpi := TForm(_frm).PixelsPerInch; +{$ENDIF DELPHIX_TOKYO_UP} + end; +end; + +procedure TDpiScaler.SetCurrentDpi(_Dpi: Integer); +begin + FCurrentDpi := _Dpi; +end; + +procedure TDpiScaler.SetCurrentDpi(_frm: TCustomForm); +begin + if not Assigned(_frm) then begin + FCurrentDpi := 96; + end else begin +// todo: adjust as needed +{$IFDEF DELPHIX_TOKYO_UP} + FCurrentDpi := TScreen_GetDpiForForm(_frm) +{$ELSE ~DELPHIX_TOKYO_UP} + FCurrentDpi := TForm(_frm).PixelsPerInch; +{$ENDIF DELPHIX_TOKYO_UP} + end; +end; + +{ TCtrlDpiScaler } + +function GetFontSize(_fnt: TFont): Integer; +begin +// Result := _fnt.Size; + Result := _fnt.Height; +end; + +procedure SetFontSize(_fnt: TFont; _Size: Integer); +begin +// _fnt.Size := _Size; + _fnt.Height := _Size; +end; + +procedure TCtrlDpiScaler.ApplyScale(const _Scaler: TDpiScaler); +var + br: TRect; +begin + br := _Scaler.Calc(BoundsRect); + Ctrl.BoundsRect := br; + ResizeFont(_Scaler); +end; + +procedure TCtrlDpiScaler.Assign(_ctrl: TControl); +var + fnt: TFont; +begin + Ctrl := _ctrl; + BoundsRect := Ctrl.BoundsRect; + if not TAdvancedObject.TryGetObjectProperty(_ctrl, 'Font', TObject(fnt)) then begin + FontSize := 0; + end else begin + FontSize := GetFontSize(fnt); + end; +end; + +procedure TCtrlDpiScaler.ResizeFont(const _Scaler: TDpiScaler); +var + fnt: TFont; + ParentFontValue: Boolean; +begin + if TAdvancedObject.TryGetObjectProperty(Ctrl, 'Font', TObject(fnt)) then begin + if not TAdvancedObject.TryGetBoolProperty(Ctrl, 'ParentFont', ParentFontValue) + or not ParentFontValue then begin + Assert(FontSize <> 0); + SetFontSize(fnt, _Scaler.Calc(FontSize)); + end; + end; +end; + +{ TFormDpiScaler } + +procedure TFormDpiScaler.AddControls(_ctrl: TWinControl); +var + Offset: Integer; + i: Integer; + cnt: Integer; + Ctrl: TControl; +begin + cnt := _ctrl.ControlCount; + Offset := Length(CtrlParams); + SetLength(CtrlParams, Offset + cnt); + for i := 0 to cnt - 1 do begin + Ctrl := _ctrl.Controls[i]; + CtrlParams[Offset + i].Assign(Ctrl); + if Ctrl is TWinControl then + AddControls(TWinControl(Ctrl)); + end; +end; + +procedure TFormDpiScaler.ApplyDpi(_NewDpi: Integer; _NewBounds: PRect); +var + Scaler: TDpiScaler; + br: TRect; + RedrawLock: IInterface; +begin + if not Assigned(FFrm) then + Exit; //==> + + RedrawLock := TWinControl_Lock(FFrm); + try + Scaler.Init(DesignDPI, _NewDpi); + if Assigned(_NewBounds) then begin + FFrm.BoundsRect := _NewBounds^; + end else begin + br := FFrm.BoundsRect; + br.Width := Scaler.Calc(br.Width); + br.Height := Scaler.Calc(br.Height); + FFrm.BoundsRect := br; + end; + ApplyScale(Scaler); + finally + RedrawLock := nil; + end; +end; + +procedure TFormDpiScaler.ApplyScale(const _Scaler: TDpiScaler); +var + cnt: Integer; + i: Integer; +begin + SetFontSize(FFrm.Font, _Scaler.Calc(FontSize)); + cnt := Length(CtrlParams); + for i := 0 to cnt - 1 do begin + CtrlParams[i].ApplyScale(_Scaler); + end; +end; + +constructor TFormDpiScaler.Create(_frm: TForm); +var + Scaler: TDpiScaler; +begin + inherited Create; + FFrm := _frm; + Width := _frm.ClientWidth; + Height := _frm.ClientHeight; + FontSize := GetFontSize(_frm.Font); + DesignDPI := TForm_GetDesignDPI(_frm); + Scaler.Init(_frm.Font.PixelsPerInch, DesignDPI); + FontSize := Scaler.Calc(FontSize); + AddControls(FFrm); +end; + +end. Modified: trunk/ExternalSource/dzlib/u_dzOsUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzOsUtils.pas 2021-09-30 15:34:25 UTC (rev 3635) +++ trunk/ExternalSource/dzlib/u_dzOsUtils.pas 2021-10-01 15:53:08 UTC (rev 3636) @@ -16,6 +16,7 @@ EOsFunc = class(EdzException); EOFNoFileinfo = class(EOsFunc); EPowerRequestFailed = class(EOsFunc) + public ErrorCode: Word; end; Added: trunk/ExternalSource/dzlib/u_dzTypInfo.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzTypInfo.pas (rev 0) +++ trunk/ExternalSource/dzlib/u_dzTypInfo.pas 2021-10-01 15:53:08 UTC (rev 3636) @@ -0,0 +1,320 @@ +unit u_dzTypInfo; + +{$INCLUDE 'dzlib.inc'} + +interface + +{$IFNDEF DELPHI2007_UP} +{$IFNDEF NO_DELPHI2007UP_HINT} +{$MESSAGE HINT 'Delphi <2007 not supported'} +{$ENDIF} +{$ELSE} + +uses + SysUtils, + Classes, + TypInfo, + u_dzTranslator; + + // I am not going to proved support for Variant properties here. I hate Variants. + +const + ///<summary> property types that can be converted to string </summary> + STRING_PROPERTY_TYPES = [ +{$IFDEF FPC} + tkAString, + tkUString, +{$ENDIF} +{$IFDEF SUPPORTS_UNICODE} + tkUString, +{$ENDIF SUPPORTS_UNICODE} + tkChar, tkString, tkWChar, tkLString, tkWString]; + ///<summary> property types that can be converted to float </summary> + FLOAT_PROPERTY_TYPES = [tkInteger, tkFloat]; + +const + NilMethod: TMethod = (Code: nil; Data: nil); + +function TryGetStringProperty(_Instance: TObject; const _Name: string; out _Value: string): Boolean; +function GetStringProperty(_Instance: TObject; const _Name: string; const _Default: string): string; overload; +function GetStringProperty(_Instance: TObject; const _Name: string): string; overload; + +{$IFDEF SUPPORTS_EXTENDED} +function TryGetFloatProperty(_Instance: TObject; const _Name: string; out _Value: Extended): Boolean; overload; +{$ENDIF} +function TryGetFloatProperty(_Instance: TObject; const _Name: string; out _Value: Double): Boolean; overload; +function TryGetFloatProperty(_Instance: TObject; const _Name: string; out _Value: Single): Boolean; overload; + +function TryGetIntProperty(_Instance: TObject; const _Name: string; out _Value: Integer): Boolean; +function TrySetIntProperty(_Instance: TObject; const _Name: string; _Value: Integer): Boolean; +function TryGetBoolProperty(_Instance: TObject; const _Name: string; out _Value: Boolean): Boolean; +///<summary> +/// Reads an enum type property with type checking. +/// @param TypeInfo is the PTypeInfo for the enum, pass TypeInfo(YourEnumType) here </summary> +function TryGetEnumProperty(_Instance: TObject; const _Name: string; const _TypeInfo: PTypeInfo; + out _Value: Integer): Boolean; overload; +///<summary> +/// Reads an enum type property without type checking </summary> +function TryGetEnumProperty(_Instance: TObject; const _Name: string; + out _Value: Integer): Boolean; overload; + +{$IFDEF SUPPORTS_EXTENDED} +function GetFloatProperty(_Instance: TObject; const _Name: string; const _Default: Extended): Extended; overload; +function GetFloatProperty(_Instance: TObject; const _Name: string): Extended; overload; +{$ELSE} +function GetFloatProperty(_Instance: TObject; const _Name: string; const _Default: Double): Double; overload; +function GetFloatProperty(_Instance: TObject; const _Name: string): Double; overload; +{$ENDIF SUPPORTS_EXTENDED} + +function TryGetObjectProperty(_Instance: TObject; const _Name: string; out _Value: TObject): Boolean; +function GetObjectProperty(_Instance: TObject; const _Name: string; _Default: TObject): TObject; overload; +function GetObjectProperty(_Instance: TObject; const _Name: string): TObject; overload; + +function TryGetEventProperty(_Instance: TObject; const _Name: string; out _Value: TMethod): Boolean; +function GetEventProperty(_Instance: TObject; const _Name: string; _Default: TMethod): TMethod; overload; +function GetEventProperty(_Instance: TObject; const _Name: string): TMethod; overload; +function TrySetEventProperty(_Instance: TObject; const _Name: string; _Value: TMethod): Boolean; +procedure SetEventProperty(_Instance: TObject; const _Name: string; _Value: TMethod); + +function TryGetEnumValues(_Instance: TObject; const _Name: string; _sl: TStrings): Boolean; +procedure GetEnumValues(_Instance: TObject; const _Name: string; _sl: TStrings); + +{$ENDIF DELPHI2007_UP} + +implementation + +{$IFDEF DELPHI2007_UP} + +function _(const _s: string): string; inline; +begin + Result := dzlibGetText(_s); +end; + +function TryGetStringProperty(_Instance: TObject; const _Name: string; out _Value: string): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind in STRING_PROPERTY_TYPES); + if Result then + _Value := GetPropValue(_Instance, PropInfo) +end; + +function GetStringProperty(_Instance: TObject; const _Name: string; const _Default: string): string; +begin + if not TryGetStringProperty(_Instance, _Name, Result) then + Result := _Default; +end; + +function GetStringProperty(_Instance: TObject; const _Name: string): string; overload; +begin + if not TryGetStringProperty(_Instance, _Name, Result) then + raise EPropertyError.CreateFmt(_('String property %s not found.'), [_Name]); +end; + +{$IFDEF SUPPORTS_EXTENDED} +function TryGetFloatProperty(_Instance: TObject; const _Name: string; out _Value: Extended): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind in FLOAT_PROPERTY_TYPES); + if Result then + _Value := GetPropValue(_Instance, PropInfo) +end; +{$ENDIF} + +function TryGetFloatProperty(_Instance: TObject; const _Name: string; out _Value: Double): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind in FLOAT_PROPERTY_TYPES); + if Result then + _Value := GetPropValue(_Instance, PropInfo) +end; + +function TryGetFloatProperty(_Instance: TObject; const _Name: string; out _Value: Single): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind in FLOAT_PROPERTY_TYPES); + if Result then + _Value := GetPropValue(_Instance, PropInfo) +end; + +{$IFDEF SUPPORTS_EXTENDED} +function GetFloatProperty(_Instance: TObject; const _Name: string; const _Default: Extended): Extended; +begin + if not TryGetFloatProperty(_Instance, _Name, Result) then + Result := _Default; +end; + +function GetFloatProperty(_Instance: TObject; const _Name: string): Extended; +begin + if not TryGetFloatProperty(_Instance, _Name, Result) then + raise EPropertyError.CreateFmt(_('Float property %s not found.'), [_Name]); +end; +{$ELSE} +function GetFloatProperty(_Instance: TObject; const _Name: string; const _Default: Double): Double; +begin + if not TryGetFloatProperty(_Instance, _Name, Result) then + Result := _Default; +end; + +function GetFloatProperty(_Instance: TObject; const _Name: string): Double; +begin + if not TryGetFloatProperty(_Instance, _Name, Result) then + raise EPropertyError.CreateFmt(_('Float property %s not found.'), [_Name]); +end; +{$ENDIF} + +function TryGetIntProperty(_Instance: TObject; const _Name: string; out _Value: Integer): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkInteger); + if Result then + _Value := GetOrdProp(_Instance, PropInfo); +end; + +function TrySetIntProperty(_Instance: TObject; const _Name: string; _Value: Integer): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkInteger); + if Result then + SetOrdProp(_Instance, PropInfo, _Value); +end; + +function TryGetBoolProperty(_Instance: TObject; const _Name: string; out _Value: Boolean): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkEnumeration) + and (GetTypeData(PropInfo.PropType^)^.BaseType^ = TypeInfo(Boolean)); + if Result then + _Value := Boolean(GetOrdProp(_Instance, PropInfo)); +end; + +function TryGetEnumProperty(_Instance: TObject; const _Name: string; const _TypeInfo: PTypeInfo; + out _Value: Integer): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkEnumeration) + and (GetTypeData(PropInfo.PropType^)^.BaseType^ = _TypeInfo); + if Result then + _Value := GetOrdProp(_Instance, PropInfo); +end; + +function TryGetEnumProperty(_Instance: TObject; const _Name: string; out _Value: Integer): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkEnumeration); + if Result then + _Value := GetOrdProp(_Instance, PropInfo); +end; + +function TryGetObjectProperty(_Instance: TObject; const _Name: string; out _Value: TObject): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkClass); + if Result then + _Value := TObject(GetOrdProp(_Instance, PropInfo)); +end; + +function GetObjectProperty(_Instance: TObject; const _Name: string; _Default: TObject): TObject; +begin + if not TryGetObjectProperty(_Instance, _Name, Result) then + Result := _Default; +end; + +function GetObjectProperty(_Instance: TObject; const _Name: string): TObject; +begin + if not TryGetObjectProperty(_Instance, _Name, Result) then + raise EPropertyError.CreateFmt(_('Object property %s not found.'), [_Name]); +end; + +function TryGetEventProperty(_Instance: TObject; const _Name: string; out _Value: TMethod): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkMethod); + if Result then begin + _Value := GetMethodProp(_Instance, PropInfo); + end; +end; + +function GetEventProperty(_Instance: TObject; const _Name: string; _Default: TMethod): TMethod; +begin + if not TryGetEventProperty(_Instance, _Name, Result) then + Result := _Default; +end; + +function GetEventProperty(_Instance: TObject; const _Name: string): TMethod; +begin + if not TryGetEventProperty(_Instance, _Name, Result) then + raise EPropertyError.CreateFmt(_('Event property %s not found.'), [_Name]); +end; + +function TrySetEventProperty(_Instance: TObject; const _Name: string; _Value: TMethod): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkMethod); + if Result then begin + SetMethodProp(_Instance, PropInfo, _Value); + end; +end; + +procedure SetEventProperty(_Instance: TObject; const _Name: string; _Value: TMethod); +begin + if not TrySetEventProperty(_Instance, _Name, _Value) then + raise EPropertyError.CreateFmt(_('Event property %s not found.'), [_Name]); +end; + +function TryGetEnumValues(_Instance: TObject; const _Name: string; _sl: TStrings): Boolean; +var + T: PTypeData; + i: Integer; + PropInfo: PPropInfo; + PropType: PTypeInfo; +begin + PropInfo := GetPropInfo(_Instance, _Name); + Result := Assigned(PropInfo); + if not Result then + Exit; //==> + + PropType := PropInfo.PropType^; + Result := PropType^.Kind = tkEnumeration; + if not Result then + Exit; //==> + + _sl.Clear; + T := GetTypeData(GetTypeData(PropType).BaseType^); + for i := T.MinValue to T.MaxValue do begin + _sl.AddObject(GetEnumName(PropType, i), Pointer(i)); + end; +end; + +procedure GetEnumValues(_Instance: TObject; const _Name: string; _sl: TStrings); +begin + if not TryGetEnumValues(_Instance, _Name, _sl) then + raise EPropertyError.CreateFmt(_('Enum property %s not found.'), [_Name]); +end; + +{$ENDIF DELPHI2007_UP} + +end. Modified: trunk/ExternalSource/dzlib/u_dzVclUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2021-09-30 15:34:25 UTC (rev 3635) +++ trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2021-10-01 15:53:08 UTC (rev 3636) @@ -86,20 +86,7 @@ end; {$IFEND} -{$IFDEF SUPPORTS_ENHANCED_RECORDS} type - TDpiScaler = record - private - FDesignDpi: Integer; - FCurrentDpi: Integer; - public - procedure Init(_frm: TCustomForm); inline; - procedure SetCurrentDpi(_frm: TCustomForm); inline; - function Calc(_Value: Integer): Integer; inline; - end; -{$ENDIF SUPPORTS_ENHANCED_RECORDS} - -type ///<summary> This is a copy of the TFileFormatsList class from Graphics which /// is unfortunately only declaread in the implementation section </summary> TFileFormatsList = class(TList) @@ -7063,46 +7050,6 @@ end; {$ENDIF} -{$IFDEF SUPPORTS_ENHANCED_RECORDS} -{ TDpiScaler } - -function TDpiScaler.Calc(_Value: Integer): Integer; -begin - Result := MulDiv(_Value, FCurrentDpi, FDesignDpi); -end; - -procedure TDpiScaler.Init(_frm: TCustomForm); -begin - if not Assigned(_frm) then begin - FDesignDpi := 96; - FCurrentDpi := 96; - end else begin -// todo: adjust as needed -{$IFDEF DELPHIX_TOKYO_UP} - FDesignDpi := TForm_GetDesignDPI(TForm(_frm)); - FCurrentDpi := TScreen_GetDpiForForm(_frm); -{$ELSE ~DELPHIX_TOKYO_UP} - FDesignDpi := TForm(_frm).PixelsPerInch; - FCurrentDpi := TForm(_frm).PixelsPerInch; -{$ENDIF DELPHIX_TOKYO_UP} - end; -end; - -procedure TDpiScaler.SetCurrentDpi(_frm: TCustomForm); -begin - if not Assigned(_frm) then begin - FCurrentDpi := 96; - end else begin -// todo: adjust as needed -{$IFDEF DELPHIX_TOKYO_UP} - FCurrentDpi := TScreen_GetDpiForForm(_frm) -{$ELSE ~DELPHIX_TOKYO_UP} - FCurrentDpi := TForm(_frm).PixelsPerInch; -{$ENDIF DELPHIX_TOKYO_UP} - end; -end; -{$ENDIF SUPPORTS_ENHANCED_RECORDS} - initialization InitializeCustomMessages; finalization This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tw...@us...> - 2021-10-20 08:41:52
|
Revision: 3669 http://sourceforge.net/p/gexperts/code/3669 Author: twm Date: 2021-10-20 08:41:49 +0000 (Wed, 20 Oct 2021) Log Message: ----------- updated to latest version from OSDN Modified Paths: -------------- trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas trunk/ExternalSource/dzlib/u_dzVclUtils.pas Modified: trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2021-10-17 16:28:50 UTC (rev 3668) +++ trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2021-10-20 08:41:49 UTC (rev 3669) @@ -128,6 +128,7 @@ {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF} + procedure TdzRgbTriple_SetColor(var _Triple: TdzRgbTriple; _Color: TColor); {$IFDEF SUPPORTS_INLINE} inline; @@ -449,6 +450,14 @@ {$ENDIF} ///<summary> +/// Create an empty Mono8 TBitmap </summary> +function TBitmap_CreateMono8: TBitmap; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} + + +///<summary> /// Calculates the positive y coordinate for the given x coordinate for an ellipse /// with horizontal and vertical axes, centered on the coordinate origin (0/0). /// @param a, b are horizontal and vertical radius values @@ -1720,6 +1729,13 @@ _bmp.Palette := MakeGrayPalette(); end; +function TBitmap_CreateMono8: TBitmap; +begin + Result := TBitmap.Create; + Result.PixelFormat := pf8bit; + Result.Palette := MakeGrayPalette(); +end; + // original source: http://www.delphigeist.com/2009/09/blur-bitmap-algorithm.html // but heavily modified Modified: trunk/ExternalSource/dzlib/u_dzVclUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2021-10-17 16:28:50 UTC (rev 3668) +++ trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2021-10-20 08:41:49 UTC (rev 3669) @@ -1919,7 +1919,7 @@ AssignFile(t, _Filename); Rewrite(t); try - write(t, s); + Write(t, s); finally CloseFile(t); end; @@ -4152,7 +4152,7 @@ procedure TControl_SetHint(_Ctrl: TControl; const _Hint: string); begin - _Ctrl.hint := _Hint; + _Ctrl.Hint := _Hint; _Ctrl.ShowHint := True; end; @@ -5799,12 +5799,12 @@ begin inherited Create; FCtrl := _Ctrl; - SendMessage(FCtrl.Handle, WM_SETREDRAW, wParam(LongBool(False)), 0); + SendMessage(FCtrl.Handle, WM_SETREDRAW, WPARAM(LongBool(False)), 0); end; destructor TWinControlLocker.Destroy; begin - SendMessage(FCtrl.Handle, WM_SETREDRAW, wParam(LongBool(True)), 0); + SendMessage(FCtrl.Handle, WM_SETREDRAW, WPARAM(LongBool(True)), 0); RedrawWindow(FCtrl.Handle, nil, 0, RDW_ERASE or RDW_INVALIDATE or RDW_ALLCHILDREN); inherited; end; @@ -5860,8 +5860,8 @@ procedure TdzButtonedEdit.Loaded; begin inherited; - if RightButton.Visible and (RightButton.hint = '') then begin - RightButton.hint := _('Ctrl+Return to ''click'' right button.'); + if RightButton.Visible and (RightButton.Hint = '') then begin + RightButton.Hint := _('Ctrl+Return to ''click'' right button.'); ShowHint := True; end; end; @@ -6849,7 +6849,7 @@ tb: TTrackBar; begin tb := TrackBar; - tb.hint := IntToStr(tb.Position); + tb.Hint := IntToStr(tb.Position); Application.ActivateHint(Mouse.CursorPos); doOnChange(_Sender); end; @@ -7064,4 +7064,3 @@ finalization FreeAndNil(gblCheckListBoxHelper); end. - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tw...@us...> - 2021-10-20 09:04:25
|
Revision: 3670 http://sourceforge.net/p/gexperts/code/3670 Author: twm Date: 2021-10-20 09:04:22 +0000 (Wed, 20 Oct 2021) Log Message: ----------- updated to latest version from OSDN (again) Modified Paths: -------------- trunk/ExternalSource/dzlib/u_dzErrorThread.pas trunk/ExternalSource/dzlib/u_dzStringUtils.pas trunk/ExternalSource/dzlib/u_dzVclUtils.pas Modified: trunk/ExternalSource/dzlib/u_dzErrorThread.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzErrorThread.pas 2021-10-20 08:41:49 UTC (rev 3669) +++ trunk/ExternalSource/dzlib/u_dzErrorThread.pas 2021-10-20 09:04:22 UTC (rev 3670) @@ -17,7 +17,7 @@ /// Do not override Execute, override doExecute instead. </summary> TErrorThread = class(TNamedThread) private - FExceptionClass: TClass; + FExceptionClass: ExceptClass; FErrorMessage: string; FHasFinished: Boolean; {$IF not Declared(SyncEvent)} @@ -45,6 +45,11 @@ function WaitFor(_TimeoutMsecs: DWORD; out _ReturnValue: DWORD): Boolean; overload; function WaitFor(_TimeoutMsecs: DWORD): Boolean; overload; ///<summary> + /// Checks whether the thread has terminated and if yes, checks whether an exception was the cause + /// for this and raises this exception. This method is meant to be called from the main thread + /// To make sure that an exception in a background thread does not go unnoticed. </summary> + procedure RaiseErrorException; + ///<summary> /// Calls Windows.TerminateThread to kill the thread without freeing resources. /// Read the documentation first! /// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-terminatethread @@ -63,7 +68,7 @@ property ErrorMessage: string read FErrorMessage; ///<summary> /// Class of exception whose message was stored in ErrorMessage </summary> - property ExceptionClass: TClass read FExceptionClass; + property ExceptionClass: ExceptClass read FExceptionClass; end; implementation @@ -100,7 +105,7 @@ doExecute; except on e: Exception do begin - FExceptionClass := e.ClassType; + FExceptionClass := ExceptClass(e.ClassType); FErrorMessage := e.Message; UniqueString(FErrorMessage); end; @@ -118,6 +123,14 @@ end; end; +procedure TErrorThread.RaiseErrorException; +begin + if HasFinished then begin + if Assigned(FExceptionClass) then + raise FExceptionClass.Create(Self.FErrorMessage + ' in ' + Self.Classname); + end; +end; + function TErrorThread.WaitFor(_TimeoutMsecs: DWORD): Boolean; var Dummy: DWORD; Modified: trunk/ExternalSource/dzlib/u_dzStringUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzStringUtils.pas 2021-10-20 08:41:49 UTC (rev 3669) +++ trunk/ExternalSource/dzlib/u_dzStringUtils.pas 2021-10-20 09:04:22 UTC (rev 3670) @@ -417,7 +417,7 @@ ///<summary> /// Split string s into the list of substrings delimited by any of the given delimiters /// NOTE: Duplicate delimiters are ignored, so 'abc def' will be split into two strings (which you -/// would expect), but also 'abc'#9#9'def' is two words (which you might not expect) +/// would expect), but also 'abc'#9#9'def' is two strings (which you might not expect) /// @param sl is the stringlist in which to return the result. If it is not empty, the /// new strings will be appended to the existing content. /// @param s is the string to split @@ -429,7 +429,7 @@ ///<summary> /// Split string s into the array of substrings delimited by any of the given delimiters /// NOTE: Duplicate delimiters are ignored, so 'abc def' will be split into two strings (which you -/// would expect), but also 'abc'#9#9'def' is two words (which you might not expect) +/// would expect), but also 'abc'#9#9'def' is two strings (which you might not expect) /// @param s is the string to split /// @param Delimiters is a string/array of char containing all delimiter characters /// @returns a TStringArray with the parts </summary> Modified: trunk/ExternalSource/dzlib/u_dzVclUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2021-10-20 08:41:49 UTC (rev 3669) +++ trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2021-10-20 09:04:22 UTC (rev 3670) @@ -41,7 +41,8 @@ ComObj, u_dzTranslator, u_dzDateUtils, // we need this for $IF Declared(TryIso2Time) - u_dzTypes; + u_dzTypes, + u_dzVersionInfo; var WM_WINDOW_PROC_HOOK_HELPER: Word = 0; // initialized on startup using RegisterWindowMessage @@ -1384,6 +1385,10 @@ ///<summary> gets the file version from the executable's version information </summary> function TApplication_GetFileVersion: string; +///<summary> gets the file version from the executable's version information +/// Information can be limited to a certain level of detail </summary> +function TApplication_GetFileVersionStr(_Parts: TVersionParts = vpMajorMinorRevision): string; + ///<summary> Returns the ini-file with the application name </summary> function TApplication_GetDefaultIniFileName: string; @@ -1765,7 +1770,6 @@ {$ENDIF dzMESSAGEDEBUG} u_dzSortProvider, u_dzLineBuilder, - u_dzVersionInfo, u_dzTypesUtils, u_dzOsUtils, u_dzStringArrayUtils; @@ -4754,6 +4758,16 @@ Result := VersionInfo.FileVersion; end; +function TApplication_GetFileVersionStr(_Parts: TVersionParts = vpMajorMinorRevision): string; +var + VersionInfo: IFileInfo; +begin + Result := ''; + VersionInfo := TApplicationInfo.Create; + if VersionInfo.HasVersionInfo then + Result := VersionInfo.FileVersionStr(_Parts); +end; + procedure TControl_SetConstraints(_Control: TControl; _Which: TControlConstraintsSet); begin if ccMinWidth in _Which then This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tw...@us...> - 2022-01-22 14:01:46
|
Revision: 3795 http://sourceforge.net/p/gexperts/code/3795 Author: twm Date: 2022-01-22 14:01:43 +0000 (Sat, 22 Jan 2022) Log Message: ----------- synced with dzlib from OSDN Modified Paths: -------------- trunk/ExternalSource/dzlib/dzlib.inc trunk/ExternalSource/dzlib/u_dzDpiScaleUtils.pas trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas trunk/ExternalSource/dzlib/u_dzVclUtils.pas Modified: trunk/ExternalSource/dzlib/dzlib.inc =================================================================== --- trunk/ExternalSource/dzlib/dzlib.inc 2022-01-17 06:00:05 UTC (rev 3794) +++ trunk/ExternalSource/dzlib/dzlib.inc 2022-01-22 14:01:43 UTC (rev 3795) @@ -106,8 +106,14 @@ {$DEFINE HAS_INTTOHEX_FUNCTION_UINT64} {$ENDIF} +{$IFDEF DELPHIX_TOKYO_UP} +// todo: Adjust to reflect when TPicture.LoadFromStream was made public and suported more than +// TBitmap. +{$DEFINE PICTURE_HAS_PUBLIC_LOADFROMSTREAM} +{$ENDIF} + {$IFDEF DELPHI2010_UP} -{$DEFINE CUSTOMINIFILE_HAS_READSUBSECTIONS} + {$DEFINE CUSTOMINIFILE_HAS_READSUBSECTIONS} {$ENDIF} Modified: trunk/ExternalSource/dzlib/u_dzDpiScaleUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzDpiScaleUtils.pas 2022-01-17 06:00:05 UTC (rev 3794) +++ trunk/ExternalSource/dzlib/u_dzDpiScaleUtils.pas 2022-01-22 14:01:43 UTC (rev 3795) @@ -46,27 +46,13 @@ FDesignDpi: Integer; FCurrentDpi: Integer; public - procedure Init(_frm: TCustomForm); overload; -{$IFDEF SUPPORTS_INLINE} inline; -{$ENDIF} - procedure Init(_DPI: Integer); overload; -{$IFDEF SUPPORTS_INLINE} inline; -{$ENDIF} - procedure Init(_DesignDpi, _CurrentDpi: Integer); overload; -{$IFDEF SUPPORTS_INLINE} inline; -{$ENDIF} - procedure SetCurrentDpi(_frm: TCustomForm); overload; -{$IFDEF SUPPORTS_INLINE} inline; -{$ENDIF} - procedure SetCurrentDpi(_DPI: Integer); overload; -{$IFDEF SUPPORTS_INLINE} inline; -{$ENDIF} - function Calc(_Value: Integer): Integer; overload; -{$IFDEF SUPPORTS_INLINE} inline; -{$ENDIF} - function Calc(const _Value: TRect): TRect; overload; -{$IFDEF SUPPORTS_INLINE} inline; -{$ENDIF} + procedure Init(_frm: TCustomForm); overload; {$IFDEF SUPPORTS_INLINE}inline;{$ENDIF} + procedure Init(_Dpi: Integer); overload; {$IFDEF SUPPORTS_INLINE}inline;{$ENDIF} + procedure Init(_DesignDpi, _CurrentDpi: Integer); overload; {$IFDEF SUPPORTS_INLINE}inline;{$ENDIF} + procedure SetCurrentDpi(_frm: TCustomForm); overload; {$IFDEF SUPPORTS_INLINE}inline;{$ENDIF} + procedure SetCurrentDpi(_Dpi: Integer); overload; {$IFDEF SUPPORTS_INLINE}inline;{$ENDIF} + function Calc(_Value: Integer): Integer; overload; {$IFDEF SUPPORTS_INLINE}inline;{$ENDIF} + function Calc(const _Value: TRect): TRect; overload; {$IFDEF SUPPORTS_INLINE}inline;{$ENDIF} function ScaleFactorPercent: Integer; end; @@ -162,10 +148,10 @@ Result.Bottom := Calc(_Value.Bottom); end; -procedure TDpiScaler.Init(_DPI: Integer); +procedure TDpiScaler.Init(_Dpi: Integer); begin - FDesignDpi := _DPI; - FCurrentDpi := _DPI; + FDesignDpi := _Dpi; + FCurrentDpi := _Dpi; end; procedure TDpiScaler.Init(_DesignDpi, _CurrentDpi: Integer); @@ -210,9 +196,9 @@ Result := MulDiv(100, FCurrentDpi, FDesignDpi); end; -procedure TDpiScaler.SetCurrentDpi(_DPI: Integer); +procedure TDpiScaler.SetCurrentDpi(_Dpi: Integer); begin - FCurrentDpi := _DPI; + FCurrentDpi := _Dpi; end; procedure TDpiScaler.SetCurrentDpi(_frm: TCustomForm); @@ -579,5 +565,3 @@ CloseFile(LogFile); {$ENDIF} end. - - Modified: trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2022-01-17 06:00:05 UTC (rev 3794) +++ trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2022-01-22 14:01:43 UTC (rev 3795) @@ -43,6 +43,7 @@ Windows, Types, SysUtils, + Classes, Graphics, {$IFDEF HAS_UNIT_SYSTEM_UITYPES} System.UITypes, @@ -704,12 +705,20 @@ function TryStr2Color(const _s: string; out _Color: TColor): Boolean; +function TPicture_TryLoadMatchingFile(_pic: TPicture; const _FileMask: string): Boolean; + +function TPicture_TryLoadFromResource(_pic: TPicture; const _ResName: string): Boolean; + implementation uses Math, jpeg, // if you get a compile error here you might need to add Vcl.Imaging to the unit scope names - GraphUtil; +{$IFDEF HAS_UNIT_PNGIMAGE} + pngimage, // support for TImage.LoadGraphics for PNG files +{$ENDIF} + GraphUtil, + u_dzFileUtils; function _(const _s: string): string; {$IFDEF SUPPORTS_INLINE} @@ -1128,7 +1137,7 @@ _Canvas.Polygon([_Tip, Point(BaselineLeft, BaselineY), Point(BaselineRight, BaselineY)]); end; -// Inlined method must be iomplemented before it is called +// Inlined method must be implemented before it is called function GetFastLuminance(const _Red, _Green, _Blue: Byte): Byte; begin Result := Round(0.299 * _Red + 0.587 * _Green + 0.114 * _Blue); @@ -3471,4 +3480,75 @@ end; end; +function TPicture_TryLoadMatchingFile(_pic: TPicture; const _FileMask: string): Boolean; +var + fn: string; +begin + Result := False; + if TFileSystem.FindMatchingFile(_FileMask, fn) = mfFile then begin + try + _pic.LoadFromFile(fn); + Result := True; + except + end; + end; +end; + +{$IFNDEF PICTURE_HAS_PUBLIC_LOADFROMSTREAM} +function TPicture_TryLoadFromJpgStream(_pic: TPicture; _st: TStream): Boolean; +var + jpg: TJPEGImage; +begin + jpg := TJPEGImage.Create; + try + try + _st.Position := 0; + jpg.LoadFromStream(_st); + _pic.Bitmap.Assign(jpg); + Result := True; + except + Result := False; + end; + finally + FreeAndNil(jpg); + end; +end; + +function TPicture_TryLoadFromBmpStream(_pic: TPicture; _st: TStream): Boolean; +begin + try + _st.Position := 0; + _pic.Bitmap.LoadFromStream(_st); + Result := True; + except + Result := False; + end; +end; +{$ENDIF} + +function TPicture_TryLoadFromResource(_pic: TPicture; const _ResName: string): Boolean; +var + ResStream: TResourceStream; +begin + Assert(Assigned(_pic)); + try + ResStream := TResourceStream.Create(HInstance, _ResName, RT_rcdata); + try + ResStream.Position := 0; +{$IFDEF PICTURE_HAS_PUBLIC_LOADFROMSTREAM} + _pic.LoadFromStream(ResStream); + Result := True; +{$ELSE} + Result := TPicture_TryLoadFromJpgStream(_pic, ResStream); + if not Result then + Result := TPicture_TryLoadFromBmpStream(_pic, ResStream); +{$ENDIF} + finally + FreeAndNil(ResStream); + end; + except + Result := False; + end; +end; + end. Modified: trunk/ExternalSource/dzlib/u_dzVclUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2022-01-17 06:00:05 UTC (rev 3794) +++ trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2022-01-22 14:01:43 UTC (rev 3795) @@ -1210,6 +1210,14 @@ /// @returns the center of the form as a TPoint </summary> function TForm_GetCenter(_frm: TForm): TPoint; +///<summary> +/// Starts a background thread that waits for a new window to be activated and then centers it +/// on the current active window. It also makes sure that the new windows is fully visible. +/// @NOTE: This procedure must be called *before* opening the window to be centered. +/// @NOTE: This should work with any kind of window, not just common dialogs, but has +/// not been tested </summary> +procedure TCommonDialog_CenterWithBackgroundThread; + type TFormPlacementEnum = (fpePositionOnly, fpeSizeOnly, fpePosAndSize); @@ -1333,9 +1341,11 @@ function TForm_ReadConfigValue(_frm: TForm; const _Name: string; const _Default: string = ''): string; overload; function TForm_ReadConfigValue(_frm: TForm; const _Name: string; _Default: Integer): Integer; overload; +function TForm_ReadConfigValue(_frm: TForm; const _Name: string; _Default: Boolean): Boolean; overload; function TForm_WriteConfigValue(_frm: TForm; const _Name, _Value: string): Boolean; overload; function TForm_WriteConfigValue(_frm: TForm; const _Name: string; _Value: Integer): Boolean; overload; +function TForm_WriteConfigValue(_frm: TForm; const _Name: string; _Value: Boolean): Boolean; overload; ///<summary> Sets the form's Constraints.MinWidth and .MinHeight to the form's current size. </summary> procedure TForm_SetMinConstraints(_frm: TForm); deprecated; // use TControl_SetMinConstraints instead @@ -1577,6 +1587,12 @@ procedure TActionList_SetAllVisible(_al: TActionList; _Visible: Boolean); ///<summary> +/// (Tries to) set the Enabled property of all actions in the action list. +/// This only works for Actions that are derived from TCustomAction (TActionList.Actions contains +/// TBasicAction items, so this is not necessarily true for all actions). +procedure TActionList_SetAllEnabled(_al: TActionList; _Enabled: Boolean); + +///<summary> /// Sets the Enabled property of all actions that match the given category. </summary> procedure TActionList_SetCategoryEnabled(_al: TActionList; const _Category: string; _Enabled: Boolean); @@ -1651,10 +1667,14 @@ procedure TMonitor_MakeFullyVisible(_MonitorRect: TRect; var _Left, _Top, _Width, _Height: Integer); overload; procedure TMonitor_MakeFullyVisible(_Monitor: TMonitor; var _Left, _Top, _Width, _Height: Integer); overload; procedure TMonitor_MakeFullyVisible(_MonitorRect: TRect; var _Rect: TRect; out _Width, _Height: Integer); overload; +procedure TMonitor_MakeFullyVisible(_MonitorRect: TRect; var _Rect: TRect); overload; +procedure TMonitor_MakeFullyVisible(_MonitorRect: TRect; var _Rect: TRectLTWH); overload; procedure TMonitor_MakeFullyVisible(_Monitor: TMonitor; var _Rect: TRect; out _Width, _Height: Integer); overload; procedure TMonitor_MakeFullyVisible(_Monitor: TMonitor; var _Rect: TRect); overload; procedure TMonitor_MakeFullyVisible(_Monitor: TMonitor; var _Rect: TRectLTWH); overload; procedure TMonitor_MakeFullyVisible(_Monitor: TMonitor; _frm: TForm); overload; +procedure TMonitor_MakeFullyVisible(_MonitorHandle: HMonitor; var _Rect: TRect); overload; +procedure TMonitor_MakeFullyVisible(_MonitorHandle: HMonitor; var _Rect: TRectLTWH); overload; ///<summary> /// Tries to get the primary monitor. @@ -1774,7 +1794,8 @@ u_dzLineBuilder, u_dzTypesUtils, u_dzOsUtils, - u_dzStringArrayUtils; + u_dzStringArrayUtils, + u_dzNamedThread; function _(const _s: string): string; {$IFDEF SUPPORTS_INLINE} @@ -2575,8 +2596,8 @@ FLbl.Font.Style := FLbl.Font.Style + [fsUnderline]; FLbl.Font.Color := clBlue; FLbl.Cursor := crHandPoint; - if (FLbl.hint = '') and (Menus.StripHotkey(FLbl.Caption) <> FUrl) then begin - FLbl.hint := FUrl; + if (FLbl.Hint = '') and (Menus.StripHotkey(FLbl.Caption) <> FUrl) then begin + FLbl.Hint := FUrl; FLbl.ShowHint := True; end; end; @@ -4158,7 +4179,7 @@ procedure TControl_SetHint(_Ctrl: TControl; const _Hint: string); begin - _Ctrl.hint := _Hint; + _Ctrl.Hint := _Hint; _Ctrl.ShowHint := True; end; @@ -4332,13 +4353,18 @@ procedure TForm_CenterOn(_frmHwnd: HWND; _Center: TPoint); var - Position: TRect; + FrmRect: TRect; + FrmCenter: TPoint; + MonitorHandle: HMonitor; begin - GetWindowRect(_frmHwnd, Position); + GetWindowRect(_frmHwnd, FrmRect); + FrmCenter := TRect_Center(FrmRect); + TRect_SetOffset(FrmRect, _Center.X - FrmCenter.X, _Center.Y - FrmCenter.Y); + MonitorHandle := MonitorFromRect(@FrmRect, MONITOR_DEFAULTTONEAREST); + TMonitor_MakeFullyVisible(MonitorHandle, FrmRect); SetWindowPos(_frmHwnd, HWND_TOPMOST, - _Center.X - (Position.Right - Position.Left) div 2, - _Center.Y - (Position.Bottom - Position.Top) div 2, - 0, 0, SWP_SHOWWINDOW or SWP_NOSIZE); + FrmRect.Left, FrmRect.Top, 0, 0, + SWP_SHOWWINDOW or SWP_NOSIZE); end; procedure TForm_CenterOn(_frm: TForm; _Center: TWinControl); @@ -4470,6 +4496,11 @@ Result := TRegistry_ReadInteger(TForm_GetConfigRegistryKey(_frm), _Name, _Default); end; +function TForm_ReadConfigValue(_frm: TForm; const _Name: string; _Default: Boolean): Boolean; +begin + Result := TRegistry_ReadBool(TForm_GetConfigRegistryKey(_frm), _Name, _Default); +end; + function TForm_WriteConfigValue(_frm: TForm; const _Name, _Value: string): Boolean; begin try @@ -4490,6 +4521,16 @@ end; end; +function TForm_WriteConfigValue(_frm: TForm; const _Name: string; _Value: Boolean): Boolean; +begin + try + TRegistry_WriteBool(TForm_GetConfigRegistryKey(_frm), _Name, _Value); + Result := True; + except + Result := False; + end; +end; + function TForm_StorePlacement(const _Bounds: TRectLTWH; const _RegEntry: TRegistryEntry; _HKEY: HKEY = HKEY_CURRENT_USER): Boolean; begin @@ -4576,7 +4617,7 @@ var s: string; PosStr: string; - l, t, w, h: Integer; + L, t, w, h: Integer; begin if u_dzOsUtils.IsShiftDown then begin // if the user holds shift, do not restore the form's placement @@ -4588,7 +4629,7 @@ Result := TRegistry_TryReadString(_RegEntry.KeyName, _RegEntry.ValueName, PosStr, _HKEY); if Result then begin s := ExtractStr(PosStr, ','); - if not TryStrToInt(s, l) then + if not TryStrToInt(s, L) then Exit; //==> s := ExtractStr(PosStr, ','); if not TryStrToInt(s, t) then @@ -4600,7 +4641,7 @@ if not TryStrToInt(s, h) then Exit; //==> - _Bounds.Left := l; + _Bounds.Left := L; _Bounds.Top := t; _Bounds.Width := w; _Bounds.Height := h; @@ -5698,6 +5739,18 @@ end; end; +procedure TActionList_SetAllEnabled(_al: TActionList; _Enabled: Boolean); +var + i: Integer; + act: TBasicAction; +begin + for i := 0 to _al.ActionCount - 1 do begin + act := _al[i]; + if act is TCustomAction then + TCustomAction(act).Enabled := _Enabled; + end; +end; + type THackGroupBox = class(TCustomGroupBox) end; @@ -5815,12 +5868,12 @@ begin inherited Create; FCtrl := _Ctrl; - SendMessage(FCtrl.Handle, WM_SETREDRAW, wParam(LongBool(False)), 0); + SendMessage(FCtrl.Handle, WM_SETREDRAW, WPARAM(LongBool(False)), 0); end; destructor TWinControlLocker.Destroy; begin - SendMessage(FCtrl.Handle, WM_SETREDRAW, wParam(LongBool(True)), 0); + SendMessage(FCtrl.Handle, WM_SETREDRAW, WPARAM(LongBool(True)), 0); RedrawWindow(FCtrl.Handle, nil, 0, RDW_ERASE or RDW_INVALIDATE or RDW_ALLCHILDREN); inherited; end; @@ -5876,8 +5929,8 @@ procedure TdzButtonedEdit.Loaded; begin inherited; - if RightButton.Visible and (RightButton.hint = '') then begin - RightButton.hint := _('Ctrl+Return to ''click'' right button.'); + if RightButton.Visible and (RightButton.Hint = '') then begin + RightButton.Hint := _('Ctrl+Return to ''click'' right button.'); ShowHint := True; end; end; @@ -6536,6 +6589,19 @@ _Rect.Bottom := Top + _Height; end; +procedure TMonitor_MakeFullyVisible(_MonitorRect: TRect; var _Rect: TRect); +var + Width: Integer; + Height: Integer; +begin + TMonitor_MakeFullyVisible(_MonitorRect, _Rect, Width, Height); +end; + +procedure TMonitor_MakeFullyVisible(_MonitorRect: TRect; var _Rect: TRectLTWH); +begin + TMonitor_MakeFullyVisible(_MonitorRect, _Rect.Left, _Rect.Top, _Rect.Width, _Rect.Height); +end; + procedure TMonitor_MakeFullyVisible(_Monitor: TMonitor; var _Rect: TRect; out _Width, _Height: Integer); var Left: Integer; @@ -6579,6 +6645,30 @@ _frm.BoundsRect := re; end; +procedure TMonitor_MakeFullyVisible(_MonitorHandle: HMonitor; var _Rect: TRect); +var + MonitorInfo: TMonitorInfo; +begin + MonitorInfo.cbSize := SizeOf(MonitorInfo); + if not GetMonitorInfo(_MonitorHandle, @MonitorInfo) then begin + // no monitor info available, we can't do anything + Exit; //==> + end; + TMonitor_MakeFullyVisible(MonitorInfo.rcWork, _Rect); +end; + +procedure TMonitor_MakeFullyVisible(_MonitorHandle: HMonitor; var _Rect: TRectLTWH); +var + MonitorInfo: TMonitorInfo; +begin + MonitorInfo.cbSize := SizeOf(MonitorInfo); + if not GetMonitorInfo(_MonitorHandle, @MonitorInfo) then begin + // no monitor infor available, we can't do anything + Exit; //==> + end; + TMonitor_MakeFullyVisible(MonitorInfo.rcWork, _Rect); +end; + function TScreen_GetPrimaryMonitor: TMonitor; begin if not TScreen_TryGetPrimaryMonitor(Result) then @@ -6876,7 +6966,7 @@ tb: TTrackBar; begin tb := TrackBar; - tb.hint := IntToStr(tb.Position); + tb.Hint := IntToStr(tb.Position); Application.ActivateHint(Mouse.CursorPos); doOnChange(_Sender); end; @@ -7033,6 +7123,64 @@ WM_WINDOW_PROC_HOOK_HELPER := RegisterWindowMessage('WM_WINDOW_PROC_HOOK_HELPER'); end; +type + TCenterWindowThread = class(TNamedThread) + private + FParentHandle: HWND; + protected + procedure Execute; override; + public + constructor Create(_ParentHandle: HWND); + end; + +{ TCenterWindowThread } + +constructor TCenterWindowThread.Create(_ParentHandle: HWND); +begin + FreeOnTerminate := True; + FParentHandle := _ParentHandle; + inherited Create(False); +end; + +procedure TCenterWindowThread.Execute; +var + MaxTickCount: DWORD; + ThreadInfo: TGUIThreadinfo; + ParentRect: TRect; + ParentCenter: TPoint; +begin + inherited; + + GetWindowRect(FParentHandle, ParentRect); + ParentCenter := TRect_Center(ParentRect); + + ThreadInfo.cbSize := SizeOf(ThreadInfo); + MaxTickCount := GetTickCount + 10000; // 10 Seconds should be plenty + while MaxTickCount > GetTickCount do begin + Sleep(50); + if GetGUIThreadInfo(MainThreadID, ThreadInfo) then begin + if ThreadInfo.hwndActive <> FParentHandle then begin + // After the first call to TForm_CenterOn the window sometimes doesn't get moved, + // at other times it gets shown outside the visible area. Calling it twice with a 50 ms + // delay always seems to work. Only sleeping for 50 ms before the call didn't work either. + TForm_CenterOn(ThreadInfo.hwndActive, ParentCenter); + Sleep(50); + TForm_CenterOn(ThreadInfo.hwndActive, ParentCenter); + Exit; //==> + end; + end; + end; +end; + +procedure TCommonDialog_CenterWithBackgroundThread; +var + ThreadInfo: TGUIThreadinfo; +begin + ThreadInfo.cbSize := SizeOf(ThreadInfo); + GetGUIThreadInfo(MainThreadID, ThreadInfo); + TCenterWindowThread.Create(ThreadInfo.hwndActive); +end; + {$IFDEF SUPPORTS_ENHANCED_RECORDS} { TRegistryEntry } @@ -7091,4 +7239,3 @@ finalization FreeAndNil(gblCheckListBoxHelper); end. - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tw...@us...> - 2022-02-06 10:50:30
|
Revision: 3809 http://sourceforge.net/p/gexperts/code/3809 Author: twm Date: 2022-02-06 10:50:27 +0000 (Sun, 06 Feb 2022) Log Message: ----------- updated to latest dzlib from OSDN Modified Paths: -------------- trunk/ExternalSource/dzlib/u_dzTypes.pas trunk/ExternalSource/dzlib/u_dzVclUtils.pas Modified: trunk/ExternalSource/dzlib/u_dzTypes.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzTypes.pas 2022-02-05 11:33:34 UTC (rev 3808) +++ trunk/ExternalSource/dzlib/u_dzTypes.pas 2022-02-06 10:50:27 UTC (rev 3809) @@ -204,6 +204,8 @@ procedure Assign(_Left, _Top, _Width, _Height: Integer); overload; procedure Assign(_a: TRect); overload; procedure AssignTLRB(_Left, _Top, _Right, _Bottom: Integer); + procedure AssignTo(out _Left, _Top, _Width, _Height: Integer); overload; + procedure AssignTo(out _a: TRect); overload; ///<summary> /// Gets and sets the top left coordinates keeping the size </summary> property TopLeft: TPoint read GetTopLeft write SetTopLeft; @@ -246,6 +248,19 @@ Assign(_Left, _Top, _Right - _Left, _Bottom - _Top); end; +procedure TRectLTWH.AssignTo(out _Left, _Top, _Width, _Height: Integer); +begin + _Left := Left; + _Top := Top; + _Width := Width; + _Height := Height; +end; + +procedure TRectLTWH.AssignTo(out _a: TRect); +begin + _a := Rect(Left, Top, Left + Width, Top + Height); +end; + class function TRectLTWH.FromLTWH(_Left, _Top, _Width, _Height: Integer): TRectLTWH; begin Result.Assign(_Left, _Top, _Width, _Height); Modified: trunk/ExternalSource/dzlib/u_dzVclUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2022-02-05 11:33:34 UTC (rev 3808) +++ trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2022-02-06 10:50:27 UTC (rev 3809) @@ -1749,7 +1749,7 @@ PdzMonitor = ^TdzMonitor; TdzMonitor = record public - Handle: HMonitor; + Handle: HMONITOR; MonitorNum: Integer; BoundsRect: TRectLTWH; WorkArea: TRectLTWH; @@ -4637,7 +4637,7 @@ var s: string; PosStr: string; - l, t, w, h: Integer; + L, t, w, h: Integer; begin if u_dzOsUtils.IsShiftDown then begin // if the user holds shift, do not restore the form's placement @@ -4649,7 +4649,7 @@ Result := TRegistry_TryReadString(_RegEntry.KeyName, _RegEntry.ValueName, PosStr, _HKEY); if Result then begin s := ExtractStr(PosStr, ','); - if not TryStrToInt(s, l) then + if not TryStrToInt(s, L) then Exit; //==> s := ExtractStr(PosStr, ','); if not TryStrToInt(s, t) then @@ -4661,7 +4661,7 @@ if not TryStrToInt(s, h) then Exit; //==> - _Bounds.Left := l; + _Bounds.Left := L; _Bounds.Top := t; _Bounds.Width := w; _Bounds.Height := h; @@ -5888,12 +5888,12 @@ begin inherited Create; FCtrl := _Ctrl; - SendMessage(FCtrl.Handle, WM_SETREDRAW, wParam(LongBool(False)), 0); + SendMessage(FCtrl.Handle, WM_SETREDRAW, WPARAM(LongBool(False)), 0); end; destructor TWinControlLocker.Destroy; begin - SendMessage(FCtrl.Handle, WM_SETREDRAW, wParam(LongBool(True)), 0); + SendMessage(FCtrl.Handle, WM_SETREDRAW, WPARAM(LongBool(True)), 0); RedrawWindow(FCtrl.Handle, nil, 0, RDW_ERASE or RDW_INVALIDATE or RDW_ALLCHILDREN); inherited; end; @@ -7221,7 +7221,7 @@ { TdzScreen } -function EnumMonitorsProc(hm: HMonitor; dc: HDC; r: PRECT; Data: Pointer): Boolean; stdcall; +function EnumMonitorsProc(hm: HMONITOR; dc: HDC; r: PRECT; Data: Pointer): Boolean; stdcall; var Info: TMonitorInfoEx; M: TdzScreen.PdzMonitor; @@ -7259,4 +7259,3 @@ finalization FreeAndNil(gblCheckListBoxHelper); end. - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tw...@us...> - 2022-05-29 13:49:01
|
Revision: 3849 http://sourceforge.net/p/gexperts/code/3849 Author: twm Date: 2022-05-29 13:48:58 +0000 (Sun, 29 May 2022) Log Message: ----------- update to latest version from OSDN Modified Paths: -------------- trunk/ExternalSource/dzlib/dzlib.inc trunk/ExternalSource/dzlib/u_dzAdvancedObject.pas trunk/ExternalSource/dzlib/u_dzClassUtils.pas trunk/ExternalSource/dzlib/u_dzConvertUtils.pas trunk/ExternalSource/dzlib/u_dzCriticalSection.pas trunk/ExternalSource/dzlib/u_dzDpiScaleUtils.pas trunk/ExternalSource/dzlib/u_dzDpiScaleUtilsDummy.pas trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas trunk/ExternalSource/dzlib/u_dzOsUtils.pas trunk/ExternalSource/dzlib/u_dzStopwatch.pas trunk/ExternalSource/dzlib/u_dzTranslator.pas trunk/ExternalSource/dzlib/u_dzVclUtils.pas Modified: trunk/ExternalSource/dzlib/dzlib.inc =================================================================== --- trunk/ExternalSource/dzlib/dzlib.inc 2022-05-29 12:55:09 UTC (rev 3848) +++ trunk/ExternalSource/dzlib/dzlib.inc 2022-05-29 13:48:58 UTC (rev 3849) @@ -116,6 +116,9 @@ {$DEFINE CUSTOMINIFILE_HAS_READSUBSECTIONS} {$ENDIF} +{$IFDEF DELPHIX_SYDNEY_UP} + {$DEFINE SUPPORTS_PER_MONITOR_DPI} +{$ENDIF} {$IFOPT T+} {$DEFINE TYPEDADDRESS_IS_ON} Modified: trunk/ExternalSource/dzlib/u_dzAdvancedObject.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzAdvancedObject.pas 2022-05-29 12:55:09 UTC (rev 3848) +++ trunk/ExternalSource/dzlib/u_dzAdvancedObject.pas 2022-05-29 13:48:58 UTC (rev 3849) @@ -297,13 +297,8 @@ class function TAdvancedObject.SetIntProperty(_Instance: TObject; const _Name: string; _Value: Integer): Boolean; -var - PropInfo: PPropInfo; begin - PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); - Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkInteger); - if Result then - TypInfo.SetOrdProp(_Instance, PropInfo, _Value); + Result := u_dzTypInfo.TrySetIntProperty(_Instance, _Name, _Value); end; {$IFDEF SUPPORTS_EXTENDED} Modified: trunk/ExternalSource/dzlib/u_dzClassUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzClassUtils.pas 2022-05-29 12:55:09 UTC (rev 3848) +++ trunk/ExternalSource/dzlib/u_dzClassUtils.pas 2022-05-29 13:48:58 UTC (rev 3849) @@ -1095,18 +1095,17 @@ var Len: Integer; ErrCode: DWORD; + s: AnsiString; begin - Len := Length(_s); - if Len > 0 then begin - Result := _Stream.Write(_s[1], Len); - if Result <> Len then begin - ErrCode := GetLastError; - RaiseLastOSErrorEx(ErrCode, - Format(_('Error writing string of length %d to stream, wrote only %d bytes: %%1:s (%%0:d)'), - [Len, Result])); - end; - end else - Result := 0; + s := AnsiString(_s); + Len := Length(s); + Result := _Stream.Write(PAnsiChar(s)^, Len); + if Result <> Len then begin + ErrCode := GetLastError; + RaiseLastOSErrorEx(ErrCode, + Format(_('Error writing string of length %d to stream, wrote only %d bytes: %%1:s (%%0:d)'), + [Len, Result])); + end; end; {$IFDEF UNICODE} Modified: trunk/ExternalSource/dzlib/u_dzConvertUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzConvertUtils.pas 2022-05-29 12:55:09 UTC (rev 3848) +++ trunk/ExternalSource/dzlib/u_dzConvertUtils.pas 2022-05-29 13:48:58 UTC (rev 3849) @@ -667,6 +667,8 @@ // Inlined method must be implemented before it is called function ReduceToUInt8(const _Value: Integer): UInt8; begin + // this could call EnsureRange(0, MaxUIn8) in Math, but I am not sure which Delphi + // versions support these functions. if _Value < 0 then Result := 0 else if _Value > MaxUInt8 then @@ -682,6 +684,8 @@ function ReduceToInt8(const _Value: Integer): Int8; begin + // this could call EnsureRange(MinInt8, MaxIn8) in Math, but I am not sure which Delphi + // versions support these functions. if _Value < MinInt8 then Result := MinInt8 else if _Value > MaxInt8 then @@ -692,6 +696,8 @@ function ReduceToUInt16(const _Value: Integer): UInt16; begin + // this could call EnsureRange(0, MaxUIn16) in Math, but I am not sure which Delphi + // versions support these functions. if _Value < 0 then Result := 0 else if _Value > MaxUInt16 then @@ -702,6 +708,8 @@ function ReduceToInt16(const _Value: Integer): Int16; begin + // this could call EnsureRange(MinInt16, MaxIn16) in Math, but I am not sure which Delphi + // versions support these functions. if _Value < MinInt16 then Result := MinInt16 else if _Value > MaxInt16 then Modified: trunk/ExternalSource/dzlib/u_dzCriticalSection.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzCriticalSection.pas 2022-05-29 12:55:09 UTC (rev 3848) +++ trunk/ExternalSource/dzlib/u_dzCriticalSection.pas 2022-05-29 13:48:58 UTC (rev 3849) @@ -115,6 +115,7 @@ uses u_dzMiscUtils, + u_dzOsUtils, u_dzTypes; var @@ -155,89 +156,6 @@ end; {$ENDIF DEBUG_CRIT_SECT} -{$IF not declared(PSystemLogicalProcessorInformation)} -{$ALIGN ON} -{$MINENUMSIZE 4} - -{$IF not declared(ULONG_PTR)} -type - ULONG_PTR = LongWord; -{$IFEND} - -{$IF not declared(ULONGLONG)} - ULONGLONG = UInt64; -{$IFEND} - -type - _PROCESSOR_CACHE_TYPE = (CacheUnified { = 0}, CacheInstruction { = 1}, CacheData { = 2}, CacheTrace { = 3}); - PROCESSOR_CACHE_TYPE = _PROCESSOR_CACHE_TYPE; - TProcessorCacheType = PROCESSOR_CACHE_TYPE; -type - TCacheDescriptor = record - Level: BYTE; - Associativity: BYTE; - LineSize: Word; - Size: DWORD; - _Type: PROCESSOR_CACHE_TYPE; - end; - -type - TLogicalProcessorRelationship = (RelationProcessorCore { = 0}, - RelationNumaNode { = 1}, - RelationCache { = 2}, - RelationProcessorPackage { = 3}, - RelationGroup { = 4}, RelationAll = $FFFF); - -type - TSystemLogicalProcessorInformation = record - ProcessorMask: ULONG_PTR; - Relationship: TLogicalProcessorRelationship; - case Integer of - 0: (Flags: BYTE); // ProcessorCore - 1: (NodeNumber: DWORD); // NumaNode - 2: (Cache: TCacheDescriptor); //Cache - 3: (Reserved: array[0..1] of ULONGLONG); - end; - PSystemLogicalProcessorInformation = ^TSystemLogicalProcessorInformation; - -function GetLogicalProcessorInformation(Buffer: PSystemLogicalProcessorInformation; var ReturnedLength: DWORD): BOOL; stdcall; - external kernel32 Name 'GetLogicalProcessorInformation'; -{$IFEND} - -function GetCacheLineSize: Integer; -var - ProcInfo: PSystemLogicalProcessorInformation; - CurInfo: PSystemLogicalProcessorInformation; - Len: DWORD; - Err: DWORD; -begin - Result := 64; - - Len := 0; - if not GetLogicalProcessorInformation(nil, Len) then begin - Err := GetLastError; - if Err = ERROR_INSUFFICIENT_BUFFER then begin - GetMem(ProcInfo, Len); - try - if GetLogicalProcessorInformation(ProcInfo, Len) then begin - // it should not be possible that the second call still returns, but ... - CurInfo := ProcInfo; - while Len > 0 do begin - if (CurInfo.Relationship = RelationCache) and (CurInfo.Cache.Level = 1) then begin - Result := CurInfo.Cache.LineSize; - Exit; - end; - Inc(CurInfo); - Dec(Len, SizeOf(CurInfo^)); - end; - end; - finally - FreeMem(ProcInfo); - end; - end; - end; -end; - {$IFDEF SUPPORTS_ENHANCED_RECORDS} { TdzRTLCriticalSection } @@ -432,7 +350,7 @@ {$ENDIF SUPPORTS_ENHANCED_RECORDS} initialization - CacheLineSize := GetCacheLineSize; + CacheLineSize := GetCpuCacheLineSize; {$IFDEF SUPPORTS_ENHANCED_RECORDS} Assert(SizeOf(TdzRTLCriticalSection) = SizeOf(TRTLCriticalSection)); TryInitInitializeCriticalSectionEx; Modified: trunk/ExternalSource/dzlib/u_dzDpiScaleUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzDpiScaleUtils.pas 2022-05-29 12:55:09 UTC (rev 3848) +++ trunk/ExternalSource/dzlib/u_dzDpiScaleUtils.pas 2022-05-29 13:48:58 UTC (rev 3849) @@ -92,11 +92,48 @@ uses StdCtrls, CommCtrl, - u_dzAdvancedObject, - u_dzVclUtils, + u_dzTypInfo, u_dzTypesUtils, u_dzMiscUtils; +type + TFormHack = class(TForm) + end; + +function TForm_GetDesignDPI(_Frm: TForm): UINT; +begin +{$IFDEF HAS_TFORM_GETDESIGNDPI} + Result := TFormHack(_Frm).GetDesignDpi; +{$ELSE} + Result := 96; +{$ENDIF} +end; + +type + TGetDpiForWindow = function(_HWnd: HWND): UINT; stdcall; +var + GetDpiForWindow: TGetDpiForWindow = nil; + +procedure InitApiCalls; +var + Handle: Cardinal; +begin + Handle := LoadLibrary('user32.dll'); + if Handle <> 0 then begin + GetDpiForWindow := GetProcAddress(Handle, 'GetDpiForWindow'); + end; +end; + +function TScreen_GetDpiForForm(_Frm: TCustomForm): UINT; +begin + Result := Screen.PixelsPerInch; + if _Frm is TForm then begin + if Assigned(GetDpiForWindow) then + Result := GetDpiForWindow(_Frm.Handle); + end; +end; + + {$IFDEF DPI_SCALER_LOGGING} var LogFile: Textfile; @@ -258,7 +295,7 @@ Ctrl.BoundsRect := br; if ItemHeight <> 0 then begin - TAdvancedObject.SetIntProperty(Ctrl, 'ItemHeight', _Scaler.Calc(ItemHeight)); + TrySetIntProperty(Ctrl, 'ItemHeight', _Scaler.Calc(ItemHeight)); end; // if we don't do this, the text is truncated on the left @@ -274,13 +311,13 @@ begin Ctrl := _Ctrl; BoundsRect := Ctrl.BoundsRect; - if not TAdvancedObject.TryGetObjectProperty(_Ctrl, 'Font', TObject(fnt)) then begin + if not TryGetObjectProperty(_Ctrl, 'Font', TObject(fnt)) then begin FontSize := 0; end else begin FontSize := GetFontSize(fnt); end; - if not TAdvancedObject.TryGetIntProperty(_Ctrl, 'ItemHeight', ItemHeight) then begin + if not TryGetIntProperty(_Ctrl, 'ItemHeight', ItemHeight) then begin ItemHeight := 0; end; @@ -294,8 +331,8 @@ ParentFontValue: Boolean; OldFontSize: Integer; begin - if TAdvancedObject.TryGetObjectProperty(Ctrl, 'Font', TObject(fnt)) then begin - if not TAdvancedObject.TryGetBoolProperty(Ctrl, 'ParentFont', ParentFontValue) + if TryGetObjectProperty(Ctrl, 'Font', TObject(fnt)) then begin + if not TryGetBoolProperty(Ctrl, 'ParentFont', ParentFontValue) or not ParentFontValue then begin Assert(FontSize <> 0); Modified: trunk/ExternalSource/dzlib/u_dzDpiScaleUtilsDummy.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzDpiScaleUtilsDummy.pas 2022-05-29 12:55:09 UTC (rev 3848) +++ trunk/ExternalSource/dzlib/u_dzDpiScaleUtilsDummy.pas 2022-05-29 13:48:58 UTC (rev 3849) @@ -1,5 +1,7 @@ unit u_dzDpiScaleUtilsDummy; +{$I 'dzlib.inc'} + interface uses @@ -9,7 +11,32 @@ Controls, Forms; +{$IFDEF SUPPORTS_ENHANCED_RECORDS} type + TDpiScaler = record + private + FDesignDpi: Integer; + FCurrentDpi: Integer; + public + procedure Init(_frm: TCustomForm); overload; +{$IFDEF SUPPORTS_INLINE} inline; {$ENDIF} + procedure Init(_Dpi: Integer); overload; +{$IFDEF SUPPORTS_INLINE} inline; {$ENDIF} + procedure Init(_DesignDpi, _CurrentDpi: Integer); overload; +{$IFDEF SUPPORTS_INLINE} inline; {$ENDIF} + procedure SetCurrentDpi(_frm: TCustomForm); overload; +{$IFDEF SUPPORTS_INLINE} inline; {$ENDIF} + procedure SetCurrentDpi(_Dpi: Integer); overload; +{$IFDEF SUPPORTS_INLINE} inline; {$ENDIF} + function Calc(_Value: Integer): Integer; overload; +{$IFDEF SUPPORTS_INLINE} inline; {$ENDIF} + function Calc(const _Value: TRect): TRect; overload; +{$IFDEF SUPPORTS_INLINE} inline; {$ENDIF} + function ScaleFactorPercent: Integer; + end; +{$ENDIF} + +type PScaledImagesRec = ^TScaledImagesRec; TScaledImagesRec = record FDpi: Integer; @@ -22,7 +49,7 @@ FOriginal: TImageList; public constructor Create(_Owner: TComponent; _Original: TImageList); reintroduce; - function GetScaledList(_DPI: Integer): TImageList; + function GetScaledList(_Dpi: Integer): TImageList; end; type @@ -60,10 +87,57 @@ FOriginal := _Original; end; -function TImageListScaler.GetScaledList(_DPI: Integer): TImageList; +function TImageListScaler.GetScaledList(_Dpi: Integer): TImageList; begin Result := FOriginal; end; +{$IFDEF SUPPORTS_ENHANCED_RECORDS} +{ TDpiScaler } + +function TDpiScaler.Calc(_Value: Integer): Integer; +begin + Result := _Value; +end; + +function TDpiScaler.Calc(const _Value: TRect): TRect; +begin + Result := _Value; +end; + +procedure TDpiScaler.Init(_frm: TCustomForm); +begin + FDesignDpi := 96; + FCurrentDpi := 96; +end; + +procedure TDpiScaler.Init(_DesignDpi, _CurrentDpi: Integer); +begin + FDesignDpi := _DesignDpi; + FCurrentDpi := _CurrentDpi; +end; + +procedure TDpiScaler.Init(_Dpi: Integer); +begin + FCurrentDpi := _Dpi; + FDesignDpi := _Dpi; +end; + +function TDpiScaler.ScaleFactorPercent: Integer; +begin + Result := 100; +end; + +procedure TDpiScaler.SetCurrentDpi(_Dpi: Integer); +begin + FCurrentDpi := _Dpi; +end; + +procedure TDpiScaler.SetCurrentDpi(_frm: TCustomForm); +begin + FCurrentDpi := 96; +end; +{$ENDIF} + end. Modified: trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2022-05-29 12:55:09 UTC (rev 3848) +++ trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2022-05-29 13:48:58 UTC (rev 3849) @@ -2,11 +2,14 @@ {$INCLUDE 'dzlib.inc'} -{.$IFDEF DELPHI2005} -// the Delphi 2005 cmpiler crashes if this is compiled with typed @ operator +{.$UNDEF OPTIMIZE_DZ_GRAPHIC_UTILS} +{.$UNDEF SUPPORTS_INLINE} + +{$IFDEF DELPHI2005} +// the Delphi 2005 compiler crashes if this is compiled with typed @ operator // turned on {$TYPEDADDRESS OFF} -{.$ENDIF} +{$ENDIF} {$IFDEF OPTIMIZE_DZ_GRAPHIC_UTILS} {$OPTIMIZATION ON} @@ -57,6 +60,11 @@ u_dzTypesUtils; type + EdzPixelFormatNotSupported = class(EdzException) + constructor Create(_PixelFormat: TPixelFormat); overload; + end; + +type TRgbBrightnessChannelEnum = (rcbAverage, rcbFastLuminance, rcbRed, rcbGreen, rcbBlue, rcbLuminance); type @@ -94,7 +102,14 @@ function GetValues(_Idx: TValueIdxTriple): Byte; inline; procedure SetValues(_Idx: TValueIdxTriple; _Value: Byte); inline; function GetColor: TColor; + ///<summary> + /// Sets Blue, Green and Red for the given Color, supporting system colors in addition to RGB colors + /// @Note this is marginally slower than SetRgbColor. </summary> procedure SetColor(_Color: TColor); + ///<summary> + /// Sets Blue, Green and Red for the given Color assuming that it is an RGB color and not a system color. + /// @Note this is marginally faster than SetColor. </summary> + procedure SetRgbColor(_Color: TColor); procedure SetGray(_Value: Byte); function GetLuminance: Byte; function GetFastLuminance: Byte; overload; @@ -109,22 +124,39 @@ function GetRgbBrightness(_Red, _Green, _Blue: Byte; _Channel: TRgbBrightnessChannelEnum): Byte; -// if you are using Delphi 2007 or older you need to correct the NativeInt declaration from 8 bytes to 4 bytes: -{$IF SizeOf(Pointer) = 4} -type - NativeInt = Integer; -{$IFEND} +function CalcBytesPerPixel(_PixelFormat: TPixelFormat): Integer; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} -function AddToPtr(const _Ptr: Pointer; _Offset: NativeInt): Pointer; +function CalcBytesPerLine(_Width, _BytesPerPixel: Integer): Integer; overload; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF} +function CalcBytesPerLine(_Width: Integer; _PixelFormat: TPixelFormat): Integer; overload; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} +function CalcBytesPerLine(_Width: Integer; _bmp: TBitmap): Integer; overload; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} -function PtrDiff(const _Ptr1, _Ptr2: Pointer): NativeInt; +procedure IncPtr(var _Ptr: Pointer; _Offset: IntPtr); {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF} +function AddToPtr(const _Ptr: Pointer; _Offset: IntPtr): Pointer; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} + +function PtrDiff(const _Ptr1, _Ptr2: Pointer): IntPtr; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} + function TdzRgbTriple_GetFastLuminance(const _Triple: TdzRgbTriple): Byte; {$IFDEF SUPPORTS_INLINE} inline; @@ -238,6 +270,26 @@ inline; {$ENDIF} +procedure TCanvas_DrawLine(_cnv: TCanvas; _x1, _y1, _x2, _y2: Integer); overload; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} + +procedure TCanvas_DrawLine(_cnv: TCanvas; _pnt1, _pnt2: TPoint); overload; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} + +procedure TCanvas_DrawHorizontalLine(_cnv: TCanvas; _x1, _x2, _y: Integer); +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} + +procedure TCanvas_DrawVerticalLine(_cnv: TCanvas; _x, _y1, _y2: Integer); +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} + ///<summary> calls Windows.SaveDC and returns an interface which will automatically call /// Windows.RestoreDC when destroyed </summary> function TCanvas_SaveDC(_Canvas: TCanvas): IInterface; @@ -287,17 +339,31 @@ ///<summary> abbreviation for StretchBlt that takes TCanvas and TPoint values. </summary> function dzStretchBlt(_DestCnv: TCanvas; _DestTopLeft: TPoint; _DestSize: TPoint; _SrcCnv: TCanvas; _SrcTopLeft: TPoint; _SrcSize: TPoint; _Rop: DWORD = SRCCOPY): BOOL; overload; -{$IFDEF SUPPORTS_INLINE}inline; {$ENDIF} +{$IFDEF SUPPORTS_INLINE}inline; +{$ENDIF} +function dzStretchBlt(_DestCnv: TCanvas; _DestLeft, _DestTop: Integer; _DestSize: TPoint; + _SrcCnv: TCanvas; _SrcTopLeft: TPoint; _SrcSize: TPoint; _Rop: DWORD = SRCCOPY): BOOL; overload; +{$IFDEF SUPPORTS_INLINE}inline; +{$ENDIF} + ///<summary> abbreviation for StretchBlt that takes TCanvas, TBitmap and TPoint values. </summary> function dzStretchBlt(_DestCnv: TCanvas; _DestTopLeft: TPoint; _DestSize: TPoint; _SrcBmp: TBitmap; _SrcTopLeft: TPoint; _SrcSize: TPoint; _Rop: DWORD = SRCCOPY): BOOL; overload; -{$IFDEF SUPPORTS_INLINE}inline; {$ENDIF} +{$IFDEF SUPPORTS_INLINE}inline; +{$ENDIF} +///<summary> abbreviation for StretchBlt that takes TCanvas, TBitmap and TPoint values. </summary> +function dzStretchBlt(_DestCnv: TCanvas; _DestLeft, _DestTop: Integer; _DestSize: TPoint; + _SrcBmp: TBitmap; _SrcTopLeft: TPoint; _SrcSize: TPoint; _Rop: DWORD = SRCCOPY): BOOL; overload; +{$IFDEF SUPPORTS_INLINE}inline; +{$ENDIF} + ///<summary> abbreviation for StretchBlt that takes two TBitmap and TPoint values. </summary> function dzStretchBlt(_DestBmp: TBitmap; _DestTopLeft: TPoint; _DestSize: TPoint; _SrcBmp: TBitmap; _SrcTopLeft: TPoint; _SrcSize: TPoint; _Rop: DWORD = SRCCOPY): BOOL; overload; -{$IFDEF SUPPORTS_INLINE}inline; {$ENDIF} +{$IFDEF SUPPORTS_INLINE}inline; +{$ENDIF} ///<summary> abbreviation for StretchBlt that takes TRect </summary> function dzStretchBlt(_DestHandle: Hdc; _DestRect: TRect; @@ -457,7 +523,6 @@ inline; {$ENDIF} - ///<summary> /// Calculates the positive y coordinate for the given x coordinate for an ellipse /// with horizontal and vertical axes, centered on the coordinate origin (0/0). @@ -526,7 +591,18 @@ {$ENDIF} ///<summary> -/// Calculates the average brightness of an bitmap with PixelFormat = pf8Bit +/// Balances the brightness of the SrcBmp bitmap and returns the result in the DstBmp bitmap +/// If possible, the contrast will also be maximized using histogram stretching. +/// @param SrcBmp ist the input bitmap which will remain unchanged +/// @param DstBmp will be filled with the result. The Result will be an 8 bit grayscal bitmap. +/// @param Offset gives the radius of the area used to calculage the average brightness for each +/// pixel. The default is 3*64 (=192) +/// @NOTE: This currently leaves an outer frame of Offset pixels unchanged. A future version will +/// probably also process that area. </summary> +procedure TBitmap8_BalanceBrightness(_SrcBmp, _DstBmp: TBitmap; _Offset: Word = 3 * 64); // 192 + +///<summary> +/// Calculates the average brightness of a bitmap with PixelFormat = pf8Bit /// @param bmp is the bitmap to process /// @param LowCutoff is the lower brightness limit for pixels to be included in the calculation /// @param HighCutoff is the upper brightness limit for pixels to be included in the calculation @@ -537,7 +613,7 @@ out _Average: Byte): Boolean; ///<summary> -/// Calculates the average brightness of an bitmap with PixelFormat = pf24Bit +/// Calculates the average brightness of a bitmap with PixelFormat = pf24Bit /// @param bmp is the bitmap to process /// @param LowCutoff is the lower brightness limit for pixels to be included in the calculation /// @param HighCutoff is the upper brightness limit for pixels to be included in the calculation @@ -550,7 +626,7 @@ out _Average: Byte): Boolean; ///<summary> -/// Calculates the average brightness of an bitmap with PixelFormat = pf24Bit thereby only +/// Calculates the average brightness of a bitmap with PixelFormat = pf24Bit thereby only /// using the blue channel. /// @param bmp is the bitmap to process /// @param LowCutoff is the lower brightness limit for pixels to be included in the calculation @@ -589,8 +665,21 @@ procedure TBitmap24_GetHistograms(_bmp: TBitmap; _BrightnessChannel: TRgbBrightnessChannelEnum; out _Red, _Green, _Blue, _Brightness: TUInt64Array256); overload; -function TBitmap8_GetHistogram(_bmp: TBitmap): TUInt64Array256; overload; +///<summary> +/// Calcluates the histogram of a grayscale 8, 24 or 32 bit bitmap </summary> +function TBitmapMono_GetHistogram(_bmp: TBitmap): TUInt64Array256; overload; +procedure TBitmapMono_GetHistogram(_bmp: TBitmap; out _Histogram: TUInt64Array256; out _Average: UInt8); overload; +function TBitmap8_GetHistogram(_bmp: TBitmap): TUInt64Array256; overload; deprecated; // use TBitmapMono_GetHistogram +///<summary> +/// Calculates the histogram for an 8 bit grayscale bitmap +/// @param bmp is the bitmap to analyze +/// @param Histogram is an array which will be filled with the histogram +/// @param Average is set to the average brightness of the bitmap +/// todo: This should maybe also (or instead) return the Median </summary> +procedure TBitmap8_GetHistogram(_bmp: TBitmap; out _Histogram: TUInt64Array256; + out _Average: UInt8); overload; deprecated; // use TBitmapMono_GetHistogram + type // Note: The bitmap is stored upside down, so the y coordinates are reversed! TPixel24FilterCallback = procedure(_x, _y: Integer; var _Pixel: TdzRgbTriple) of object; @@ -614,7 +703,7 @@ ///</summary> /// Apply the given gamma curve to an 8 bit gray scale bitmap </summary> -procedure TBitmap8_ApplyGamma(_SrcBmp, _DstBmp: TBitmap; const _Gamma: TGammaCurve); overload; +procedure TBitmap8_ApplyGamma(_SrcBmp, _DstBmp: TBitmap; const _Gamma: TGammaCurve); ///</summary> /// Apply the given gamma curve to a 24 bit gray scale bitmap and convert it to 8 bit @@ -624,11 +713,11 @@ /// @param DstBmp is the destinateion bitmap, it will be set to the same size as the source /// and to PixelFormat pf8bit and a gray scale palette. /// @param Gamma is an array representing the gamma curve to apply. </summary> -procedure TBitmap24_ApplyGammaTo8(_SrcBmp, _DstBmp: TBitmap; const _Gamma: TGammaCurve); overload; +procedure TBitmap24_ApplyGammaTo8(_SrcBmp, _DstBmp: TBitmap; const _Gamma: TGammaCurve); ///</summary> /// Sequentially Apply the given gamma curves to an 8 bit gray scale bitmap </summary> -procedure TBitmap8_ApplyMultiGamma(_SrcBmp, _DstBmp: TBitmap; const _GammaArr: array of TGammaCurve); overload; +procedure TBitmap8_ApplyMultiGamma(_SrcBmp, _DstBmp: TBitmap; const _GammaArr: array of TGammaCurve); type ///<summary> @@ -700,8 +789,30 @@ /// @returns clWhite or clBlack depending on the brightness (luminance) of the color </summary> function BestForegroundForColor(_Color: TColor): TColor; overload; +///<summary> +/// @param Hue is a value between 0 and 1 </summary> function RainbowColor(_Hue: Double): TColor; overload; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} +///<summary> +/// @param Brightness is a grayscale value </summary> +function RainbowColor(_Brightness: Byte): TColor; overload; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} +procedure RainbowColor(_Brightness: Byte; out _Red, _Green, _Blue: Byte); overload; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} +procedure RainbowColor(_Brightness: Byte; out _Pixel: TdzRgbTriple); overload; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} function RainbowColor(_MinHue, _MaxHue, _Hue: Integer): TColor; overload; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} function TryStr2Color(const _s: string; out _Color: TColor): Boolean; @@ -713,6 +824,7 @@ uses Math, + TypInfo, jpeg, // if you get a compile error here you might need to add Vcl.Imaging to the unit scope names {$IFDEF HAS_UNIT_PNGIMAGE} pngimage, // support for TImage.LoadGraphics for PNG files @@ -739,6 +851,17 @@ _SrcSize.x, _SrcSize.y, _Rop); end; +function dzStretchBlt(_DestCnv: TCanvas; _DestLeft, _DestTop: Integer; _DestSize: TPoint; + _SrcCnv: TCanvas; _SrcTopLeft: TPoint; _SrcSize: TPoint; _Rop: DWORD = SRCCOPY): BOOL; +begin + Result := StretchBlt(_DestCnv.Handle, + _DestLeft, _DestTop, + _DestSize.x, _DestSize.y, + _SrcCnv.Handle, + _SrcTopLeft.x, _SrcTopLeft.y, + _SrcSize.x, _SrcSize.y, _Rop); +end; + function dzStretchBlt(_DestCnv: TCanvas; _DestTopLeft: TPoint; _DestSize: TPoint; _SrcBmp: TBitmap; _SrcTopLeft: TPoint; _SrcSize: TPoint; _Rop: DWORD = SRCCOPY): BOOL; begin @@ -746,6 +869,13 @@ _SrcBmp.Canvas, _SrcTopLeft, _SrcSize, _Rop); end; +function dzStretchBlt(_DestCnv: TCanvas; _DestLeft, _DestTop: Integer; _DestSize: TPoint; + _SrcBmp: TBitmap; _SrcTopLeft: TPoint; _SrcSize: TPoint; _Rop: DWORD = SRCCOPY): BOOL; +begin + Result := dzStretchBlt(_DestCnv, _DestLeft, _DestTop, _DestSize, + _SrcBmp.Canvas, _SrcTopLeft, _SrcSize, _Rop); +end; + function dzStretchBlt(_DestBmp: TBitmap; _DestTopLeft: TPoint; _DestSize: TPoint; _SrcBmp: TBitmap; _SrcTopLeft: TPoint; _SrcSize: TPoint; _Rop: DWORD = SRCCOPY): BOOL; overload; begin @@ -1052,6 +1182,29 @@ Result := TCanvas_DrawText(_Canvas, _Text, _Rect, Flags) end; +procedure TCanvas_DrawVerticalLine(_cnv: TCanvas; _x, _y1, _y2: Integer); +begin + _cnv.MoveTo(_x, _y1); + _cnv.LineTo(_x, _y2); +end; + +procedure TCanvas_DrawHorizontalLine(_cnv: TCanvas; _x1, _x2, _y: Integer); +begin + _cnv.MoveTo(_x1, _y); + _cnv.LineTo(_x2, _y); +end; + +procedure TCanvas_DrawLine(_cnv: TCanvas; _x1, _y1, _x2, _y2: Integer); +begin + _cnv.MoveTo(_x1, _y1); + _cnv.LineTo(_x2, _y2); +end; + +procedure TCanvas_DrawLine(_cnv: TCanvas; _pnt1, _pnt2: TPoint); +begin + TCanvas_DrawLine(_cnv, _pnt1.x, _pnt1.y, _pnt2.x, _pnt2.y); +end; + type TCanvasSaveDC = class(TInterfacedObject) private @@ -1158,7 +1311,11 @@ procedure GetRgbHls(_Red, _Green, _Blue: Byte; out _Hls: THlsRec); begin +{$IFDEF dzUseGraphics32} + GR32.RGBtoHSL(GR32.Color32(RGB(_Red, _Green, _Blue)), _Hls.Hue, _Hls.Saturation, _Hls.Luminance); +{$ELSE} ColorRGBToHLS(RGB(_Red, _Green, _Blue), _Hls.Hue, _Hls.Luminance, _Hls.Saturation); +{$ENDIF} end; function GetRgbLuminance(_Red, _Green, _Blue: Byte): Byte; @@ -1190,6 +1347,32 @@ end; end; +function CalcBytesPerPixel(_PixelFormat: TPixelFormat): Integer; +begin + case _PixelFormat of + pf8bit: Result := SizeOf(Byte); + pf24bit: Result := SizeOf(TdzRgbTriple); + pf32bit: Result := SizeOf(TdzRgbQuad); + else + raise EdzPixelFormatNotSupported.Create(_PixelFormat); + end; +end; + +function CalcBytesPerLine(_Width, _BytesPerPixel: Integer): Integer; +begin + Result := ((_Width * 8 * _BytesPerPixel + 31) and not 31) div 8; +end; + +function CalcBytesPerLine(_Width: Integer; _PixelFormat: TPixelFormat): Integer; +begin + Result := CalcBytesPerLine(_Width, CalcBytesPerPixel(_PixelFormat)); +end; + +function CalcBytesPerLine(_Width: Integer; _bmp: TBitmap): Integer; +begin + Result := CalcBytesPerLine(_Width, _bmp.PixelFormat); +end; + {$IFDEF SUPPORTS_ENHANCED_RECORDS} { TdzRgbTriple } @@ -1221,6 +1404,13 @@ Result := RGB(Red, Green, Blue); end; +procedure TdzRgbTriple.SetRgbColor(_Color: TColor); +begin + Red := GetRValue(_Color); + Green := GetGValue(_Color); + Blue := GetBValue(_Color); +end; + procedure TdzRgbTriple.SetColor(_Color: TColor); begin _Color := ColorToRGB(_Color); @@ -1456,6 +1646,9 @@ Red := _Value; Green := _Value; Blue := _Value; + // According to the Win32 API documenation this member is reserved and must be zero, + // but apparently it can be non-zero and contain an alpha value. + Reserved := 0; end; procedure TdzRgbQuad.SetHls(_Hue, _Luminance, _Saturation: Word); @@ -1519,24 +1712,89 @@ end; end; -function MakeGrayPalette(_NumColors: TNumColors): HPALETTE; var + // global structure for the most common case of 256 colors, initialized on demand + GreyPalette256: TMaxLogPalette = ( + palVersion: 0; // 0 => has not been initialized + ); + +procedure InternalMakeGrayPalette(_NumColors: TNumColors; out lp: TMaxLogPalette); +var i: Integer; - lp: TMaxLogPalette; Grey: Byte; + MaxValue: Integer; begin - lp.palVersion := $300; lp.palNumEntries := _NumColors; + MaxValue := _NumColors - 1; for i := 0 to _NumColors - 1 do begin - Grey := i * 255 div _NumColors; + Grey := i * 255 div MaxValue; lp.palPalEntry[i].peRed := Grey; lp.palPalEntry[i].peGreen := Grey; lp.palPalEntry[i].peBlue := Grey; lp.palPalEntry[i].peFlags := PC_RESERVED; end; - Result := CreatePalette(pLogPalette(@lp)^); + // set it last, so we don't create a race condition with multithreaded access + lp.palVersion := $300; end; +function MakeGrayPalette(_NumColors: TNumColors): HPALETTE; +var + lp: TMaxLogPalette; + plp: PMaxLogPalette; +begin + if _NumColors = 256 then begin + if GreyPalette256.palVersion = 0 then + InternalMakeGrayPalette(_NumColors, GreyPalette256); + plp := @GreyPalette256; + end else begin + InternalMakeGrayPalette(_NumColors, lp); + plp := @lp; + end; + Result := CreatePalette(pLogPalette(plp)^); +end; + +///<sumamry> +/// Calls to this function are meant to be enclosed into Assert() so the compiler creates code for +/// it only if assertions are enabled </summary> +function AssertPixelFormat(_bmp: TBitmap; _Expected: TPixelFormat): Boolean; overload; +var + ActualName: string; + ExpectedName: string; +begin + Assert(Assigned(_bmp), 'bitmap is not assigned'); + Result := (_bmp.PixelFormat = _Expected); + if not Result then begin + ActualName := GetEnumName(TypeInfo(TPixelFormat), Ord(_bmp.PixelFormat)); + ExpectedName := GetEnumName(TypeInfo(TPixelFormat), Ord(_Expected)); + Assert(False, 'unexpected PixelFormat ' + ActualName + ' (expected ' + ExpectedName + ')'); + end; +end; + +type + TPixelFormatSet = set of TPixelFormat; + +///<sumamry> +/// Calls to this function are meant to be enclosed into Assert() so the compiler creates code for +/// it only if assertions are enabled </summary> +function AssertPixelFormat(_bmp: TBitmap; _Expected: TPixelFormatSet): Boolean; overload; +var + ActualName: string; + ExpectedNames: string; + pf: TPixelFormat; +begin + Assert(Assigned(_bmp), 'bitmap is not assigned'); + Result := (_bmp.PixelFormat in _Expected); + if not Result then begin + ActualName := GetEnumName(TypeInfo(TPixelFormat), Ord(_bmp.PixelFormat)); + ExpectedNames := ''; + for pf := Low(TPixelFormat) to High(TPixelFormat) do begin + ExpectedNames := ExpectedNames + ',' + GetEnumName(TypeInfo(TPixelFormat), Ord(pf)); + end; + ExpectedNames := Copy(ExpectedNames, 2, 255); + Assert(False, 'unexpected PixelFormat ' + ActualName + ' (expected one of' + ExpectedNames + ')'); + end; +end; + procedure TBitmap_AssignBgr8(_Buffer: PByte; _bmp: TBitmap; _YIsReversed: Boolean); const BytesPerPixel = 3; @@ -1551,7 +1809,7 @@ // bfh: TBitmapFileHeader; // bih: TBitmapInfoHeader; begin - Assert(_bmp.PixelFormat = pf24bit, 'unexpected PixelFormat (expected pf24bit)'); + Assert(AssertPixelFormat(_bmp, pf24bit)); h := _bmp.Height; w := _bmp.Width; @@ -1607,7 +1865,7 @@ ScanLine: PdzRgbTripleArray; h: Integer; begin - Assert(_bmp.PixelFormat = pf24bit, 'unexpected PixelFormat (expected pf24bit)'); + Assert(AssertPixelFormat(_bmp, pf24bit)); h := _bmp.Height; for y := 0 to h - 1 do begin @@ -1637,7 +1895,7 @@ h: Integer; Value: Byte; begin - Assert(_bmp.PixelFormat = pf24bit, 'unexpected PixelFormat (expected pf24bit)'); + Assert(AssertPixelFormat(_bmp, pf24bit)); h := _bmp.Height; for y := 0 to h - 1 do begin if _YIsReversed then begin @@ -1661,7 +1919,7 @@ y: Integer; ScanLine: PByte; begin - Assert(_bmp.PixelFormat = pf8bit, 'unexpected PixelFormat (expected pf8bit)'); + Assert(AssertPixelFormat(_bmp, pf8bit)); // Unfortunately the y coordinates of TBitmap are reversed (the picture is upside down). // So we can only copy the whole picture in one go, if the buffer is also upside down @@ -1680,51 +1938,96 @@ type PByteArray = SysUtils.PByteArray; - TCopyScanline = procedure(_Width: Integer; _SrcLine: Pointer; _DestLine: PByteArray); + TCopyScanline = procedure(_Width: Integer; _SrcLine: Pointer; _DestLine: Pointer); -procedure Copy24Bit(_Width: Integer; _SrcLine: Pointer; _DestLine: PByteArray); +procedure Copy8Bit(_Width: Integer; _SrcLine: Pointer; _DestLine: Pointer); +begin + Move(PByte(_SrcLine)^, PByte(_DestLine)^, _Width); +end; + +procedure Copy24Bit(_Width: Integer; _SrcLine: Pointer; _DestLine: Pointer); var x: Integer; - SrcLine: PdzRgbTripleArray absolute _SrcLine; + SrcPixel: PdzRgbTriple; + DstPixel: PByte; begin + SrcPixel := _SrcLine; + DstPixel := _DestLine; for x := 0 to _Width - 1 do begin - _DestLine[x] := SrcLine[x].Blue; + DstPixel^ := SrcPixel.Blue; + Inc(SrcPixel); + Inc(DstPixel); end; end; -procedure Copy32Bit(_Width: Integer; _SrcLine: Pointer; _DestLine: PByteArray); +procedure Copy32Bit(_Width: Integer; _SrcLine: Pointer; _DestLine: Pointer); var x: Integer; - SrcLine: PdzRgbQuadArray absolute _SrcLine; + SrcPixel: PdzRgbQuad; + DstPixel: PByte; begin + SrcPixel := _SrcLine; + DstPixel := _DestLine; for x := 0 to _Width - 1 do begin - _DestLine[x] := SrcLine[x].Blue; + DstPixel^ := SrcPixel.Blue; + Inc(SrcPixel); + Inc(DstPixel); end; end; procedure TBitmap_MonoToMono8(_InBmp, _OutBmp: TBitmap); +const + DstBytesPerPixel = 1; var CopyScanLine: TCopyScanline; + SrcBytesPerPixel: Integer; + SrcBytesPerLine: Integer; + DstBytesPerLine: Integer; w: Integer; h: Integer; y: Integer; + SrcLine: PByte; + DstLine: PByte; begin - _OutBmp.PixelFormat := pf8bit; - _OutBmp.Palette := MakeGrayPalette(); + Assert(AssertPixelFormat(_InBmp, [pf8bit, pf24bit, pf32bit])); - if _InBmp.PixelFormat = pf24bit then begin - CopyScanLine := Copy24Bit - end else if _InBmp.PixelFormat = pf32bit then begin - CopyScanLine := Copy32Bit; - end else - raise Exception.Create(_('Only bitmaps with PixelFormat = pf32bit or pf24bit are supported')); + case _InBmp.PixelFormat of + pf8bit: begin + CopyScanLine := Copy8Bit; + SrcBytesPerPixel := 1; + end; + pf24bit: begin + CopyScanLine := Copy24Bit; + SrcBytesPerPixel := 3; + end; + pf32bit: begin + CopyScanLine := Copy32Bit; + SrcBytesPerPixel := 4; + end; + else + raise EdzPixelFormatNotSupported.Create(_InBmp.PixelFormat) + end; w := _InBmp.Width; h := _InBmp.Height; + + _OutBmp.PixelFormat := pf8bit; + _OutBmp.Palette := MakeGrayPalette(); + _OutBmp.Width := w; _OutBmp.Height := h; + + SrcBytesPerLine := ((w * 8 * SrcBytesPerPixel + 31) and not 31) div 8; + Assert(SrcBytesPerLine = Graphics.BytesPerScanline(w, SrcBytesPerPixel * 8, 32)); + DstBytesPerLine := ((w * 8 * DstBytesPerPixel + 31) and not 31) div 8; + Assert(DstBytesPerLine = Graphics.BytesPerScanline(w, DstBytesPerPixel * 8, 32)); + + SrcLine := _InBmp.ScanLine[0]; + DstLine := _OutBmp.ScanLine[0]; for y := 0 to h - 1 do begin - CopyScanLine(w, _InBmp.ScanLine[y], _OutBmp.ScanLine[y]); + CopyScanLine(w, SrcLine, DstLine); + Dec(SrcLine, SrcBytesPerLine); + Dec(DstLine, DstBytesPerLine); end; end; @@ -1761,9 +2064,20 @@ w := Length(_In[0]); SetLength(_out, h); + // Yes, this could be moved inside the loop for setting the first and last line. + // but it would bomb out there when w = 0. So we either have to check for w=0 all the time + // or we make it a separate loop. + for y := 0 to h - 1 do begin + SetLength(_out[y], w); + end; + + if (w = 0) or (h = 0) then begin + asm nop end; + Exit; + end; + // copy first and last line without changes for y := 0 to h - 1 do begin - SetLength(_out[y], w); _out[y][0] := _In[y][0]; _out[y][w - 1] := _In[y][w - 1]; end; @@ -2167,8 +2481,7 @@ SrcTriple: PdzRgbTriple; BytesPerLine: Integer; begin - Assert(Assigned(_SrcBmp)); - Assert(_SrcBmp.PixelFormat = pf24bit); + Assert(AssertPixelFormat(_SrcBmp, pf24bit)); _DstBmp.PixelFormat := pf24bit; w := _SrcBmp.Width; @@ -2218,8 +2531,7 @@ SrcTriple: PdzRgbTriple; BytesPerLine: Integer; begin - Assert(Assigned(_SrcBmp)); - Assert(_SrcBmp.PixelFormat = pf24bit); + Assert(AssertPixelFormat(_SrcBmp, pf24bit)); _DstBmp.PixelFormat := pf24bit; w := _SrcBmp.Width; @@ -2269,8 +2581,7 @@ BytesPerLineInput: Integer; BytesPerLineOutput: Integer; begin - Assert(Assigned(_SrcBmp)); - Assert(_SrcBmp.PixelFormat = pf24bit); + Assert(AssertPixelFormat(_SrcBmp, pf24bit)); w := _SrcBmp.Width; h := _SrcBmp.Height; @@ -2318,8 +2629,7 @@ DstPixel: PByte; BytesPerLine: Integer; begin - Assert(Assigned(_SrcBmp)); - Assert(_SrcBmp.PixelFormat = pf8bit); + Assert(AssertPixelFormat(_SrcBmp, pf8bit)); _DstBmp.Assign(nil); _DstBmp.PixelFormat := pf8bit; @@ -2367,8 +2677,7 @@ i: Integer; Value: Byte; begin - Assert(Assigned(_SrcBmp)); - Assert(_SrcBmp.PixelFormat = pf8bit); + Assert(AssertPixelFormat(_SrcBmp, pf8bit)); _DstBmp.Assign(nil); _DstBmp.PixelFormat := pf8bit; @@ -2491,11 +2800,11 @@ // remember: Bitmaps are stored upside down, so for the previous line, we must add BytesPerLine // and for the next line we must subtract BytesPerLine SrcPixelLeft := SrcPixelCenter; - Inc(SrcPixelCenter); + Dec(SrcPixelLeft); SrcPixelRight := SrcPixelCenter; Inc(SrcPixelRight); - SrcPixelTop := PPixel(Integer(SrcPixelCenter) + BytesPerLine); - SrcPixelBottom := PPixel(Integer(SrcPixelCenter) - BytesPerLine); + SrcPixelTop := AddToPtr(SrcPixelCenter, +BytesPerLine); + SrcPixelBottom := AddToPtr(SrcPixelCenter, -BytesPerLine); for Column := 1 to WorkAreaWidth do begin CenterBrightness := SrcPixelCenter^; @@ -2601,16 +2910,16 @@ // We could of course call _SrcBmp.Scanline[], but that would affect the efficiency // of the code due the the function call and some overhead in that code. SrcRows[0] := FirstSrcRow; - SrcRows[1] := PByte(Integer(FirstSrcRow) - BytesPerLine); - SrcRows[2] := PByte(Integer(SrcRows[1]) - BytesPerLine); + SrcRows[1] := AddToPtr(FirstSrcRow, -BytesPerLine); + SrcRows[2] := AddToPtr(SrcRows[1], -BytesPerLine); for Row := 1 to WorkAreaHeight do begin Dec(DstRow, BytesPerLine); DstPixel := PPixel(DstRow); - SrcPixels[0] := PPixel(Integer(SrcRows[0]) + 1 * BytesPerPixel); //top + SrcPixels[0] := AddToPtr(SrcRows[0], +1 * BytesPerPixel); //top SrcPixels[1] := PPixel(SrcRows[1]); //left - SrcPixels[2] := PPixel(Integer(SrcRows[1]) + 1 * BytesPerPixel); //center - SrcPixels[3] := PPixel(Integer(SrcRows[1]) + 2 * BytesPerPixel); //right - SrcPixels[4] := PPixel(Integer(SrcRows[2]) + 1 * BytesPerPixel); //bottom + SrcPixels[2] := AddToPtr(SrcRows[1], +1 * BytesPerPixel); //center + SrcPixels[3] := AddToPtr(SrcRows[1], +2 * BytesPerPixel); //right + SrcPixels[4] := AddToPtr(SrcRows[2], +1 * BytesPerPixel); //bottom DstPixel^ := SrcPixels[1]^; //1st col unchanged for Column := 1 to WorkAreaWidth do begin // calculate average weighted by -beta for each color @@ -2671,18 +2980,23 @@ end; end; -// Inlined method must be iomplemented before it is called -function AddToPtr(const _Ptr: Pointer; _Offset: NativeInt): Pointer; +procedure IncPtr(var _Ptr: Pointer; _Offset: IntPtr); begin - Result := Pointer(NativeInt(_Ptr) + _Offset); + _Ptr := Pointer(IntPtr(_Ptr) + _Offset); end; -// Inlined method must be iomplemented before it is called -function PtrDiff(const _Ptr1, _Ptr2: Pointer): NativeInt; +// Inlined method must be implemented before it is called +function AddToPtr(const _Ptr: Pointer; _Offset: IntPtr): Pointer; begin - Result := NativeInt(_Ptr1) - NativeInt(_Ptr2); + Result := Pointer(IntPtr(_Ptr) + _Offset); end; +// Inlined method must be implemented before it is called +function PtrDiff(const _Ptr1, _Ptr2: Pointer): IntPtr; +begin + Result := IntPtr(_Ptr1) - IntPtr(_Ptr2); +end; + procedure TBitmap8_Sharpen(_SrcBmp, _DstBmp: TBitmap; const _AlphaMap: TSingleMatrix); type PPixel = PByte; @@ -2706,7 +3020,7 @@ CenterBrightness: Integer; AvgBrightness: Integer; BytesPerLine: Integer; - AlphaEntrySize: NativeInt; + AlphaEntrySize: IntPtr; AlphaPtr: PSingle; begin // sharpening is blending of the current pixel @@ -2761,11 +3075,11 @@ // remember: Bitmaps are stored upside down, so for the previous line, we must add BytesPerLine // and for the next line we must subtract BytesPerLine SrcPixelLeft := SrcPixelCenter; - Inc(SrcPixelCenter); + Dec(SrcPixelLeft); SrcPixelRight := SrcPixelCenter; Inc(SrcPixelRight); - SrcPixelTop := PPixel(Integer(SrcPixelCenter) + BytesPerLine); - SrcPixelBottom := PPixel(Integer(SrcPixelCenter) - BytesPerLine); + SrcPixelTop := AddToPtr(SrcPixelCenter, +BytesPerLine); + SrcPixelBottom := AddToPtr(SrcPixelCenter, -BytesPerLine); AlphaPtr := @(_AlphaMap[Row][1]); for Column := 1 to WorkAreaWidth do begin @@ -2804,7 +3118,7 @@ Inc(SrcPixelRight); Inc(SrcPixelBottom); - AlphaPtr := AddToPtr(AlphaPtr, AlphaEntrySize); + IncPtr(Pointer(AlphaPtr), AlphaEntrySize); end; // copy Last column unchanged @@ -2881,8 +3195,8 @@ // We could of course call _SrcBmp.Scanline[], but that would affect the efficiency // of the code due the the function call and some overhead in that code. SrcRows[0] := FirstSrcRow; - SrcRows[1] := PByte(Integer(FirstSrcRow) - BytesPerLine); - SrcRows[2] := PByte(Integer(SrcRows[1]) - BytesPerLine); + SrcRows[1] := AddToPtr(FirstSrcRow, -BytesPerLine); + SrcRows[2] := AddToPtr(SrcRows[1], -BytesPerLine); for Row := 1 to WorkAreaHeight do begin Assert(Length(_AlphaMap[Row]) = _SrcBmp.Width, Format('Number of values in AlphaMap[%d] (%d) must match bitmap width (%d)', @@ -2890,11 +3204,11 @@ Dec(DstRow, BytesPerLine); DstPixel := PPixel(DstRow); - SrcPixels[0] := PPixel(Integer(SrcRows[0]) + 1 * BytesPerPixel); //top + SrcPixels[0] := AddToPtr(SrcRows[0], +1 * BytesPerPixel); //top SrcPixels[1] := PPixel(SrcRows[1]); //left - SrcPixels[2] := PPixel(Integer(SrcRows[1]) + 1 * BytesPerPixel); //center - SrcPixels[3] := PPixel(Integer(SrcRows[1]) + 2 * BytesPerPixel); //right - SrcPixels[4] := PPixel(Integer(SrcRows[2]) + 1 * BytesPerPixel); //bottom + SrcPixels[2] := AddToPtr(SrcRows[1], +1 * BytesPerPixel); //center + SrcPixels[3] := AddToPtr(SrcRows[1], +2 * BytesPerPixel); //right + SrcPixels[4] := AddToPtr(SrcRows[2], +1 * BytesPerPixel); //bottom // copy 1st col unchanged ("[1]" is not the pixel index!) DstPixel^ := SrcPixels[1]^; for Column := 1 to WorkAreaWidth do begin @@ -2958,6 +3272,273 @@ end; end; +// this calculates the average of the given value array using the median +function CalcAverageBrightness(_Arr: array of Integer): Integer; +const + Left = 0; +var + Len: Integer; + Right: Integer; + i: Integer; + j: Integer; + tmp: Integer; + Mid: Integer; +begin + Len := Length(_Arr); + Assert(Len > 0); + Right := Len - 1; + i := Left + 1; + while i <= Right do begin + j := i; + while (j > Left) and (_Arr[j - 1] > _Arr[j]) do begin + tmp := _Arr[j]; + _Arr[j] := _Arr[j - 1]; + _Arr[j - 1] := tmp; + Dec(j); + end; + Inc(i); + end; + Mid := Left + Len div 2; + if Odd(Len) then + Result := _Arr[Mid] + else + Result := (_Arr[Mid] + _Arr[Mid - 1]) div 2; +end; + +procedure TBitmap8_BalanceBrightness(_SrcBmp, _DstBmp: TBitmap; _Offset: Word); +type + PPixel = PByte; +const + BytesPerPixel = 1; + ForcedPixelFormat = pf8bit; +var + Offset: Integer; + Row: Integer; + Column: Integer; + SrcPixel: PPixel; + SrcPixel0: PPixel; + SrcPixel1: PPixel; + SrcPixel2: PPixel; + SrcPixel3: PPixel; + SrcPixel4: PPixel; + SrcPixel5: PPixel; + SrcPixel6: PPixel; + SrcPixel7: PPixel; + SrcPixel8: PPixel; + SrcPixel9: PPixel; + SrcRow: PByte; + DstRow: PByte; + DstPixel: PPixel; + BmpWidth: Integer; + BmpHeight: Integer; + WorkAreaHeight: Integer; + WorkAreaWidth: Integer; + WorkBuffer: array of array of Integer; + CenterBrightness: Integer; + AvgBrightness: Integer; + MinBrightness: Integer; + MaxBrightness: Integer; + BytesPerLine: Integer; + SrcBottomRow: PByte; + DstBottomRow: PByte; + SrcOffset0: Integer; + SrcOffset1: Integer; + SrcOffset2: Integer; + SrcOffset3: Integer; + SrcOffset4: Integer; + SrcOffset5: Integer; + SrcOffset6: Integer; + SrcOffset7: Integer; + SrcOffset8: Integer; + SrcOffset9: Integer; +// TotalBrightness: Int64; +// TotalAvgBrightness: Integer; +begin + Assert((_SrcBmp.Width > 2 * _Offset) and (_SrcBmp.Height > 2 * _Offset), Format('Bitmap must be at least %dx%d', [2 * _Offset, 2 * _Offset])); + Offset := _Offset; + + _SrcBmp.PixelFormat := ForcedPixelFormat; + _DstBmp.PixelFormat := ForcedPixelFormat; + _DstBmp.Palette := MakeGrayPalette; + BmpWidth := _SrcBmp.Width; + BmpHeight := _SrcBmp.Height; + TBitmap_SetSize(_DstBmp, BmpWidth, BmpHeight); + + SetLength(WorkBuffer, BmpHeight); + for Row := 0 to BmpHeight - 1 do + SetLength(WorkBuffer[Row], BmpWidth); + + BytesPerLine := (((BmpWidth) * 8 * BytesPerPixel + 31) and not 31) div 8; + Assert(BytesPerLine = Graphics.BytesPerScanline(BmpWidth, BytesPerPixel * 8, 32)); + + WorkAreaWidth := BmpWidth - 2 * Offset; + WorkAreaHeight := BmpHeight - 2 * Offset; + + MinBrightness := 255; + MaxBrightness := 0; + + // ScanLine[0] is the line with the highest memory address, so we decrement it by + // BytesPerLine to get the next line (which would be ScanLine[1]) + // We could of course call _SrcBmp.Scanline[], but that would affect the efficiency + // of the code due the the function call and some overhead in that code. + + SrcBottomRow := _SrcBmp.ScanLine[0]; + DstBottomRow := _DstBmp.ScanLine[0]; + + // Calculate offsets for pixels around the SrcPixel in these positions: + // + // 0 + // - 1 + // 9 - + // - 2 + // 8 * 3 + // 7 - + // - 4 + // 6 - + // 5 + // + // The distance between SrcPixel and the pixels 0, 4 5 and 8 is Offset. + // This is designed not to be too symmetric. + // I tried using only 0, 3, 5 and 8 but it generated artifacts. + SrcOffset0 := +BytesPerLine * Offset; + SrcOffset1 := +BytesPerLine * Offset * 2 div 3 + Offset * 1 div 3; + SrcOffset2 := +BytesPerLine * Offset * 1 div 3 + Offset * 2 div 3; + SrcOffset3 := +Offset; + SrcOffset4 := -BytesPerLine * Offset * 1 div 2 + Offset * 1 div 2; + SrcOffset5 := -BytesPerLine * Offset; + SrcOffset6 := -BytesPerLine * Offset * 2 div 3 - Offset * 1 div 3; + SrcOffset7 := -BytesPerLine * Offset * 1 div 3 - Offset * 2 div 3; + SrcOffset8 := -Offset; + SrcOffset9 := +BytesPerLine * Offset * 1 div 2 - Offset * 1 div 2; + + // Experimental code: Calculate the total average brightness. + // This was originally meant to adjust the total brightness of the picture back to the + // original average. This is no longer done since we use the minimum and maximum values to + // stretch the histogram at the end to get the best possible contrast. +// TotalBrightness := 0; +// SrcRow := SrcBottomRow; +// for Row := 0 to BmpHeight - 1 do begin +// SrcPixel := PPixel(SrcRow); +// for Column := 0 to BmpWidth - 1 do begin +// CenterBrightness := SrcPixel^; +// Inc(TotalBrightness, CenterBrightness); +// Inc(SrcPixel); +// end; +// Dec(SrcRow, BytesPerLine); +// end; +// TotalAvgBrightness := TotalBrightness div BmpWidth div BmpHeight; + + // Copy bottom row(s) unchanged + SrcRow := SrcBottomRow; + DstRow := DstBottomRow; + for Row := 0 to Offset - 1 do begin + SrcPixel := PPixel(SrcRow); + DstPixel := PPixel(DstRow); + for Column := 0 to BmpWidth - 1 do begin + CenterBrightness := SrcPixel^; + WorkBuffer[Row, Column] := CenterBrightness; + DstPixel^ := CenterBrightness; + Inc(SrcPixel); + Inc(DstPixel); + end; + Dec(SrcRow, BytesPerLine); + Dec(DstRow, BytesPerLine); + end; + + for Row := Offset to Offset + WorkAreaHeight - 1 do begin + SrcPixel := PPixel(SrcRow); + DstPixel := PPixel(DstRow); + + // copy the leftmost column(s) unchanged + for Column := 0 to Offset - 1 do begin + CenterBrightness := SrcPixel^; + WorkBuffer[Row, Column] := CenterBrightness; + DstPixel^ := CenterBrightness; + Inc(SrcPixel); + Inc(DstPixel); + end; + + // remember: Bitmaps are stored upside down, so for the previous line, we must add BytesPerLine + // and for the next line we must subtract BytesPerLine + + SrcPixel0 := AddToPtr(SrcPixel, SrcOffset0); + SrcPixel1 := AddToPtr(SrcPixel, SrcOffset1); + SrcPixel2 := AddToPtr(SrcPixel, SrcOffset2); + SrcPixel3 := AddToPtr(SrcPixel, SrcOffset3); + SrcPixel4 := AddToPtr(SrcPixel, SrcOffset4); + SrcPixel5 := AddToPtr(SrcPixel, SrcOffset5); + SrcPixel6 := AddToPtr(SrcPixel, SrcOffset6); + SrcPixel7 := AddToPtr(SrcPixel, SrcOffset7); + SrcPixel8 := AddToPtr(SrcPixel, SrcOffset8); + SrcPixel9 := AddToPtr(SrcPixel, SrcOffset9); + + for Column := Offset to Offset + WorkAreaWidth - 1 do begin + CenterBrightness := SrcPixel^; + AvgBrightness := CalcAverageBrightness([SrcPixel0^, SrcPixel1^, SrcPixel2^, SrcPixel3^, + SrcPixel4^, SrcPixel5^, SrcPixel6^, SrcPixel7^, SrcPixel8^, SrcPixel9^]); + CenterBrightness := (CenterBrightness - AvgBrightness); + WorkBuffer[Row, Column] := CenterBrightness; + if CenterBrightness < MinBrightness then + MinBrightness := CenterBrightness; + if CenterBrightness > MaxBrightness then + MaxBrightness := CenterBrightness; + + Inc(SrcPixel0); + Inc(SrcPixel1); + Inc(SrcPixel2); + Inc(SrcPixel3); + Inc(SrcPixel4); + Inc(SrcPixel5); + Inc(SrcPixel6); + Inc(SrcPixel7); + Inc(SrcPixel8); + Inc(SrcPixel9); + Inc(SrcPixel); + Inc(DstPixel); + end; + + // copy rightmost column(s) unchanged + for Column := Offset + WorkAreaWidth to BmpWidth - 1 do begin + CenterBrightness := SrcPixel^; + WorkBuffer[Row, Column] := CenterBrightness; + DstPixel^ := CenterBrightness; + Inc(SrcPixel); + Inc(DstPixel); + end; + + Dec(SrcRow, BytesPerLine); + Dec(DstRow, BytesPerLine); + end; + + // copy top row(s) unchanged + for Row := Offset + WorkAreaHeight to BmpHeight - 1 do begin + DstPixel := PPixel(DstRow); + SrcPixel := PPixel(SrcRow); + for Column := 0 to BmpWidth - 1 do begin + CenterBrightness := SrcPixel^; + WorkBuffer[Row, Column] := CenterBrightness; + DstPixel^ := CenterBrightness; + Inc(SrcPixel); + Inc(DstPixel); + end; + Dec(SrcRow, BytesPerLine); + Dec(DstRow, BytesPerLine); + end; + + DstRow := DstBottomRow; + for Row := 0 to BmpHeight - 1 do begin + DstPixel := PPixel(DstRow); + for Column := 0 to BmpWidth - 1 do begin + CenterBrightness := WorkBuffer[Row, Column]; + if (Row >= Offset) and (Row < Offset + WorkAreaHeight) and (Column >= Offset) and (Column < Offset + WorkAreaWidth) then + CenterBrightness := (CenterBrightness - MinBrightness) * 255 * 100 div (MaxBrightness - MinBrightness) div 100; + DstPixel^ := ReduceToByte(CenterBrightness); + Inc(DstPixel); + end; + Dec(DstRow, BytesPerLine); + end; +end; + function TBitmap_BitBlt(_DestBmp: TBitmap; _DestPos: TPoint; _Size: TPoint; _Src: TBitmap; _SrcPos: TPoint; _Rop: DWORD = SRCCOPY): LongBool; begin @@ -3024,6 +3605,8 @@ cnt: Integer; BytesPerLine: Integer; begin + Assert(AssertPixelFormat(_bmp, pf8bit)); + h := _bmp.Height; if h = 0 then begin Result := False; @@ -3073,6 +3656,8 @@ cnt: Integer; BytesPerLine: Integer; begin + Assert(AssertPixelFormat(_bmp, pf24bit)); + h := _bmp.Height; if h = 0 then begin @@ -3126,6 +3711,8 @@ cnt: Integer; BytesPerLine: Integer; begin + Assert(AssertPixelFormat(_bmp, pf24bit)); + h := _bmp.Height; if h = 0 then begin @@ -3290,31 +3877,114 @@ MoveColor(_Pixel); end; -function RainbowColor(_Hue: Double): TColor; overload; +function RainbowColor(_Hue: Double): TColor; // taken from https://stackoverflow.com/a/19719171/49925 +var + Value: Double; + IntValue: Integer; begin - _Hue := EnsureRange(_Hue, 0, 1) * 6; - case Trunc(_Hue) of - 0: Result := RGB(255, Round(Frac(_Hue) * 255), 0); - 1: Result := RGB(255 - Round(Frac(_Hue) * 255), 255, 0); - 2: Result := RGB(0, 255, Round(Frac(_Hue) * 255)); - 3: Result := RGB(0, 255 - Round(Frac(_Hue) * 255), 255); - 4: Result := RGB(Round(Frac(_Hue) * 255), 0, 255); - else - Result := RGB(255, 0, 255 - Round(Frac(_Hue) * 255)); + Value := EnsureRange(_Hue, 0, 1) * 6; + IntValue := Round(Frac(Value) * 255); + case Trunc(Value) of + 0: Result := RGB(255, IntValue, 0); + 1: Result := RGB(255 - IntValue, 255, 0); + 2: Result := RGB(0, 255, IntValue); + 3: Result := RGB(0, 255 - IntValue, 255); + 4: Result := RGB(IntValue, 0, 255); + else // 5 + Result := RGB(255, 0, 255 - IntValue); end; end; -function RainbowColor(_MinHue, _MaxHue, _Hue: Integer): TColor; overload; +procedure RainbowColor(_Brightness: Byte; out _Red, _Green, _Blue: Byte); +var + Brightness: Integer; + TruncValue: Word; + FracValue: Word; +begin + // This is supposed to be a faster version of the overloaded function that takes a double parameter + // because it uses only integer arithmethic. + // Note that I have not timed it, but it "feels" a bit faster. The result is the same. + // -- 2022-03-17 twm + Brightness := Integer(_Brightness) * 6; + DivMod(Brightness, 255, TruncValue, FracValue); + case TruncValue of + 0: begin + _Red := 255; + _Green := FracValue; + _Blue := 0; + end; + 1: begin + _Red := 255 - FracValue; + _Green := 255; + _Blue := 0; + end; + 2: begin + _Red := 0; + _Green := 255; + _Blue := FracValue; + end; + 3: begin + _Red := 0; + _Green := 255 - FracValue; + _Blue := 255; + end; + 4: begin + _Red := FracValue; + _Green := 0; + _Blue := 255; + end; + else // 5 + _Red := 255; + _Green := 0; + _Blue := 255 - FracValue; + end; +end; + +procedure RainbowColor(_Brightness: Byte; out _Pixel: TdzRgbTriple); +begin + RainbowColor(_Brightness, _Pixel.Red, _Pixel.Green, _Pixel.Blue); +end; + +function RainbowColor(_Brightness: Byte): TColor; +var + Red: Byte; + Green: Byte; + Blue: Byte; +begin + RainbowColor(_Brightness, Red, Green, Blue); + Result := RGB(Red, Green, Blue); +// Assert(Result = RainbowColor(_Brightness / 255)); +end; + +function RainbowColor(_MinHue, _MaxHue, _Hue: Integer): TColor; // taken from https://stackoverflow.com/a/19719171/49925 begin Result := RainbowColor((_Hue - _MinHue) / (_MaxHue - _MinHue + 1)); end; -function TBitmap8_GetHistogram(_bmp: TBitmap): TUInt64Array256; overload; -const - BytesPerPixel = 1; +function TBitmap8_GetHistogram(_bmp: TBitmap): TUInt64Array256; var + Average: UInt8; +begin + TBitmapMono_GetHistogram(_bmp, Result, Average); +end; + +procedure TBitmap8_GetHistogram(_bmp: TBitmap; out _Histogram: TUInt64Array256; out _Average: UInt8); +begin + TBitmapMono_GetHistogram(_bmp, _Histogram, _Average); +end; + +function TBitmapMono_GetHistogram(_bmp: TBitmap): TUInt64Array256; +var + Average: UInt8; +begin + TBitmapMono_GetHistogram(_bmp, Result, Average); +end; + +procedure TBitmapMono_GetHistogram(_bmp: TBitmap; out _Histogram: TUInt64Array256; out _Average: UInt8); +var + BytesPerPixel: Integer; w: Integer; h: Integer; x: Integer; @@ -3322,30 +3992,44 @@ ScanLine: PByte; Pixel: PByte; BytesPerLine: Integer; + Sum: Int64; begin - for x := Low(Result) to High(Result) do - Result[x] := 0; + Assert(AssertPixelFormat(_bmp, [pf8bit, pf24bit, pf32bit])); + case _bmp.PixelFormat of + pf8bit: BytesPerPixel := 1; + pf24bit: BytesPerPixel := 3; + pf32bit: BytesPerPixel := 4; + else + raise EdzPixelFormatNotSupported.Create(_bmp.PixelFormat) + end; + _Average := 0; + for x := Low(_Histogram) to High(_Histogram) do + _Histogram[x] := 0; h := _bmp.Height; - if h = 0 then begin + if h = 0 then Exit; //==> - end; w := _bmp.Width; + if w = 0 then + Exit; //==> BytesPerLine := ((w * 8 * BytesPerPixel + 31) and not 31) div 8; Assert(BytesPerLine = Graphics.BytesPerScanline(w, BytesPerPixel * 8, 32)); + Sum := 0; ScanLine := _bmp.ScanLine[0]; for y := 0 to h - 1 do begin Assert(ScanLine = _bmp.ScanLine[y]); Pixel := ScanLine; for x := 0 to w - 1 do begin - Inc(Result[Pixel^]); + Inc(_Histogram[Pixel^]); + Inc(Sum, Pixel^); Inc(Pixel, BytesPerPixel); end; Dec(ScanLine, BytesPerLine); end; + _Average := (Sum div w) div h; end; function TBitmap24_GetHistogram(_bmp: TBitmap; _Channel: TRgbBrightnessChannelEnum): TUInt64Array256; overload; @@ -3360,6 +4044,8 @@ Pixel: PByte; BytesPerLine: Integer; begin + Assert(AssertPixelFormat(_bmp, pf24bit)); + for x := Low(Result) to High(Result) do Result[x] := 0; @@ -3401,6 +4087,8 @@ Pixel: PByte; BytesPerLine: Integer; begin + Assert(AssertPixelFormat(_bmp, pf24bit)); + for x := Low(_Red) to High(_Red) do begin _Red[x] := 0; _Green[x] := 0; @@ -3551,4 +4239,15 @@ end; end; +{ EdzPixelFormatNotSupported } + +constructor EdzPixelFormatNotSupported.Create(_PixelFormat: TPixelFormat); +var + PixelFormatName: string; +begin + PixelFormatName := GetEnumName(TypeInfo(TPixelFormat), Ord(_PixelFormat)); + CreateFmt(_('PixelFormat %s not supported'), [PixelFormatName]); +end; + end. + Modified: trunk/ExternalSource/dzlib/u_dzOsUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzOsUtils.pas 2022-05-29 12:55:09 UTC (rev 3848) +++ trunk/ExternalSource/dzlib/u_dzOsUtils.pas 2022-05-29 13:48:58 UTC (rev 3849) @@ -300,6 +300,14 @@ /// is lying, we might as well directly call GetKernel32Version instead. </summary> function GetKernel32Version(out _Major, _Minor, _Revision, _Build: Integer): Boolean; +///<summary> +/// Uses the GetLogicalProcessorInformation WinAPI function to get the size of the processor's cache line </summary> +function GetCpuCacheLineSize: Integer; + +///<summary> +/// Uses the GetSystemInfo WinAPI function to get number of logical processors </summary> +function GetCpuLogicalProcessorCount: Integer; + implementation uses @@ -848,7 +856,7 @@ Exit; //==> end; - while Extractfilename(fn) <> '' do begin + while ExtractFileName(fn) <> '' do begin fn := ExtractFileDir(fn); if (fn <> '') and DirectoryExists(fn) then begin ShellExecEx(fn, '', '', SW_SHOWNORMAL); @@ -1342,4 +1350,103 @@ Result := Result + ' ' + Values.CSDVersion; end; +{$IF not declared(PSystemLogicalProcessorInformation)} +{$ALIGN ON} +{$MINENUMSIZE 4} + +{$IF not... [truncated message content] |
From: <tw...@us...> - 2023-02-18 16:03:04
|
Revision: 3965 http://sourceforge.net/p/gexperts/code/3965 Author: twm Date: 2023-02-18 16:03:00 +0000 (Sat, 18 Feb 2023) Log Message: ----------- updated to latest version from OSDN Modified Paths: -------------- trunk/ExternalSource/dzlib/dzlib.inc trunk/ExternalSource/dzlib/u_dzAdvancedObject.pas trunk/ExternalSource/dzlib/u_dzClassUtils.pas trunk/ExternalSource/dzlib/u_dzDateUtils.pas trunk/ExternalSource/dzlib/u_dzFileUtils.pas trunk/ExternalSource/dzlib/u_dzLineBuilder.pas trunk/ExternalSource/dzlib/u_dzMiscUtils.pas trunk/ExternalSource/dzlib/u_dzQuicksort.pas trunk/ExternalSource/dzlib/u_dzSortUtils.pas trunk/ExternalSource/dzlib/u_dzSpeedBitBtn.pas trunk/ExternalSource/dzlib/u_dzStringArrayUtils.pas trunk/ExternalSource/dzlib/u_dzStringUtils.pas trunk/ExternalSource/dzlib/u_dzTranslator.pas trunk/ExternalSource/dzlib/u_dzTypInfo.pas trunk/ExternalSource/dzlib/u_dzTypes.pas trunk/ExternalSource/dzlib/u_dzTypesUtils.pas trunk/ExternalSource/dzlib/u_dzVclUtils.pas trunk/ExternalSource/dzlib/u_dzVersionInfo.pas Modified: trunk/ExternalSource/dzlib/dzlib.inc =================================================================== --- trunk/ExternalSource/dzlib/dzlib.inc 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/dzlib.inc 2023-02-18 16:03:00 UTC (rev 3965) @@ -82,6 +82,10 @@ {$DEFINE HAS_TMONITOR_PIXELSPERINCH} {$ENDIF} +{$IFDEF DELPHIXE3_UP} +{$DEFINE SUPPORTS_RECORD_HELPERS_FOR_SIMPLE_TYPES} +{$ENDIF} + {$IFDEF DELPHIX_BERLIN_UP} // TMform.GetDesignDpi was introduced in Delphi 10.0 Seattle {$DEFINE HAS_TFORM_GETDESIGNDPI} Modified: trunk/ExternalSource/dzlib/u_dzAdvancedObject.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzAdvancedObject.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzAdvancedObject.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -107,11 +107,17 @@ function TryGetFloatProperty(const _Name: string; out _Value: Double): Boolean; overload; function TryGetFloatProperty(const _Name: string; out _Value: Single): Boolean; overload; {$IFDEF SUPPORTS_EXTENDED} + class function GetFloatProperty(_Instance: TObject; const _Name: string): Extended; overload; + class function GetFloatProperty(_Instance: TObject; const _Name: string; const _Default: Extended): Extended; overload; function GetFloatProperty(const _Name: string; const _Default: Extended): Extended; overload; function GetFloatProperty(const _Name: string): Extended; overload; + class function SetFloatProperty(_Instance: TObject; const _Name: string; const _Value: Extended): Boolean; overload; {$ELSE} + class function GetFloatProperty(_Instance: TObject; const _Name: string): Double; overload; + class function GetFloatProperty(_Instance: TObject; const _Name: string; const _Default: Double): Double; overload; function GetFloatProperty(const _Name: string; const _Default: Double): Double; overload; function GetFloatProperty(const _Name: string): Double; overload; + class function SetFloatProperty(_Instance: TObject; const _Name: string; const _Value: Double): Boolean; overload; {$ENDIF} ///<summary> @@ -153,6 +159,7 @@ class function GetObjectProperty(_Instance: TObject; const _Name: string; _Default: TObject): TObject; overload; function GetObjectProperty(const _Name: string): TObject; overload; class function GetObjectProperty(_Instance: TObject; const _Name: string): TObject; overload; + class function SetObjectProperty(_Instance: TObject; const _Name: string; _Value: TObject): Boolean; ///<summary> /// Access an event property @@ -298,10 +305,20 @@ class function TAdvancedObject.SetIntProperty(_Instance: TObject; const _Name: string; _Value: Integer): Boolean; begin - Result := u_dzTypInfo.TrySetIntProperty(_Instance, _Name, _Value); + Result := u_dzTypInfo.TrySetIntProperty(_Instance, _Name, _Value); end; {$IFDEF SUPPORTS_EXTENDED} +class function TAdvancedObject.GetFloatProperty(_Instance: TObject; const _Name: string): Extended; +begin + Result := u_dzTypInfo.GetFloatProperty(_Instance, _Name); +end; + +class function TAdvancedObject.GetFloatProperty(_Instance: TObject; const _Name: string; const _Default: Extended): Extended; +begin + Result := u_dzTypInfo.GetFloatProperty(_Instance, _Name, _Default); +end; + function TAdvancedObject.GetFloatProperty(const _Name: string; const _Default: Extended): Extended; begin Result := u_dzTypInfo.GetFloatProperty(Self, _Name, _Default); @@ -311,7 +328,23 @@ begin Result := u_dzTypInfo.GetFloatProperty(Self, _Name); end; + +class function TAdvancedObject.SetFloatProperty(_Instance: TObject; const _Name: string; const _Value: Extended): Boolean; +begin + Result := u_dzTypInfo.TrySetFloatProperty(_Instance, _Name, _Value); +end; + {$ELSE} +class function TAdvancedObject.GetFloatProperty(_Instance: TObject; const _Name: string): Double; +begin + Result := u_dzTypInfo.GetFloatProperty(_Instance, _Name); +end; + +class function TAdvancedObject.GetFloatProperty(_Instance: TObject; const _Name: string; const _Default: Double): Double; +begin + Result := u_dzTypInfo.GetFloatProperty(_Instance, _Name, _Default); +end; + function TAdvancedObject.GetFloatProperty(const _Name: string; const _Default: Double): Double; overload; begin Result := u_dzTypInfo.GetFloatProperty(Self, _Name, _Default); @@ -321,6 +354,11 @@ begin Result := u_dzTypInfo.GetFloatProperty(Self, _Name); end; + +class function TAdvancedObject.SetFloatProperty(_Instance: TObject; const _Name: string; const _Value: Double): Boolean; +begin + Result := u_dzTypInfo.TrySetFloatProperty(_Instance, _Name, _Value); +end; {$ENDIF} function TAdvancedObject.GetIntProperty(const _Name: string): Integer; @@ -356,6 +394,11 @@ Result := GetObjectProperty(Self, _Name); end; +class function TAdvancedObject.SetObjectProperty(_Instance: TObject; const _Name: string; _Value: TObject): Boolean; +begin + Result := u_dzTypInfo.TrySetObjectProperty(_Instance, _Name, _Value); +end; + function TAdvancedObject.GetStringProperty(const _Name, _Default: string): string; begin Result := u_dzTypInfo.GetStringProperty(Self, _Name, _Default); @@ -586,7 +629,7 @@ SetLength(Result, cnt); for i := 0 to cnt - 1 do begin PropInfo := Props^[i]; - Result[i] := String(PropInfo.Name); + Result[i] := string(PropInfo.Name); end; finally FreeMem(Props); Modified: trunk/ExternalSource/dzlib/u_dzClassUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzClassUtils.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzClassUtils.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -19,6 +19,7 @@ Registry, u_dzTranslator, u_dzTypes, + u_dzMiscUtils, // for inlining u_dzDateUtils; // we need this for the $IF Declared() directives // NOTE: The naming convention is <extended-class>_<Methodname> @@ -711,7 +712,6 @@ uses StrUtils, u_dzConvertUtils, - u_dzMiscUtils, u_dzStringUtils; function _(const _s: string): string; Modified: trunk/ExternalSource/dzlib/u_dzDateUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzDateUtils.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzDateUtils.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -13,8 +13,10 @@ interface uses + Windows, // for inlining SysUtils, u_dzTranslator, + u_dzStringUtils, // for inlining u_dzTypes; type @@ -161,8 +163,7 @@ uses SysConst, StrUtils, - DateUtils, - u_dzStringUtils; + DateUtils; function _(const _s: string): string; {$IFDEF SUPPORTS_INLINE} Modified: trunk/ExternalSource/dzlib/u_dzFileUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzFileUtils.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzFileUtils.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -135,7 +135,8 @@ /// @param List is a string list to which the files will be appended, may be nil /// @param IncludePath determines whether the List of filenames includes the full path or not </summary> class function EnumDirsOnly(const _Mask: string; _List: TStrings; - _IncludePath: Boolean = False; _Sort: Boolean = True): Integer; + _IncludePath: Boolean = False; _Sort: Boolean = True): Integer; overload; + class function EnumDirsOnly(const _Mask: string; _IncludePath: Boolean = False; _Sort: Boolean = True): TStringArray; overload; /// <summary> /// Calls SysUtils.FindFirst on first call and SysUtls.FindNext in later /// calls. @@ -735,7 +736,9 @@ /// the full paths. /// @returns the number of matching files </summary> class function FindMatchingFiles(const _Mask: string; _sl: TStrings; _IncludePath: Boolean = False; - _Sort: Boolean = True): Integer; + _Sort: Boolean = True): Integer; overload; + class function FindMatchingFiles(const _Mask: string; + _IncludePath: Boolean = False; _Sort: Boolean = True): TStringArray; overload; /// <summary> /// tries to find a matching file @@ -757,9 +760,10 @@ class function FileExists(const _Filename: string; _RaiseException: Boolean): Boolean; overload; deprecated; // use AssertFileExists instead ///<summary> /// Checks if the given file exists. Note that wildcards are not supported! If you - /// need wildcards, use FindMatchingFile. + /// need wildcards, use AssertMatchingFileExists. /// @raises EFileNotFound if the file does not exist. </summary> class procedure AssertFileExists(const _Filename: string); + class procedure AssertMatchingFileExists(const _Mask: string); ///<summary> /// @param RaiseException determines whether an exception should be raised if the directory does not exist @@ -773,8 +777,8 @@ ///<summary> /// @param DirNames is a TStrings object containing a list of directory names to check. - /// @retursn true, if all directories in the list exist, false otherwise - /// Note: Passing an empty list, result in true. </summary> + /// @returns true, if all directories in the list exist, false otherwise + /// @NOTE: Passing an empty list will return True. </summary> class function AllDirsExist(_DirNames: TStrings): Boolean; /// <summary> @@ -788,7 +792,7 @@ /// @param Force is a boolean which controls whether this function will try to delete /// readonly directories, If true, it will use SetFileAttr to reset the /// readonly attribut and try to delete the directory again. - /// @returns true, if the directory could be deleted, false otherwise. + /// @returns True, if the directory could be deleted, false otherwise. /// @raises EOSError if there was an error and RaiseException was true </summary> class function RemoveDir(const _DirName: string; _RaiseException: Boolean = True; _Force: Boolean = False): Boolean; @@ -808,7 +812,7 @@ /// if it fails. If false, it will not raise an exception /// but just return false if deleting the directory fails. /// @param Force specifies whether it should also delete readonly files - /// @returns true, if the directory could be deleted, false otherwise. + /// @returns True, if the directory could be deleted, false otherwise. /// @raises EOSError if there was an error and RaiseException was true </summary> class function DelDirTree(const _DirName: string; _RaiseException: Boolean = True; _Force: Boolean = False): Boolean; @@ -1010,7 +1014,21 @@ ///<summary> /// Short for ChangeFileExtLast(_Filename, '') </summary> class function RemoveFileExtLast(const _Filename: string): string; + ///<summary> + /// @param Ext is the full file extension to check for, including the leading dot. + /// @returns True, if the full extension of Filename matches the given extension. + /// Comparison is case insensitive + /// False if the extensions don't machch. </summary> + class function HasFileExtFull(const _Filename: string; const _Ext: string): Boolean; + ///<summary> + /// @param Ext is the last file extension to check for, including the leading dot. + /// @returns True, if the last extension of Filename matches the given extension. + /// Comparison is case insensitive + /// False if the extensions don't machch. </summary> + class function HasFileExtLast(const _Filename: string; const _Ext: string): Boolean; + + ///<summary> /// Sets the file's date and time to the given time or to the current time /// @param Fileanme is the name of the file to touch /// @param lpSystemTime is a pointer to a TSystemTime record givng the time, @@ -1314,6 +1332,19 @@ end; end; +class function TSimpleDirEnumerator.EnumDirsOnly(const _Mask: string; _IncludePath, _Sort: Boolean): TStringArray; +var + dirs: TStringList; +begin + dirs := TStringList.Create; + try + EnumDirsOnly(_Mask, dirs, _IncludePath, _Sort); + Result := TStringArray_FromStrings(dirs); + finally + FreeAndNil(dirs); + end; +end; + class procedure TSimpleDirEnumerator.EnumFilesOnly(const _Mask: string; _Callback: TOnFileEnumCallback; _IncludePath: Boolean = False; _Sort: Boolean = True); var @@ -1512,6 +1543,16 @@ Result := GetRemoteVolumeName(_DriveLetter + ':\'); end; +class function TFileSystem.HasFileExtFull(const _Filename, _Ext: string): Boolean; +begin + Result := SameText(_Ext, ExtractFileExtFull(_Filename)); +end; + +class function TFileSystem.HasFileExtLast(const _Filename, _Ext: string): Boolean; +begin + Result := SameText(_Ext, ExtractFileExtLast(_Filename)); +end; + class function TFileSystem.GetRemoteVolumeName(const _Share: string): string; var Res: LongBool; @@ -2477,6 +2518,12 @@ raise EFileNotFound.CreateFmt(_('File not found: %s'), [_Filename]); end; +class procedure TFileSystem.AssertMatchingFileExists(const _Mask: string); +begin + if FindMatchingFile(_Mask) <> mfFile then + raise EFileNotFound.CreateFmt(_('Matching file not found: %s'), [_Mask]); +end; + class function TFileSystem.DirExists(const _DirName: string): Boolean; begin Result := SysUtils.DirectoryExists(_DirName); @@ -2545,6 +2592,24 @@ Result := FindMatchingFile(_Mask, fn); end; +class function TFileSystem.FindMatchingFiles(const _Mask: string; + _IncludePath: Boolean; _Sort: Boolean): TStringArray; +var + Cnt: Integer; + sl: TStringList; + i: Integer; +begin + sl := TStringList.Create; + try + Cnt := FindMatchingFiles(_Mask, sl, _IncludePath, _Sort); + SetLength(Result, Cnt); + for i := 0 to Cnt - 1 do + Result[i] := sl[i]; + finally + FreeAndNil(sl); + end; +end; + class function TFileSystem.FindMatchingFiles(const _Mask: string; _sl: TStrings; _IncludePath: Boolean = False; _Sort: Boolean = True): Integer; begin Modified: trunk/ExternalSource/dzlib/u_dzLineBuilder.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzLineBuilder.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzLineBuilder.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -69,6 +69,7 @@ function Length: Integer; ///<summary> allows read access to the content that has been built </summary> property Content: string read FContent; + ///<summary> Number of columns that have been added to this line </summary> property ColumnCount: Integer read FColumnCount; property DecimalSeparator: Char read GetDecimalSeparator write SetDecimalSeparator default '.'; property ListSeparator: string read FListSeparator write FListSeparator; Modified: trunk/ExternalSource/dzlib/u_dzMiscUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzMiscUtils.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzMiscUtils.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -249,9 +249,7 @@ procedure NotImplemented; begin -{$IFNDEF console} - if mrAbort = MessageDlg('Function not implemented!', mtWarning, [mbAbort, mbIgnore], 0) then -{$ENDIF} + if ID_YES <> Windows.MessageBox(0, 'Function not implemented! Continue anyway?', 'Warning', MB_YESNO + MB_ICONWARNING) then raise ENotImplemented.Create('Function not implemented'); end; {$ENDIF debug} Modified: trunk/ExternalSource/dzlib/u_dzQuicksort.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzQuicksort.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzQuicksort.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -10,58 +10,132 @@ interface uses + Classes, + SysUtils, u_dzSortUtils; type - // for binary search + ///<summary> + /// raised in the sorted list templates instead of EListError so it is possible to + /// specifically ignore these exceptions in the debugger if they are handled in code </summary> + EdzListError = class(EListError) + end; + +type + ///<sumary> + /// Method pointer for passing to BinarySearch + /// @param Key is the key to compare to as an untyped const parameter + /// @param Index is the index of te item in the list to compare this key to. + /// @returns 0 if Key = Item[Idx].Key + /// 1 if Key > Item[Idx].Key + /// -1 if Key < Item[Idx].Key</summary> TCompareToItemMeth1 = function(const _Key; _Idx: Integer): Integer of object; - TCompareToItemMeth2 = function(_Key: pointer; _Idx: Integer): Integer of object; + ///<sumary> + /// Method pointer for passing to BinarySearch + /// @param Key is a pointer to the key to compare to + /// @param Index is the index of te item in the list to compare this key to. + /// @returns 0 if Key = Item[Idx].Key + /// 1 if Key > Item[Idx].Key + /// -1 if Key < Item[Idx].Key</summary> + TCompareToItemMeth2 = function(_Key: Pointer; _Idx: Integer): Integer of object; + ///<summary> -/// Call Quicksort with two method pointers for -/// comparing and swapping two elements. -/// @longcode(## -/// Quicksort(0, Count-1, self.CompareItems, self.SwapItems); -/// ##) } +/// Quicksort with two method pointers for comparing and swapping two elements. +/// The method pointer signatures are declared in u_dzSortUtils. +/// @longcode(## +/// Quicksort(0, Count-1, self.CompareItems, self.SwapItems); +/// ##) </summary> procedure QuickSort(_Left, _Right: Integer; _CompareMeth: TCompareItemsMeth; _SwapMeth: TSwapItemsMeth); overload; ///<summary> -/// Call Quicksort with an interface that does the comparison and swapping -/// comparing and swapping two elements. -/// @longcode(## -/// Quicksort(0, Count-1, CompareAndSwapInterface); -/// ##) } +/// Quicksort with an ISortDataHandler interface that does the comparison and swapping +/// The ISortDataHandler interface are declared in u_dzSortUtils. +/// @longcode(## +/// Quicksort(0, Count-1, CompareAndSwapInterface); +/// ##) </summary> procedure QuickSort(_Left, _Right: Integer; _DataHandler: ISortDataHandler); overload; ///<summary> -/// Call BinarySearch with a method pointer that -/// compares an index to the Item sought. -/// @param Index contains the index where the item is supposed to be -/// (Its index, if it was found or the index where it would be inserted if not) -/// @param Duplicates determines whether duplicates are allowed in the list or not -/// @returns true, if the item was found, false otherwise -/// @longcode(## -/// Found := BinarySearch(0, count-1, Idx, Key, Self.CompareToKey); -/// ##) } +/// Quicksort with an ISortDataHandlerEx interface that does the comparison and swapping +/// and also give the number of items to sort. +/// The ISortDataHandlerEx interface are declared in u_dzSortUtils. +/// @longcode(## +/// Quicksort(0, Count-1, CountCompareAndSwapInterface); +/// ##) </summary> +procedure QuickSort(_DataHandler: ISortDataHandlerEx); overload; + +///<summary> +/// BinarySearch with a method pointer that compares an index to the Item sought. +/// @param Index contains the index, where the item was found (if Result = True), +/// or where it would be inserted (if Result = False) +/// @param Duplicates determines whether to check for duplicates in the list +/// If True, Index will always be that of first item that matches the key. +/// If False, Index will be any item that matches the key. +/// @returns True, if the item was found, False otherwise +/// @longcode(## +/// Found := BinarySearch(0, Count - 1, Idx, Key, Self.CompareToKey); +/// ##) </summary> function BinarySearch(_Left, _Right: Integer; out _Index: Integer; const _Key; _CompareMeth: TCompareToItemMeth1; _Duplicates: Boolean = False): Boolean; overload; +///<summary> +/// BinarySearch with a method pointer that compares an index to the Item sought. +/// @param Index contains the index, where the item was found (if Result = True), +/// or where it would be inserted (if Result = False) +/// @param Duplicates determines whether to check for duplicates in the list +/// If True, Index will always be that of first item that matches the key. +/// If False, Index will be any item that matches the key. +/// @returns True, if the item was found, False otherwise +/// @longcode(## +/// Found := BinarySearch(0, Count - 1, Idx, Key, Self.CompareToKey); +/// ##) </summary> function BinarySearch(_Left, _Right: Integer; out _Index: Integer; - _Key: pointer; _CompareMeth: TCompareToItemMeth2; + _Key: Pointer; _CompareMeth: TCompareToItemMeth2; _Duplicates: Boolean = False): Boolean; overload; type ICompareToKey = interface ['{CEB61050-D71F-4F67-B9BC-FD496A079F75}'] + ///<summary> + /// Compares the key (stored in the interface) to the the item with the given index. + /// @param Index is the index of te item in the list to compare this key to. + /// @returns 0 if Key = Item[Idx].Key + /// 1 if Key > Item[Idx].Key + /// -1 if Key < Item[Idx].Key</summary> function CompareTo(_Idx: Integer): Integer; end; +type + ICompareToKeyEx = interface(ICompareToKey)['{10673750-EE58-40E3-A144-CA9EF517EBCA}'] + function Count: Integer; + end; + +///<summary> +/// BinarySearch with an ICompareToKey interface that compares an index to the Item sought. +/// @param Index contains the index, where the item was found (if Result = True), +/// or where it would be inserted (if Result = False) +/// @param Duplicates determines whether to check for duplicates in the list +/// If True, Index will always be that of first item that matches the key. +/// If False, Index will be any item that matches the key. +/// @returns True, if the item was found, False otherwise +/// @longcode(## +/// Found := BinarySearch(0, Count - 1, Idx, Key, CompareToInt); +/// ##) } </summary> function BinarySearch(_Left, _Right: Integer; out _Index: Integer; _CompareInt: ICompareToKey; _Duplicates: Boolean = False): Boolean; overload; +function BinarySearch(out _Index: Integer; + _CompareExInt: ICompareToKeyEx; _Duplicates: Boolean = False): Boolean; overload; + implementation +procedure QuickSort(_DataHandler: ISortDataHandlerEx); overload; +begin + QuickSort(0, _DataHandler.Count - 1, _DataHandler); +end; + procedure QuickSort(_Left, _Right: Integer; _DataHandler: ISortDataHandler); overload; var I, J, P: Integer; @@ -204,5 +278,11 @@ _Index := _Left; end; +function BinarySearch(out _Index: Integer; + _CompareExInt: ICompareToKeyEx; _Duplicates: Boolean = False): Boolean; +begin + Result := BinarySearch(0, _CompareExInt.Count - 1, _Index, _CompareExInt, _Duplicates); +end; + end. Modified: trunk/ExternalSource/dzlib/u_dzSortUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzSortUtils.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzSortUtils.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -30,12 +30,19 @@ /// <0 if Item[Idx1] < Item[Idx2] /// >0 if Item[Idx1] > Item[Idx2] </summary> function Compare(_Idx1, _Idx2: Integer): Integer; - ///<summary> - /// Swap the items at the given indexes </summary> + ///<summary> + /// Swap the items at the given indexes </summary> procedure Swap(_Idx1, _Idx2: Integer); end; type + ///<summary> + /// Adds a Count method to the ISortDataHander interface </summary> + ISortDataHandlerEx = interface(ISortDataHandler)['{C2DD7397-C0C3-4519-AA24-7FB2EF559DAD}'] + function Count: Integer; + end; + +type IQSDataHandler = ISortDataHandler {$IFDEF SUPPORTS_DEPRECATED_TYPES} deprecated // use ISortDataHandler instead Modified: trunk/ExternalSource/dzlib/u_dzSpeedBitBtn.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzSpeedBitBtn.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzSpeedBitBtn.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -18,8 +18,8 @@ type ///<summary> /// A helper component that turns a TBitBtn into a button that works similar to a TSpeedButton - /// but can receive the focus. It allows to either set a caption or a Glyph, but will ignore - /// the Glyph if Caption is <> ''. + /// but can receive the focus. It allows to either set a caption and a Glyp and even supports + /// word wrapping and setting a margin. /// Clicking the button will first set its Tag property to 0 (up) or down (1) and then call the /// original OnClick method. /// To use it create it with TdzSpeedBitBtn.Create(BitBtn) where BitBtn is an already existing @@ -34,6 +34,9 @@ FUpBmp: TBitmap; FDownBmp: TBitmap; FData: Pointer; + FNeedsNewGlyphs: Boolean; + FOrigMargin: Integer; + FOrigSpacing: Integer; procedure doOnClick(_Sender: TObject); procedure HandleOnClick(_Sender: TObject); function GetDown: Boolean; @@ -40,6 +43,8 @@ procedure SetDown(const Value: Boolean); procedure UpdateGlyph; function GetBitBtn: TBitBtn; + procedure PrepareBmp(_w, _h: Integer; _Color: TColor; _Edge: UINT; out _bmp: TBitmap); + procedure PrepareBmps; protected procedure NewWindowProc(var _Msg: TMessage); override; public @@ -108,250 +113,256 @@ { TdzSpeedBitBtn } constructor TdzSpeedBitBtn.Create(_btn: TWinControl); +begin + inherited Create(_btn); + FOrigOnClick := BitBtn.OnClick; + FCaption := BitBtn.Caption; - procedure PrepareBmp(_w, _h: Integer; _Color: TColor; _Edge: UINT; out _bmp: TBitmap); - var - cnv: TCanvas; + FOrigBmp := TBitmap.Create; + FOrigBmp.Assign(BitBtn.Glyph); + FOrigBmp.Transparent := True; - procedure HandleBmpOnly; - var - x: Integer; - y: Integer; - begin - x := BitBtn.Margin; - y := (_h - FOrigBmp.Height) div 2; - if x = -1 then begin - // center image in the button - x := (_w - FOrigBmp.Width) div 2; - end else begin - // left align image - end; - cnv.Draw(x, y, FOrigBmp); - end; + BitBtn.Caption := ''; - procedure HandleTextOnlySingleLine; - var - x: Integer; - r: TRect; - HorizontalAlignment: TDrawTextHorizontalAlignment; - begin - x := BitBtn.Margin; - if x = -1 then begin - HorizontalAlignment := dthaCenter; - r := Rect(2, 0, _w - 3, _h); - end else begin - HorizontalAlignment := dthaLeft; - r := Rect(x + 2, 0, _w - 3, _h); - end; - TCanvas_DrawTextSingleLine(cnv, FCaption, r, HorizontalAlignment, dtvaCenter, []); - end; + FUpBmp := TBitmap.Create; + FDownBmp := TBitmap.Create; - procedure HandleTextOnlyMultiLine; - var - x: Integer; - r: TRect; - TextWidth: Integer; - TextHeight: Integer; - begin - x := BitBtn.Margin; - if x = -1 then begin - // center - r := Rect(2, 0, _w - 3, _h - 4); - TCanvas_DrawText(cnv, FCaption, r, [dtfCalcRect, dtfCenter, dtfWordBreak]); - TextHeight := r.Bottom - r.Top; - r.Left := 2; - r.Top := Max(0, (_h - TextHeight) div 2); - r.Right := _w - 3; - r.Bottom := Min(_h - 4, r.Top + TextHeight); - TCanvas_DrawText(cnv, FCaption, r, [dtfCenter, dtfWordBreak]); - end else begin - // left align the centered text - // Yes, that doesn't make much sense, but TBitBtn works that way. - // Actually it's even worse: TBitBtn draws the text centered on the possible button width - // and then moves it to the right which clips the text if it is too wide. - // We don't make that mistake here but still center the text and then move it. - r := Rect(x + 2, 0, _w - 3, _h - 4); - TCanvas_DrawText(cnv, FCaption, r, [dtfCalcRect, dtfCenter, dtfWordBreak]); - TextWidth := r.Right - r.Left; - TextHeight := r.Bottom - r.Top; - r.Left := x + 2; - r.Top := Max(0, (_h - TextHeight) div 2); - r.Right := Min(_w - 3, x + 2 + TextWidth); - r.Bottom := Min(_h - 4, r.Top + TextHeight); - TCanvas_DrawText(cnv, FCaption, r, [dtfCenter, dtfWordBreak]); - end; - end; + PrepareBmps; - procedure HandleTextOnly; - begin - {$IFDEF HAS_BITBTN_WORDWRAP} - if BitBtn.WordWrap then begin - HandleTextOnlyMultiLine; - end else - {$ENDIF}begin - HandleTextOnlySingleLine; - end; - end; + BitBtn.OnClick := HandleOnClick; - procedure HandleBmpAndSingleLineText; - var - TextSize: TSize; - RequiredWidth: Integer; - r: TRect; - x: Integer; - begin - TextSize := cnv.TextExtent(FCaption); - if BitBtn.Margin = -1 then begin - // center image and text on the button - RequiredWidth := FOrigBmp.Width + BitBtn.Spacing + TextSize.cx; - x := (_w - RequiredWidth) div 2; - cnv.Draw(x, (_h - FOrigBmp.Width) div 2, FOrigBmp); - r.Left := x + BitBtn.Margin + BitBtn.Spacing + FOrigBmp.Width; - r.Top := (_h - TextSize.cy) div 2; - r.Right := r.Left + TextSize.cx; - r.Bottom := r.Top + TextSize.cy; - TCanvas_DrawText(cnv, FCaption, r, [dtfLeft, dtfTopSingle, dtfSingleLine, dtfNoClip]); - end else begin - // left align image and text - cnv.Draw(BitBtn.Margin, (_h - FOrigBmp.Height) div 2, FOrigBmp); - r.Left := BitBtn.Margin + BitBtn.Spacing + FOrigBmp.Width; - r.Top := (_h - TextSize.cy) div 2; - r.Right := r.Left + TextSize.cx; - r.Bottom := r.Top + TextSize.cy; - TCanvas_DrawText(cnv, FCaption, r, [dtfLeft, dtfTopSingle, dtfSingleLine, dtfNoClip]); - end; - end; + FOrigMargin := BitBtn.Margin; + FOrigSpacing := BitBtn.Spacing; + BitBtn.Margin := -1; + BitBtn.Spacing := 0; - procedure HandleBmpAndMultilineText; - var - r: TRect; - TextWidth: Integer; - TextHeight: Integer; - RequiredWidth: Integer; - x: Integer; - begin - if BitBtn.Margin = -1 then begin - // center image and text on the button + UpdateGlyph; +end; - r := Rect(0, 0, _w - FOrigBmp.Width - 1 - BitBtn.Spacing, _h - 2); - TCanvas_DrawText(cnv, FCaption, r, [dtfCalcRect, dtfCenter, dtfWordBreak]); - TextWidth := r.Right - r.Left; - TextHeight := r.Bottom - r.Top; - RequiredWidth := FOrigBmp.Width + BitBtn.Spacing + TextWidth; - x := (_w - RequiredWidth) div 2; - cnv.Draw(x, (_h - FOrigBmp.Height) div 2, FOrigBmp); +destructor TdzSpeedBitBtn.Destroy; +begin + // If we get here, either the constructor failed (which automatically calls the destructor) + // or BitBtn was already destroyed, so we must not access it at all. + FUpBmp.Free; + FDownBmp.Free; + FOrigBmp.Free; + inherited; +end; - r.Left := x + FOrigBmp.Width + BitBtn.Spacing; - r.Top := (_h - TextHeight) div 2; - r.Right := r.Left + TextWidth; - r.Bottom := r.Top + TextHeight; - TCanvas_DrawText(cnv, FCaption, r, [dtfCenter, dtfWordBreak]); - end else begin - // left align image and text +procedure TdzSpeedBitBtn.PrepareBmps; +var + w: Integer; + h: Integer; + ColBack1: TColor; + ColBack2: TColor; +begin + w := BitBtn.ClientWidth; + h := BitBtn.ClientHeight; - r := Rect(0, 0, _w - BitBtn.Margin - FOrigBmp.Width - 1 - BitBtn.Spacing, _h - 2); - TCanvas_DrawText(cnv, FCaption, r, [dtfCalcRect, dtfCenter, dtfWordBreak]); - TextWidth := r.Right - r.Left; - TextHeight := r.Bottom - r.Top; + ColBack1 := RGB(240, 240, 240); // clBtnFace; + ColBack2 := RGB(245, 245, 245); // a bit lighter than clBtnFace; - cnv.Draw(BitBtn.Margin, (_h - FOrigBmp.Width) div 2, FOrigBmp); + PrepareBmp(w, h, ColBack1, EDGE_RAISED, FUpBmp); + PrepareBmp(w, h, ColBack2, EDGE_SUNKEN, FDownBmp); +end; - r.Left := BitBtn.Margin + FOrigBmp.Width + BitBtn.Spacing; - r.Top := (_h - TextWidth) div 2; - r.Right := r.Left + TextWidth; - r.Bottom := r.Top + TextHeight; - TCanvas_DrawText(cnv, FCaption, r, [dtfCenter, dtfWordBreak]); - end; +procedure TdzSpeedBitBtn.PrepareBmp(_w, _h: Integer; _Color: TColor; _Edge: UINT; out _bmp: TBitmap); +var + cnv: TCanvas; + + procedure HandleBmpOnly; + var + X: Integer; + Y: Integer; + begin + X := FOrigMargin; + Y := (_h - FOrigBmp.Height) div 2; + if X = -1 then begin + // center image in the button + X := (_w - FOrigBmp.Width) div 2; + end else begin + // left align image end; + cnv.Draw(X, Y, FOrigBmp); + end; - procedure HandleBmpAndText; - begin - // This is complicated. For now we will only support buttons with - // Layout=blGlyphLeft - {$IFDEF HAS_BITBTN_WORDWRAP} - if BitBtn.WordWrap then begin - HandleBmpAndMultilineText; - end else - {$ENDIF}begin - HandleBmpAndSingleLineText; - end; + procedure HandleTextOnlySingleLine; + var + X: Integer; + r: TRect; + HorizontalAlignment: TDrawTextHorizontalAlignment; + begin + X := FOrigMargin; + if X = -1 then begin + HorizontalAlignment := dthaCenter; + r := Rect(2, 0, _w - 3, _h); + end else begin + HorizontalAlignment := dthaLeft; + r := Rect(X + 2, 0, _w - 3, _h); end; + TCanvas_DrawTextSingleLine(cnv, FCaption, r, HorizontalAlignment, dtvaCenter, []); + end; + procedure HandleTextOnlyMultiLine; var + X: Integer; r: TRect; + TextWidth: Integer; + TextHeight: Integer; begin - _bmp := TBitmap.Create; - _bmp.Width := _w; - _bmp.Height := _h; - _bmp.TransparentColor := clFuchsia; + X := FOrigMargin; + if X = -1 then begin + // center + r := Rect(2, 0, _w - 3, _h - 4); + TCanvas_DrawText(cnv, FCaption, r, [dtfCalcRect, dtfCenter, dtfWordBreak]); + TextHeight := r.Bottom - r.Top; + r.Left := 2; + r.Top := Max(0, (_h - TextHeight) div 2); + r.Right := _w - 3; + r.Bottom := Min(_h - 4, r.Top + TextHeight); + TCanvas_DrawText(cnv, FCaption, r, [dtfCenter, dtfWordBreak]); + end else begin + // left align the centered text + // Yes, that doesn't make much sense, but TBitBtn works that way. + // Actually it's even worse: TBitBtn draws the text centered on the possible button width + // and then moves it to the right which clips the text if it is too wide. + // We don't make that mistake here but still center the text and then move it. + r := Rect(X + 2, 0, _w - 3, _h - 4); + TCanvas_DrawText(cnv, FCaption, r, [dtfCalcRect, dtfCenter, dtfWordBreak]); + TextWidth := r.Right - r.Left; + TextHeight := r.Bottom - r.Top; + r.Left := X + 2; + r.Top := Max(0, (_h - TextHeight) div 2); + r.Right := Min(_w - 3, X + 2 + TextWidth); + r.Bottom := Min(_h - 4, r.Top + TextHeight); + TCanvas_DrawText(cnv, FCaption, r, [dtfCenter, dtfWordBreak]); + end; + end; - cnv := _bmp.Canvas; + procedure HandleTextOnly; + begin +{$IFDEF HAS_BITBTN_WORDWRAP} + if BitBtn.WordWrap then begin + HandleTextOnlyMultiLine; + end else +{$ENDIF}begin + HandleTextOnlySingleLine; + end; + end; - cnv.Brush.Color := _Color; - cnv.Brush.Style := bsSolid; - cnv.FillRect(Rect(0, 0, _w, _h)); + procedure HandleBmpAndSingleLineText; + var + TextSize: TSize; + RequiredWidth: Integer; + r: TRect; + X: Integer; + begin + TextSize := cnv.TextExtent(FCaption); + if FOrigMargin = -1 then begin + // center image and text on the button + RequiredWidth := FOrigBmp.Width + FOrigSpacing + TextSize.cx; + X := (_w - RequiredWidth) div 2; + cnv.Draw(X, (_h - FOrigBmp.Width) div 2, FOrigBmp); + r.Left := X + FOrigMargin + FOrigSpacing + FOrigBmp.Width; + r.Top := (_h - TextSize.cy) div 2; + r.Right := r.Left + TextSize.cx; + r.Bottom := r.Top + TextSize.cy; + TCanvas_DrawText(cnv, FCaption, r, [dtfLeft, dtfTopSingle, dtfSingleLine, dtfNoClip]); + end else begin + // left align image and text + cnv.Draw(FOrigMargin, (_h - FOrigBmp.Height) div 2, FOrigBmp); + r.Left := FOrigMargin + FOrigSpacing + FOrigBmp.Width; + r.Top := (_h - TextSize.cy) div 2; + r.Right := r.Left + TextSize.cx; + r.Bottom := r.Top + TextSize.cy; + TCanvas_DrawText(cnv, FCaption, r, [dtfLeft, dtfTopSingle, dtfSingleLine, dtfNoClip]); + end; + end; - r := Rect(0, 0, _w - 1, _h - 2); - DrawEdge(cnv.Handle, r, _Edge, BF_RECT); + procedure HandleBmpAndMultilineText; + var + r: TRect; + TextWidth: Integer; + TextHeight: Integer; + RequiredWidth: Integer; + X: Integer; + begin + if FOrigMargin = -1 then begin + // center image and text on the button + r := Rect(0, 0, _w - FOrigBmp.Width - 1 - FOrigSpacing, _h - 2); + TCanvas_DrawText(cnv, FCaption, r, [dtfCalcRect, dtfCenter, dtfWordBreak]); + TextWidth := r.Right - r.Left; + TextHeight := r.Bottom - r.Top; + RequiredWidth := FOrigBmp.Width + FOrigSpacing + TextWidth; + X := (_w - RequiredWidth) div 2; + cnv.Draw(X, (_h - FOrigBmp.Height) div 2, FOrigBmp); - cnv.Brush.Style := bsClear; - cnv.Font := BitBtn.Font; + r.Left := X + FOrigBmp.Width + FOrigSpacing; + r.Top := (_h - TextHeight) div 2; + r.Right := r.Left + TextWidth; + r.Bottom := r.Top + TextHeight; + TCanvas_DrawText(cnv, FCaption, r, [dtfCenter, dtfWordBreak]); + end else begin + // left align image and text + r := Rect(0, 0, _w - FOrigMargin - FOrigBmp.Width - 1 - FOrigSpacing, _h - 2); + TCanvas_DrawText(cnv, FCaption, r, [dtfCalcRect, dtfCenter, dtfWordBreak]); + TextWidth := r.Right - r.Left; + TextHeight := r.Bottom - r.Top; - if FCaption <> '' then begin - if (FOrigBmp.Width <> 0) and (FOrigBmp.Height <> 0) then begin - HandleBmpAndText; - end else begin - // text only - HandleTextOnly; - end; - end else begin - HandleBmpOnly; + cnv.Draw(FOrigMargin, (_h - FOrigBmp.Width) div 2, FOrigBmp); + + r.Left := FOrigMargin + FOrigBmp.Width + FOrigSpacing; + r.Top := (_h - TextWidth) div 2; + r.Right := r.Left + TextWidth; + r.Bottom := r.Top + TextHeight; + TCanvas_DrawText(cnv, FCaption, r, [dtfCenter, dtfWordBreak]); end; end; + procedure HandleBmpAndText; + begin + // This is complicated. For now we will only support buttons with + // Layout=blGlyphLeft +{$IFDEF HAS_BITBTN_WORDWRAP} + if BitBtn.WordWrap then begin + HandleBmpAndMultilineText; + end else +{$ENDIF}begin + HandleBmpAndSingleLineText; + end; + end; + var - w: Integer; - h: Integer; - ColBack1: TColor; - ColBack2: TColor; + r: TRect; begin - inherited Create(_btn); - FOrigOnClick := BitBtn.OnClick; - FCaption := BitBtn.Caption; + _bmp.Width := _w; + _bmp.Height := _h; + _bmp.TransparentColor := clFuchsia; - FOrigBmp := TBitmap.Create; - FOrigBmp.Assign(BitBtn.Glyph); - FOrigBmp.Transparent := True; + cnv := _bmp.Canvas; - BitBtn.Caption := ''; + cnv.Brush.Color := _Color; + cnv.Brush.Style := bsSolid; + cnv.FillRect(Rect(0, 0, _w, _h)); - w := BitBtn.ClientWidth; - h := BitBtn.ClientHeight; + r := Rect(0, 0, _w - 1, _h - 2); + DrawEdge(cnv.Handle, r, _Edge, BF_RECT); - ColBack1 := rgb(240, 240, 240); // clBtnFace; - ColBack2 := rgb(245, 245, 245); // a bit lighter than clBtnFace; + cnv.Brush.Style := bsClear; + cnv.Font := BitBtn.Font; - PrepareBmp(w, h, ColBack1, EDGE_RAISED, FUpBmp); - PrepareBmp(w, h, ColBack2, EDGE_SUNKEN, FDownBmp); - - BitBtn.OnClick := HandleOnClick; - - BitBtn.Margin := -1; - BitBtn.Spacing := 0; - - UpdateGlyph; + if FCaption <> '' then begin + if (FOrigBmp.Width <> 0) and (FOrigBmp.Height <> 0) then begin + HandleBmpAndText; + end else begin + // text only + HandleTextOnly; + end; + end else begin + HandleBmpOnly; + end; end; -destructor TdzSpeedBitBtn.Destroy; -begin - // If we get here, either the constructor failed (which automatically calls the destructor) - // or BitBtn was already destroyed, so we must not access it at all. - FUpBmp.Free; - FDownBmp.Free; - FOrigBmp.Free; - inherited; -end; - procedure TdzSpeedBitBtn.doOnClick(_Sender: TObject); begin if Assigned(FOrigOnClick) then @@ -372,6 +383,20 @@ _Msg.Result := 1; end else inherited; + end else if (_Msg.Msg = CM_FONTCHANGED) +{$IF Declared(WM_DPICHANGED_AFTERPARENT)} + or (_Msg.Msg = WM_DPICHANGED_AFTERPARENT) +{$IFEND} + or (_Msg.Msg = WM_SIZE) then begin + FNeedsNewGlyphs := True; + inherited; + end else if _Msg.Msg = WM_PAINT then begin + if FNeedsNewGlyphs then begin + PrepareBmps; + UpdateGlyph; + FNeedsNewGlyphs := False; + end; + inherited; end else inherited; end; @@ -462,7 +487,7 @@ SetUp(i); end else SetDown(i); - break; //==> + Break; //==> end; end; doOnClick; Modified: trunk/ExternalSource/dzlib/u_dzStringArrayUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzStringArrayUtils.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzStringArrayUtils.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -27,6 +27,8 @@ function TStringArray_Contains(const _arr: TStringArray; const _s: string; out _Idx: Integer): Boolean; overload; function TStringArray_Contains(const _arr: TStringArray; const _s: string): Boolean; overload; +function TStringArray_AsCsv(const _arr: TStringArray; const _Separator: string = ','): string; + function TStringArray_FromStrings(_sl: TStrings): TStringArray; {$IFDEF SUPPORTS_INLINE}inline;{$ENDIF} @@ -168,6 +170,23 @@ Result := TStringArray_Contains(_arr, _s, Idx); end; +function TStringArray_AsCsv(const _arr: TStringArray; const _Separator: string = ','): string; +var + i: Integer; + len: Integer; +begin + len := Length(_arr); + case len of + 0: Result := ''; + 1: Result := _arr[0]; + else + Result := _arr[0]; + for i := 1 to len - 1 do begin + Result := Result + _Separator + _arr[i]; + end; + end; +end; + function TStringArray_Concat(const _Arr1, _Arr2: array of string): TStringArray; var Len1: Integer; Modified: trunk/ExternalSource/dzlib/u_dzStringUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzStringUtils.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzStringUtils.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -56,6 +56,12 @@ {$ENDIF SUPPORTS_UNICODE} ///<summary> +/// Cuts off the string at the first #0 and returns the new length </summary> +function StrTrimNul(var _s: AnsiString): Integer; +///<summary> use StrTrimNul </summary> +function StrTrimZero(var _s: AnsiString): integer; deprecated; // use StrTrimNul + +///<summary> /// Converts an array of byte to a string, interpreting the bytes as AnsiString </summary> function ByteArrayToString(const _buf: array of Byte): string; ///<summary> @@ -1523,6 +1529,25 @@ Result := string(s); end; +function StrTrimNul(var _s: AnsiString): Integer; +var + i: Integer; +begin + Result := Length(_s); + for i := 1 to Result do begin + if _s[i] = #0 then begin + Result := i - 1; + SetLength(_s, Result); + Exit; //==> + end; + end; +end; + +function StrTrimZero(var _s: AnsiString): Integer; +begin + Result := StrTrimNul(_s); +end; + function IsStringIn(const _s: string; const _Arr: array of string; out _Idx: Integer): Boolean; var i: Integer; Modified: trunk/ExternalSource/dzlib/u_dzTranslator.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzTranslator.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzTranslator.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -12,6 +12,9 @@ {$ENDIF} {$ENDIF} +// if defined, any code requiring VCL units is omited below, use this for WinAPI only programs +{.$define NoVCL} + interface uses @@ -75,7 +78,8 @@ implementation -{$IFNDEF console} +{$IFNDEF CONSOLE} +{$IFNDEF NoVCL} uses Windows, Controls, @@ -82,7 +86,8 @@ ActnList, Graphics, ExtCtrls; -{$ENDIF console} +{$ENDIF NoVCL} +{$ENDIF CONSOLE} function _(const _s: string): string; begin @@ -390,7 +395,8 @@ {$ENDIF} {$ENDIF} -{$IFNDEF console} +{$IFNDEF CONSOLE} +{$IFNDEF NoVCL} // ignore these VCL properties / classes TP_GlobalIgnoreClassProperty(TAction, 'Category'); TP_GlobalIgnoreClassProperty(TControl, 'ImeName'); @@ -397,7 +403,8 @@ TP_GlobalIgnoreClassProperty(TControl, 'HelpKeyword'); TP_TryGlobalIgnoreClass(TFont); TP_GlobalIgnoreClassProperty(TNotebook, 'Pages'); -{$ENDIF console} +{$ENDIF NoVCL} +{$ENDIF CONSOLE} // for more ignores, see u_dzTranslatorDB, u_dzTranslatorADO and other u_dzTranslatorXxx units {$IFDEF DXGETTEXTDEBUG} Modified: trunk/ExternalSource/dzlib/u_dzTypInfo.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzTypInfo.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzTypInfo.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -61,14 +61,17 @@ {$IFDEF SUPPORTS_EXTENDED} function GetFloatProperty(_Instance: TObject; const _Name: string; const _Default: Extended): Extended; overload; function GetFloatProperty(_Instance: TObject; const _Name: string): Extended; overload; +function TrySetFloatProperty(_Instance: TObject; const _Name: string; const _Value: Extended): Boolean; overload; {$ELSE} function GetFloatProperty(_Instance: TObject; const _Name: string; const _Default: Double): Double; overload; function GetFloatProperty(_Instance: TObject; const _Name: string): Double; overload; +function TrySetFloatProperty(_Instance: TObject; const _Name: string; const _Value: Double): Boolean; overload; {$ENDIF SUPPORTS_EXTENDED} function TryGetObjectProperty(_Instance: TObject; const _Name: string; out _Value: TObject): Boolean; function GetObjectProperty(_Instance: TObject; const _Name: string; _Default: TObject): TObject; overload; function GetObjectProperty(_Instance: TObject; const _Name: string): TObject; overload; +function TrySetObjectProperty(_Instance: TObject; const _Name: string; _Value: TObject): Boolean; function TryGetEventProperty(_Instance: TObject; const _Name: string; out _Value: TMethod): Boolean; function GetEventProperty(_Instance: TObject; const _Name: string; _Default: TMethod): TMethod; overload; @@ -156,6 +159,17 @@ if not TryGetFloatProperty(_Instance, _Name, Result) then raise EPropertyError.CreateFmt(_('Float property %s not found.'), [_Name]); end; + +function TrySetFloatProperty(_Instance: TObject; const _Name: string; const _Value: Extended): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind in FLOAT_PROPERTY_TYPES); + if Result then + SetPropValue(_Instance, PropInfo, _Value); +end; + {$ELSE} function GetFloatProperty(_Instance: TObject; const _Name: string; const _Default: Double): Double; begin @@ -168,6 +182,16 @@ if not TryGetFloatProperty(_Instance, _Name, Result) then raise EPropertyError.CreateFmt(_('Float property %s not found.'), [_Name]); end; + +function TrySetFloatProperty(_Instance: TObject; const _Name: string; const _Value: Double): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind in FLOAT_PROPERTY_TYPES); + if Result then + SetPropValue(_Instance, PropInfo, _Value); +end; {$ENDIF} function TryGetIntProperty(_Instance: TObject; const _Name: string; out _Value: Integer): Boolean; @@ -245,6 +269,17 @@ raise EPropertyError.CreateFmt(_('Object property %s not found.'), [_Name]); end; +function TrySetObjectProperty(_Instance: TObject; const _Name: string; _Value: TObject): Boolean; +var + PropInfo: PPropInfo; +begin + PropInfo := GetPropInfo(_Instance.ClassInfo, _Name); + Result := Assigned(PropInfo) and (PropInfo.PropType^.Kind = tkClass); + if Result then begin + SetObjectProp(_Instance, PropInfo, _Value); + end; +end; + function TryGetEventProperty(_Instance: TObject; const _Name: string; out _Value: TMethod): Boolean; var PropInfo: PPropInfo; Modified: trunk/ExternalSource/dzlib/u_dzTypes.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzTypes.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzTypes.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -171,6 +171,7 @@ TSingleArray = array of Single; TDoubleArray = array of Double; TExtendedArray = array of Extended; + TExtendedDynArray = TExtendedArray; {$IF not Declared(TBytes)} TBytes = array of Byte; {$IFEND} Modified: trunk/ExternalSource/dzlib/u_dzTypesUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzTypesUtils.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzTypesUtils.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -61,6 +61,14 @@ {$ENDIF} overload; +///<summary> +/// Quicksort for the Array between Lo and Hi </summary> +procedure TSingleDynArray_Sort(var _Arr: TSingleDynArray; _Lo, _Hi: Integer); + +///<summary> +/// Quicksort for the Array between Lo and Hi </summary> +procedure TDoubleDynArray_Sort(var _Arr: TDoubleDynArray; _Lo, _Hi: Integer); + implementation function TRect_Width(const _Rect: TRect): Integer; @@ -113,4 +121,62 @@ and (_Rect.Top <= _y) and (_Rect.Bottom >= _y); end; +procedure TSingleDynArray_Sort(var _Arr: TSingleDynArray; _Lo, _Hi: Integer); +var + Lo, Hi: Integer; + Pivot, t: Single; +begin + Lo := _Lo; + Hi := _Hi; + if Lo > Hi then + Exit; //==> + Pivot := _Arr[(Lo + Hi) div 2]; + repeat + while _Arr[Lo] < Pivot do + Inc(Lo); + while _Arr[Hi] > Pivot do + Dec(Hi); + if Lo <= Hi then begin + t := _Arr[Lo]; + _Arr[Lo] := _Arr[Hi]; + _Arr[Hi] := t; + Inc(Lo); + Dec(Hi); + end; + until Lo > Hi; + if Hi > _Lo then + TSingleDynArray_Sort(_Arr, _Lo, Hi); + if Lo < _Hi then + TSingleDynArray_Sort(_Arr, Lo, _Hi); +end; + +procedure TDoubleDynArray_Sort(var _Arr: TDoubleDynArray; _Lo, _Hi: Integer); +var + Lo, Hi: Integer; + Pivot, t: Single; +begin + Lo := _Lo; + Hi := _Hi; + if Lo > Hi then + Exit; //==> + Pivot := _Arr[(Lo + Hi) div 2]; + repeat + while _Arr[Lo] < Pivot do + Inc(Lo); + while _Arr[Hi] > Pivot do + Dec(Hi); + if Lo <= Hi then begin + t := _Arr[Lo]; + _Arr[Lo] := _Arr[Hi]; + _Arr[Hi] := t; + Inc(Lo); + Dec(Hi); + end; + until Lo > Hi; + if Hi > _Lo then + TDoubleDynArray_Sort(_Arr, _Lo, Hi); + if Lo < _Hi then + TDoubleDynArray_Sort(_Arr, Lo, _Hi); +end; + end. Modified: trunk/ExternalSource/dzlib/u_dzVclUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -1030,6 +1030,8 @@ /// @param IncludeDisabled determines whether the disabled items should also be returned if they are checked /// @returns the number of Items in Checked </summary> function TCheckListBox_GetChecked(_clb: TCheckListBox; _Checked: TStrings = nil; _IncludeDisabled: Boolean = False): Integer; overload; +/// todo: Why did I ever think it a good idea to return a string? A TStringArray would have been +/// a much better choice. function TCheckListBox_GetChecked(_clb: TCheckListBox; _IncludeDisabled: Boolean = False): string; overload; ///<summary> Returns the objects associated with the checked items /// @param clb is the TCheckListBox Modified: trunk/ExternalSource/dzlib/u_dzVersionInfo.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzVersionInfo.pas 2023-02-15 08:26:12 UTC (rev 3964) +++ trunk/ExternalSource/dzlib/u_dzVersionInfo.pas 2023-02-18 16:03:00 UTC (rev 3965) @@ -185,6 +185,11 @@ u_dzTranslator, u_dzOsUtils; +function _(const _s: string): string; {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF} +begin + Result := dzlibGetText(_s); +end; + { TCustomFileInfo } constructor TCustomFileInfo.Create; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tw...@us...> - 2023-08-03 12:58:48
|
Revision: 4046 http://sourceforge.net/p/gexperts/code/4046 Author: twm Date: 2023-08-03 12:58:46 +0000 (Thu, 03 Aug 2023) Log Message: ----------- updated to latest version from dzlib Modified Paths: -------------- trunk/ExternalSource/dzlib/dzlib.inc trunk/ExternalSource/dzlib/u_dzClassUtils.pas trunk/ExternalSource/dzlib/u_dzConvertUtils.pas trunk/ExternalSource/dzlib/u_dzFileUtils.pas trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas trunk/ExternalSource/dzlib/u_dzMiscUtils.pas trunk/ExternalSource/dzlib/u_dzStringUtils.pas trunk/ExternalSource/dzlib/u_dzVclUtils.pas Modified: trunk/ExternalSource/dzlib/dzlib.inc =================================================================== --- trunk/ExternalSource/dzlib/dzlib.inc 2023-07-17 14:35:43 UTC (rev 4045) +++ trunk/ExternalSource/dzlib/dzlib.inc 2023-08-03 12:58:46 UTC (rev 4046) @@ -75,6 +75,7 @@ // AHandle is declared as THandle (otherwise it's an Integer) {$DEFINE THANDLESTREAM_CREATE_HANDLE_IS_THANDLE} {$DEFINE MAXLISTSIZE_IS_DEPRECATED} +{$DEFINE TTHREAD_HAS_START} {$ENDIF} {$IFDEF DELPHIX_SEATTLE_UP} Modified: trunk/ExternalSource/dzlib/u_dzClassUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzClassUtils.pas 2023-07-17 14:35:43 UTC (rev 4045) +++ trunk/ExternalSource/dzlib/u_dzClassUtils.pas 2023-08-03 12:58:46 UTC (rev 4046) @@ -333,6 +333,9 @@ ///<summary> /// Reads a string from the ini-file, raises an exception if the value is empty </summary> function TIniFile_ReadString(_Ini: TCustomIniFile; const _Section, _Ident: string): string; overload; +///<summary> +/// Reads a string from the ini-file, raises an exception if the value is empty </summary> +function TIniFile_ReadString(const _Filename: string; const _Section, _Ident: string): string; overload; ///<summary> /// Writes a string to the ini-file. </summary> @@ -1275,6 +1278,18 @@ end; end; +function TIniFile_ReadString(const _Filename: string; const _Section, _Ident: string): string; +var + Ini: TMemIniFile; +begin + Ini := TMemIniFile.Create(_Filename); + try + Result := TIniFile_ReadString(Ini, _Section, _Ident); + finally + FreeAndNil(Ini); + end; +end; + procedure TIniFile_WriteString(const _Filename: string; const _Section, _Ident, _Value: string); var Ini: TMemIniFile; Modified: trunk/ExternalSource/dzlib/u_dzConvertUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzConvertUtils.pas 2023-07-17 14:35:43 UTC (rev 4045) +++ trunk/ExternalSource/dzlib/u_dzConvertUtils.pas 2023-08-03 12:58:46 UTC (rev 4046) @@ -37,7 +37,11 @@ EStringConvertError = class(EdzConvert); type - ULong = LongWord; +{$IFDEF DELPHI2005_UP} + ULong = LongWord deprecated; // use UInt32 +{$ELSE} + ULong = LongWord; // use UInt32 +{$ENDIF} type TBaseN = 2..36; @@ -68,36 +72,36 @@ ///<summary> /// Converts a decimal digit to its number equivalent /// @Raises EDigitOutOfRange if there is an invalid digit. </summary> -function DecDigit2Long(_a: Char): ULong; overload; +function DecDigit2Long(_a: Char): UInt32; overload; {$IFDEF unicode} -function DecDigit2Long(_a: AnsiChar): ULong; overload; +function DecDigit2Long(_a: AnsiChar): UInt32; overload; {$ENDIF} ///<summary> /// Converts a string representing a positive decimal number to a number /// @Raises EDigitOutOfRange if there is an invalid digit. </summary> -function Dec2Long(const _s: string): ULong; overload; +function Dec2Long(const _s: string): UInt32; overload; {$IFDEF unicode} -function Dec2Long(const _s: AnsiString): ULong; overload; +function Dec2Long(const _s: AnsiString): UInt32; overload; {$ENDIF} -function TryDec2Long(const _s: string; out _l: ULong): Boolean; overload; +function TryDec2Long(const _s: string; out _l: UInt32): Boolean; overload; {$IFDEF unicode} -function TryDec2Long(const _s: AnsiString; out _l: ULong): Boolean; overload; +function TryDec2Long(const _s: AnsiString; out _l: UInt32): Boolean; overload; {$ENDIF} ///<summary> /// Converts a positive number to its 2 digit decimal representation (left pads with '0') </summary> -function Long2Dec2(_l: ULong): string; +function Long2Dec2(_l: UInt32): string; ///<summary> /// Converts a positive number to its 4 digit decimal representation (left pads with '0') </summary> -function Long2Dec4(_l: ULong): string; +function Long2Dec4(_l: UInt32): string; ///<summary> /// Converts a positive number to its N digit decimal representation (left pads with '0') </summary> -function Long2DecN(_l: ULong; _n: ULong): string; +function Long2DecN(_l: UInt32; _n: UInt32): string; ///<summary> /// Converts a positive number to its decimal representation </summary> -function Long2Dec(_l: ULong): string; -function Long2DecA(_l: ULong): AnsiString; +function Long2Dec(_l: UInt32): string; +function Long2DecA(_l: UInt32): AnsiString; // Str <-> Hex conversion ///<summary> @@ -113,26 +117,26 @@ ///<summary> /// Converts a string representing a hexadecimal number to a number /// @Raises EDigitOutOfRange if there is an invalid digit. </summary> -function Hex2Long(const _s: string): ULong; +function Hex2Long(const _s: string): UInt32; ///<summary> /// Tries to interpret the string as the hexadecimal interpretation of a number and /// returns the value. /// @value is the converted value, only valid it result = true /// @returns true, if the string could be converted, false otherwise </summary> -function TryHex2Long(const _s: string; out _Value: ULong): Boolean; +function TryHex2Long(const _s: string; out _Value: UInt32): Boolean; ///<summary> /// Converts a number to its hexadecimal representation </summary> -function Long2Hex(_l: ULong): string; +function Long2Hex(_l: UInt32): string; ///<summary> /// converts a number to its hexadecimal representation left padding with 0 to a length of 2 </summary> -function Long2Hex2(_l: ULong): string; +function Long2Hex2(_l: UInt32): string; ///<summary> /// converts a number to its hexadecimal representation left padding with 0 to a length of 4 </summary> -function Long2Hex4(_l: ULong): string; +function Long2Hex4(_l: UInt32): string; ///<summary> /// converts a number to its hexadecimal representation left padding with 0 to a length of Digits </summary> -function Long2HexN(_l: ULong; _Digits: Byte): string; +function Long2HexN(_l: UInt32; _Digits: Byte): string; // Str <-> any numeric system conversion up to Base36 (that is digits 0..Z) ///<summary> @@ -148,24 +152,24 @@ ///<summary> /// Converts a Base digit to its number equivalent. /// @Raises EDigitOutOfRange if there is an invalid digit. </summary> -function Digit2Long(_a: Char; _Base: TBaseN): ULong; +function Digit2Long(_a: Char; _Base: TBaseN): UInt32; ///<summary> /// Converts a string representing a number in Base to a number. /// @Raises EDigitOutOfRange if there is an invalid digit. </summary> -function Num2Long(const _s: string; _Base: TBaseN): ULong; +function Num2Long(const _s: string; _Base: TBaseN): UInt32; ///<summary> /// Tries to convert a string representing a number in Base to a number. /// @Value contains the converted number, only valid if Result = true /// @returns true, if the conversion succeeds, false otherwise. </summary> -function TryNum2Long(const _s: string; _Base: TBaseN; out _Value: ULong): Boolean; overload; +function TryNum2Long(const _s: string; _Base: TBaseN; out _Value: UInt32): Boolean; overload; {$IFDEF unicode} -function TryNum2Long(const _s: AnsiString; _Base: TBaseN; out _Value: ULong): Boolean; overload; +function TryNum2Long(const _s: AnsiString; _Base: TBaseN; out _Value: UInt32): Boolean; overload; {$ENDIF} ///<summary> /// Converts a number to its Base representation. </summary> -function Long2Num(_l: ULong; _Base: Byte; _MinWidth: Integer = 1): string; +function Long2Num(_l: UInt32; _Base: Byte; _MinWidth: Integer = 1): string; ///<summary> /// Returns the number of characters in S that are valid digits in the given Base. </summary> function isNumberN(const _s: string; _Base: TBaseN): Integer; @@ -222,7 +226,10 @@ ///<summary> /// Does the same as TryStrToInt but does not change Value if the string cannot be converted. </summary> -function TryStr2Int(const _s: string; var _Value: Integer): Boolean; +function TryStr2Int(const _s: string; var _Value: Integer): Boolean; overload; +{$IFDEF SUPPORTS_UNICODE} +function TryStr2Int(const _s: AnsiString; var _Value: Integer): Boolean; overload; +{$ENDIF SUPPORTS_UNICODE} ///<summary> /// Converts a string to an int64. @@ -440,7 +447,56 @@ function Bool2Str(_b: Boolean): string; type + TBitNumber64 = 0..63; + TByteNumber64 = 0..7; + +{$IFDEF SUPPORTS_ENHANCED_RECORDS} +type + ///<summary> + /// Stores up to 64 bits similar to the Delphi TBits class but + /// as a record, so it does not need a destructor </summary> + TBits64 = record + public + type + TBitNumber = TBitNumber64; + TByteNumber = TByteNumber64; + TValue = UInt64; + const + Low = 0; + Bits = 64; + High = Bits - 1; + private + // unfortunately Delphi 2007 does not allow us to use TValue here + FValue: UInt64; + public + class function Create(_Value: TValue): TBits64; static; + class function AllSet: TBits64; static; + class function NoneSet: TBits64; static; + procedure Init(_Value: TValue); + function IsBitSet(_BitNo: TBitNumber): Boolean; + procedure SetBit(_BitNo: TBitNumber; _BitValue: Boolean); + ///<summary> + /// interpret the given bit range as an integer and return it </summary> + function Extract(_BitFirst, _BitLast: TBitNumber): TValue; + ///<summary> + /// Overwrite the given bit range with the given value (reverse of Extract) </summary> + procedure Overwrite(_BitFirst, _BitLast: TBitNumber; _Value: TValue); + function Value: TValue; + function GetByte(_ByteNo: TByteNumber): Byte; + procedure SetByte(_ByteNo: TByteNumber; _Value: Byte); + function AsString: string; + class operator BitwiseAnd(_a, _b: TBits64): TBits64; + class operator BitwiseOr(_a, _b: TBits64): TBits64; + class operator BitwiseXor(_a, _b: TBits64): TBits64; + // There is no BitwiseNot operator, but the LogicalNot also works + class operator LogicalNot(_a: TBits64): TBits64; + class operator Equal(_a, _b: TBits64): Boolean; + end; +{$ENDIF} + +type TBitNumber32 = 0..31; + TByteNumber32 = 0..3; {$IFDEF SUPPORTS_ENHANCED_RECORDS} type @@ -448,26 +504,47 @@ /// Stores up to 32 bits similar to the Delphi TBits class but /// as a record, so it does not need a destructor </summary> TBits32 = record + public + type + TBitNumber = TBitNumber32; + TByteNumber = TByteNumber32; + TValue = UInt32; + const + Low = 0; + Bits = 32; + High = Bits - 1; private - FValue: LongWord; + // unfortunately Delphi 2007 does not allow us to use TValue here + FValue: UInt32; public - class function Create(_Value: LongWord): TBits32; static; - procedure Init(_Value: LongWord); - function IsBitSet(_BitNo: TBitNumber32): Boolean; - procedure SetBit(_BitNo: TBitNumber32; _BitValue: Boolean); + class function Create(_Value: TValue): TBits32; static; + class function AllSet: TBits32; static; + class function NoneSet: TBits32; static; + procedure Init(_Value: TValue); + function IsBitSet(_BitNo: TBitNumber): Boolean; + procedure SetBit(_BitNo: TBitNumber; _BitValue: Boolean); ///<summary> /// interpret the given bit range as an integer and return it </summary> - function Extract(_BitFirst, _BitLast: TBitNumber32): LongWord; + function Extract(_BitFirst, _BitLast: TBitNumber): TValue; ///<summary> /// Overwrite the given bit range with the given value (reverse of Extract) </summary> - procedure Overwrite(_BitFirst, _BitLast: TBitNumber32; _Value: LongWord); - function Value: Cardinal; + procedure Overwrite(_BitFirst, _BitLast: TBitNumber; _Value: TValue); + function Value: TValue; + function GetByte(_ByteNo: TByteNumber): Byte; + procedure SetByte(_ByteNo: TByteNumber; _Value: Byte); function AsString: string; + class operator BitwiseAnd(_a, _b: TBits32): TBits32; + class operator BitwiseOr(_a, _b: TBits32): TBits32; + class operator BitwiseXor(_a, _b: TBits32): TBits32; + // There is no BitwiseNot operator, but the LogicalNot also works + class operator LogicalNot(_a: TBits32): TBits32; + class operator Equal(_a, _b: TBits32): Boolean; end; {$ENDIF} type TBitNumber16 = 0..15; + TByteNumber16 = 0..1; {$IFDEF SUPPORTS_ENHANCED_RECORDS} type @@ -475,21 +552,35 @@ /// Stores up to 16 bits similar to the Delphi TBits class but /// as a record, so it does not need a destructor </summary> TBits16 = record + public + type + TBitNumber = TBitNumber16; + TByteNumber = TByteNumber16; + TValue = UInt16; + const + Low = 0; + Bits = 16; + High = Bits - 1; private - FValue: Word; + // unfortunately Delphi 2007 does not allow us to use TValue here + FValue: UInt16; public - class function Create(_Value: Word): TBits16; static; - procedure Init(_Value: Word); - function IsBitSet(_BitNo: TBitNumber16): Boolean; + class function Create(_Value: TValue): TBits16; static; + class function AllSet: TBits16; static; + class function NoneSet: TBits16; static; + procedure Init(_Value: TValue); + function IsBitSet(_BitNo: TBitNumber): Boolean; function IsAnyBitSet: Boolean; - procedure SetBit(_BitNo: TBitNumber16; _BitValue: Boolean); + procedure SetBit(_BitNo: TBitNumber; _BitValue: Boolean); ///<summary> /// interpret the given bit range as an integer and return it </summary> - function Extract(_BitFirst, _BitLast: TBitNumber16): Word; + function Extract(_BitFirst, _BitLast: TBitNumber): TValue; ///<summary> /// Overwrite the given bit range with the given value (reverse of Extract) </summary> - procedure Overwrite(_BitFirst, _BitLast: TBitNumber16; _Value: Word); - function Value: Word; + procedure Overwrite(_BitFirst, _BitLast: TBitNumber; _Value: TValue); + function Value: TValue; + function GetByte(_ByteNo: TByteNumber): Byte; + procedure SetByte(_ByteNo: TByteNumber; _Value: Byte); function AsString: string; class operator BitwiseAnd(_a, _b: TBits16): TBits16; class operator BitwiseOr(_a, _b: TBits16): TBits16; @@ -496,11 +587,12 @@ class operator BitwiseXor(_a, _b: TBits16): TBits16; // There is no BitwiseNot operator, but the LogicalNot also works class operator LogicalNot(_a: TBits16): TBits16; + class operator Equal(_a, _b: TBits16): Boolean; end; {$ENDIF} type - TBitNumber8 = 0..8; + TBitNumber8 = 0..7; {$IFDEF SUPPORTS_ENHANCED_RECORDS} type ///<summary> @@ -507,15 +599,35 @@ /// Stores up to 8 bits similar to the Delphi TBits class but /// as a record, so it does not need a destructor </summary> TBits8 = record + public + type + TBitNumber = TBitNumber8; + TByteNumber = 0..0; + TValue = UInt8; + const + Low = 0; + Bits = 8; + High = Bits - 1; private - FValue: Byte; + // unfortunately Delphi 2007 does not allow us to use TValue here + FValue: UInt8; public - class function Create(_Value: Byte): TBits8; static; - procedure Init(_Value: Byte); - function IsBitSet(_BitNo: TBitNumber8): Boolean; + class function Create(_Value: TValue): TBits8; static; + class function AllSet: TBits8; static; + class function NoneSet: TBits8; static; + procedure Init(_Value: TValue); + function IsBitSet(_BitNo: TBitNumber): Boolean; function IsAnyBitSet: Boolean; - procedure SetBit(_BitNo: TBitNumber8; _BitValue: Boolean); - function Value: Byte; + procedure SetBit(_BitNo: TBitNumber; _BitValue: Boolean); + ///<summary> + /// interpret the given bit range as an integer and return it </summary> + function Extract(_BitFirst, _BitLast: TBitNumber): TValue; + ///<summary> + /// Overwrite the given bit range with the given value (reverse of Extract) </summary> + procedure Overwrite(_BitFirst, _BitLast: TBitNumber; _Value: TValue); + function Value: TValue; + function GetByte(_ByteNo: TByteNumber): Byte; + procedure SetByte(_ByteNo: TByteNumber; _Value: Byte); function AsString: string; // according to the documentation: // > For a logical operator and a bitwise operator using the same symbol, @@ -530,6 +642,7 @@ class operator BitwiseXor(_a, _b: TBits8): TBits8; // There is no BitwiseNot operator, but the LogicalNot also works class operator LogicalNot(_a: TBits8): TBits8; + class operator Equal(_a, _b: TBits8): Boolean; end; {$ENDIF} { TODO -otwm : @@ -596,7 +709,7 @@ Inc(Result); end; -function Digit2Long(_a: Char; _Base: TBaseN): ULong; +function Digit2Long(_a: Char; _Base: TBaseN): UInt32; begin Result := Pos(UpCase(_a), LeftStr(DIGIT_CHARS, _Base)); if Result = 0 then @@ -604,7 +717,7 @@ Dec(Result); end; -function Num2Long(const _s: string; _Base: TBaseN): ULong; +function Num2Long(const _s: string; _Base: TBaseN): UInt32; var i: Integer; begin @@ -611,12 +724,12 @@ Result := 0; for i := 1 to Length(_s) do if isDigit(_s[i], _Base) then - Result := (Result * _Base + ULong(Pos(UpCase(_s[i]), DIGIT_CHARS)) - 1) + Result := (Result * _Base + UInt32(Pos(UpCase(_s[i]), DIGIT_CHARS)) - 1) else raise EDigitOutOfRange.CreateFmt(_('Digit #%d (%s) out of range'), [i, _s[i]]); end; -function TryNum2Long(const _s: string; _Base: TBaseN; out _Value: ULong): Boolean; +function TryNum2Long(const _s: string; _Base: TBaseN; out _Value: UInt32): Boolean; var i: Integer; begin @@ -624,7 +737,7 @@ _Value := 0; for i := 1 to Length(_s) do begin if isDigit(_s[i], _Base) then - _Value := (_Value * _Base + ULong(Pos(UpCase(_s[i]), DIGIT_CHARS)) - 1) + _Value := (_Value * _Base + UInt32(Pos(UpCase(_s[i]), DIGIT_CHARS)) - 1) else begin Exit; end; @@ -633,7 +746,7 @@ end; {$IFDEF unicode} -function TryNum2Long(const _s: AnsiString; _Base: TBaseN; out _Value: ULong): Boolean; +function TryNum2Long(const _s: AnsiString; _Base: TBaseN; out _Value: UInt32): Boolean; var i: Integer; begin @@ -641,7 +754,7 @@ _Value := 0; for i := 1 to Length(_s) do begin if isDigit(_s[i], _Base) then - _Value := (_Value * _Base + ULong(Pos(string(UpCase(_s[i])), DIGIT_CHARS)) - 1) + _Value := (_Value * _Base + UInt32(Pos(string(UpCase(_s[i])), DIGIT_CHARS)) - 1) else begin Exit; end; @@ -650,7 +763,7 @@ end; {$ENDIF} -function Long2Num(_l: ULong; _Base: Byte; _MinWidth: Integer = 1): string; +function Long2Num(_l: UInt32; _Base: Byte; _MinWidth: Integer = 1): string; var m: Byte; begin @@ -753,28 +866,28 @@ Result := Digit2Long(_a, 16); end; -function Hex2Long(const _s: string): ULong; +function Hex2Long(const _s: string): UInt32; begin Result := Num2Long(_s, 16); end; -function TryHex2Long(const _s: string; out _Value: ULong): Boolean; +function TryHex2Long(const _s: string; out _Value: UInt32): Boolean; begin Result := TryNum2Long(_s, 16, _Value); end; -function Long2Hex(_l: ULong): string; +function Long2Hex(_l: UInt32): string; begin Result := Long2Num(_l, 16); end; -function Long2HexN(_l: ULong; _Digits: Byte): string; +function Long2HexN(_l: UInt32; _Digits: Byte): string; begin Result := Long2Hex(_l); Result := StringOfChar('0', _Digits - Length(Result)) + Result; end; -function Long2Hex2(_l: ULong): string; +function Long2Hex2(_l: UInt32): string; begin Result := Long2Hex(_l); if Length(Result) < 2 then @@ -781,7 +894,7 @@ Result := '0' + Result; end; -function Long2Hex4(_l: ULong): string; +function Long2Hex4(_l: UInt32): string; var Len: Integer; begin @@ -815,19 +928,19 @@ end; {$ENDIF} -function DecDigit2Long(_a: Char): ULong; +function DecDigit2Long(_a: Char): UInt32; begin Result := Digit2Long(_a, 10); end; {$IFDEF unicode} -function DecDigit2Long(_a: AnsiChar): ULong; +function DecDigit2Long(_a: AnsiChar): UInt32; begin Result := Digit2Long(Char(_a), 10); end; {$ENDIF} -function Dec2Long(const _s: string): ULong; +function Dec2Long(const _s: string): UInt32; var c: Char; i: Integer; @@ -840,7 +953,7 @@ end; {$IFDEF unicode} -function Dec2Long(const _s: AnsiString): ULong; overload; +function Dec2Long(const _s: AnsiString): UInt32; overload; var c: AnsiChar; i: Integer; @@ -853,19 +966,19 @@ end; {$ENDIF} -function TryDec2Long(const _s: string; out _l: ULong): Boolean; +function TryDec2Long(const _s: string; out _l: UInt32): Boolean; begin Result := TryNum2Long(_s, 10, _l); end; {$IFDEF unicode} -function TryDec2Long(const _s: AnsiString; out _l: ULong): Boolean; +function TryDec2Long(const _s: AnsiString; out _l: UInt32): Boolean; begin Result := TryNum2Long(_s, 10, _l); end; {$ENDIF} -function Long2Dec(_l: ULong): string; +function Long2Dec(_l: UInt32): string; var s: AnsiString; begin @@ -873,26 +986,26 @@ Result := string(s); end; -function Long2DecA(_l: ULong): AnsiString; +function Long2DecA(_l: UInt32): AnsiString; begin Str(_l, Result); end; -function Long2Dec2(_l: ULong): string; +function Long2Dec2(_l: UInt32): string; begin Result := Long2DecN(_l, 2); end; -function Long2Dec4(_l: ULong): string; +function Long2Dec4(_l: UInt32): string; begin Result := Long2DecN(_l, 4); end; -function Long2DecN(_l: ULong; _n: ULong): string; +function Long2DecN(_l: UInt32; _n: UInt32): string; begin Result := Long2Dec(_l); - if ULong(Length(Result)) < _n then - Insert(DupeString('0', _n - ULong(Length(Result))), Result, 1); + if UInt32(Length(Result)) < _n then + Insert(DupeString('0', _n - UInt32(Length(Result))), Result, 1); end; function TimeToSeconds(_Zeit: TDateTime): Integer; @@ -1046,6 +1159,13 @@ _Value := v; end; +{$IFDEF SUPPORTS_UNICODE} +function TryStr2Int(const _s: AnsiString; var _Value: Integer): Boolean; +begin + Result := TryStr2Int(string(_s), _Value); +end; +{$ENDIF SUPPORTS_UNICODE} + function Str2Int64(const _s: string; _Default: Int64): Int64; var e: Integer; @@ -1274,26 +1394,169 @@ end; {$IFDEF SUPPORTS_ENHANCED_RECORDS} + +{ TBits64 } + +class function TBits64.Create(_Value: TValue): TBits64; +begin + Result.Init(_Value); +end; + +class function TBits64.AllSet: TBits64; +begin + Result.Init($FFFFFFFFFFFFFFFF); +end; + +class function TBits64.NoneSet: TBits64; +begin + Result.Init(0); +end; + +procedure TBits64.Init(_Value: TValue); +begin + FValue := _Value; +end; + +type + TLoHi64 = packed record + Lo: UInt32; + Hi: UInt32; + end; + +function TBits64.IsBitSet(_BitNo: TBitNumber): Boolean; +var + LoHi: TLoHi64 absolute FValue; +begin + // shl only supports 32 bits + if _BitNo > 31 then begin + Result := ((LoHi.Hi and (1 shl (_BitNo - 32))) <> 0); + end else begin + Result := ((LoHi.Lo and (1 shl _BitNo)) <> 0); + end; +end; + +procedure TBits64.SetBit(_BitNo: TBitNumber; _BitValue: Boolean); +var + LoHi: TLoHi64 absolute FValue; +begin + // shl only supports 32 bits + if _BitNo > 31 then begin + if _BitValue then + LoHi.Hi := LoHi.Hi or (1 shl (_BitNo - 32)) + else + LoHi.Hi := LoHi.Hi and not (1 shl (_BitNo - 32)); + end else begin + if _BitValue then + LoHi.Lo := LoHi.Lo or (1 shl _BitNo) + else + LoHi.Lo := LoHi.Lo and not (1 shl _BitNo); + end; +end; + +function TBits64.Extract(_BitFirst, _BitLast: TBitNumber): TValue; +var + i: TBitNumber; +begin + Result := 0; + for i := _BitLast downto _BitFirst do begin + Result := Result shl 1; + if IsBitSet(i) then + Result := Result + 1; + end; +end; + +procedure TBits64.Overwrite(_BitFirst, _BitLast: TBitNumber; _Value: TValue); +var + i: TBitNumber; +begin + for i := _BitFirst to _BitLast do begin + SetBit(i, (_Value and TValue(1)) <> 0); + _Value := _Value shr 1; + end; +end; + +function TBits64.Value: TValue; +begin + Result := FValue; +end; + +type + TByteArr8 = array[TByteNumber64] of Byte; + +function TBits64.GetByte(_ByteNo: TByteNumber): Byte; +var + Bytes: TByteArr8 absolute FValue; +begin + Result := Bytes[_byteNo]; +end; + +procedure TBits64.SetByte(_ByteNo: TByteNumber; _Value: Byte); +var + Bytes: TByteArr8 absolute FValue; +begin + Bytes[_ByteNo] := _Value; +end; + +function TBits64.AsString: string; +var + i: Integer; +begin + Result := DupeString('0', Bits); + for i := High downto Low do + if IsBitSet(i) then + Result[Bits - i] := '1'; +end; + +class operator TBits64.BitwiseAnd(_a, _b: TBits64): TBits64; +begin + Result.Init(_a.Value and _b.Value); +end; + +class operator TBits64.LogicalNot(_a: TBits64): TBits64; +begin + Result.Init(_a.Value xor $FF); +end; + +class operator TBits64.BitwiseOr(_a, _b: TBits64): TBits64; +begin + Result.Init(_a.Value or _b.Value); +end; + +class operator TBits64.BitwiseXor(_a, _b: TBits64): TBits64; +begin + Result.Init(_a.Value xor _b.Value); +end; + +class operator TBits64.Equal(_a, _b: TBits64): Boolean; +begin + Result := _a.Value = _b.Value; +end; + { TBits32 } +class function TBits32.AllSet: TBits32; +begin + Result.Init($FFFFFFFF); +end; + function TBits32.AsString: string; var i: Integer; begin - Result := DupeString('0', 32); - for i := 31 downto 0 do + Result := DupeString('0', Bits); + for i := High downto Low do if IsBitSet(i) then - Result[32 - i] := '1'; + Result[Bits - i] := '1'; end; -class function TBits32.Create(_Value: LongWord): TBits32; +class function TBits32.Create(_Value: TValue): TBits32; begin Result.Init(_Value); end; -function TBits32.Extract(_BitFirst, _BitLast: TBitNumber32): LongWord; +function TBits32.Extract(_BitFirst, _BitLast: TBitNumber): TValue; var - i: TBitNumber32; + i: TBitNumber; begin Result := 0; for i := _BitLast downto _BitFirst do begin @@ -1303,9 +1566,14 @@ end; end; -procedure TBits32.Overwrite(_BitFirst, _BitLast: TBitNumber32; _Value: LongWord); +class function TBits32.NoneSet: TBits32; +begin + Result.Init(0); +end; + +procedure TBits32.Overwrite(_BitFirst, _BitLast: TBitNumber; _Value: TValue); var - i: TBitNumber32; + i: TBitNumber; begin for i := _BitFirst to _BitLast do begin SetBit(i, (_Value and $00000001) <> 0); @@ -1313,17 +1581,28 @@ end; end; -procedure TBits32.Init(_Value: LongWord); +function TBits32.GetByte(_ByteNo: TByteNumber): Byte; begin + Result := (FValue shr (_ByteNo * 8)) and $FF; +end; + +procedure TBits32.SetByte(_ByteNo: TByteNumber; _Value: Byte); +begin + _ByteNo := _ByteNo * 8; + FValue := FValue and ($FFFFFFFF xor ($FF shl _ByteNo)) or (_Value shl _ByteNo); +end; + +procedure TBits32.Init(_Value: TValue); +begin FValue := _Value; end; -function TBits32.IsBitSet(_BitNo: TBitNumber32): Boolean; +function TBits32.IsBitSet(_BitNo: TBitNumber): Boolean; begin Result := ((FValue and (1 shl _BitNo)) <> 0); end; -procedure TBits32.SetBit(_BitNo: TBitNumber32; _BitValue: Boolean); +procedure TBits32.SetBit(_BitNo: TBitNumber; _BitValue: Boolean); begin if _BitValue then FValue := FValue or (1 shl _BitNo) @@ -1331,29 +1610,59 @@ FValue := FValue and not (1 shl _BitNo); end; -function TBits32.Value: LongWord; +function TBits32.Value: TValue; begin Result := FValue; end; +class operator TBits32.BitwiseAnd(_a, _b: TBits32): TBits32; +begin + Result.Init(_a.Value and _b.Value); +end; + +class operator TBits32.LogicalNot(_a: TBits32): TBits32; +begin + Result.Init(_a.Value xor $FF); +end; + +class operator TBits32.BitwiseOr(_a, _b: TBits32): TBits32; +begin + Result.Init(_a.Value or _b.Value); +end; + +class operator TBits32.BitwiseXor(_a, _b: TBits32): TBits32; +begin + Result.Init(_a.Value xor _b.Value); +end; + +class operator TBits32.Equal(_a, _b: TBits32): Boolean; +begin + Result := _a.Value = _b.Value; +end; + { TBits16 } +class function TBits16.AllSet: TBits16; +begin + Result.Init($FFFF); +end; + function TBits16.AsString: string; var i: Integer; begin - Result := DupeString('0', 8); - for i := 7 downto 0 do + Result := DupeString('0', Bits); + for i := High downto Low do if IsBitSet(i) then - Result[8 - i] := '1'; + Result[Bits - i] := '1'; end; -class function TBits16.Create(_Value: Word): TBits16; +class function TBits16.Create(_Value: TValue): TBits16; begin Result.Init(_Value); end; -procedure TBits16.Init(_Value: Word); +procedure TBits16.Init(_Value: TValue); begin FValue := _Value; end; @@ -1363,7 +1672,7 @@ Result := FValue <> 0; end; -function TBits16.IsBitSet(_BitNo: TBitNumber16): Boolean; +function TBits16.IsBitSet(_BitNo: TBitNumber): Boolean; begin Result := ((FValue and (1 shl _BitNo)) <> 0); end; @@ -1388,9 +1697,9 @@ Result.Init(_a.Value xor _b.Value); end; -function TBits16.Extract(_BitFirst, _BitLast: TBitNumber16): Word; +function TBits16.Extract(_BitFirst, _BitLast: TBitNumber): TValue; var - i: TBitNumber16; + i: TBitNumber; begin Result := 0; for i := _BitLast downto _BitFirst do begin @@ -1400,17 +1709,22 @@ end; end; -procedure TBits16.Overwrite(_BitFirst, _BitLast: TBitNumber16; _Value: Word); +class function TBits16.NoneSet: TBits16; +begin + Result.Init(0); +end; + +procedure TBits16.Overwrite(_BitFirst, _BitLast: TBitNumber; _Value: TValue); var - i: TBitNumber16; + i: TBitNumber; begin for i := _BitFirst to _BitLast do begin - SetBit(i, (_Value and $00000001) <> 0); + SetBit(i, (_Value and TValue(1)) <> 0); _Value := _Value shr 1; end; end; -procedure TBits16.SetBit(_BitNo: TBitNumber16; _BitValue: Boolean); +procedure TBits16.SetBit(_BitNo: TBitNumber; _BitValue: Boolean); begin if _BitValue then FValue := FValue or (1 shl _BitNo) @@ -1418,11 +1732,27 @@ FValue := FValue and not (1 shl _BitNo); end; -function TBits16.Value: Word; +function TBits16.Value: TValue; begin Result := FValue; end; +function TBits16.GetByte(_ByteNo: TByteNumber): Byte; +begin + Result := (FValue shr (_ByteNo * 8)) and $FF; +end; + +procedure TBits16.SetByte(_ByteNo: TByteNumber; _Value: Byte); +begin + _ByteNo := _ByteNo * 8; + FValue := FValue and ($FFFF xor ($FF shl _ByteNo)) or (_Value shl _ByteNo); +end; + +class operator TBits16.Equal(_a, _b: TBits16): Boolean; +begin + Result := _a.Value = _b.Value; +end; + { TBits8 } function TBits8.AsString: string; @@ -1429,28 +1759,43 @@ var i: Integer; begin - Result := DupeString('0', 8); - for i := 7 downto 0 do + Result := DupeString('0', Bits); + for i := High downto Low do if IsBitSet(i) then - Result[8 - i] := '1'; + Result[Bits - i] := '1'; end; -class function TBits8.Create(_Value: Byte): TBits8; +class function TBits8.AllSet: TBits8; begin + Result.Init($FF); +end; + +class function TBits8.Create(_Value: TValue): TBits8; +begin Result.Init(_Value); end; -procedure TBits8.Init(_Value: Byte); +function TBits8.GetByte(_ByteNo: TByteNumber): Byte; begin + Result := FValue; +end; + +procedure TBits8.SetByte(_ByteNo: TByteNumber; _Value: Byte); +begin FValue := _Value; end; +procedure TBits8.Init(_Value: TValue); +begin + FValue := _Value; +end; + function TBits8.IsAnyBitSet: Boolean; begin Result := FValue <> 0; end; -function TBits8.IsBitSet(_BitNo: TBitNumber8): Boolean; +function TBits8.IsBitSet(_BitNo: TBitNumber): Boolean; begin Result := ((FValue and (1 shl _BitNo)) <> 0); end; @@ -1475,8 +1820,13 @@ Result.Init(_a.Value xor _b.Value); end; -procedure TBits8.SetBit(_BitNo: TBitNumber8; _BitValue: Boolean); +class function TBits8.NoneSet: TBits8; begin + Result.Init(0); +end; + +procedure TBits8.SetBit(_BitNo: TBitNumber; _BitValue: Boolean); +begin if _BitValue then FValue := FValue or (1 shl _BitNo) else @@ -1483,10 +1833,38 @@ FValue := FValue and not (1 shl _BitNo); end; -function TBits8.Value: Byte; +function TBits8.Extract(_BitFirst, _BitLast: TBitNumber): TValue; +var + i: Integer; begin + Result := 0; + for i := _BitLast downto _BitFirst do begin + Result := Result shl 1; + if IsBitSet(i) then + Result := Result + 1; + end; +end; + +procedure TBits8.Overwrite(_BitFirst, _BitLast: TBitNumber; _Value: TValue); +var + i: TBitNumber; +begin + for i := _BitFirst to _BitLast do begin + SetBit(i, (_Value and TValue(1)) <> 0); + _Value := _Value shr 1; + end; +end; + +function TBits8.Value: TValue; +begin Result := FValue; end; + +class operator TBits8.Equal(_a, _b: TBits8): Boolean; +begin + Result := _a.Value = _b.Value; +end; + {$ENDIF} function Bool2Str(_b: Boolean): string; Modified: trunk/ExternalSource/dzlib/u_dzFileUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzFileUtils.pas 2023-07-17 14:35:43 UTC (rev 4045) +++ trunk/ExternalSource/dzlib/u_dzFileUtils.pas 2023-08-03 12:58:46 UTC (rev 4046) @@ -1072,8 +1072,8 @@ /// Note that this treats only the text after the last '.' as extension(s). </summary> function LastExtension: string; ///<summary> - /// Returns the filename without extension. - /// Note that this treats everything after the first '.' as extension(s) </summary> + /// @Returns the filename including the full path but without extension(s). + /// @NOTE: This treats everything after the first '.' as extension(s) </summary> function BaseName: string; ///<summary> /// replaces the drive part of the path with the given NewDrive. </summary> @@ -1133,6 +1133,14 @@ /// Splits all parts of the file name in a TStringArray /// @returns the number of parts </summary> function Split: TStringArray; + ///<summary> + /// @returns True, if the last extension matches the given one (case insensitively) + /// Fales otherwise </summary> + function HasExtensionLast(const _Ext: string): Boolean; + ///<summary> + /// @returns True, if the full extension matches the given one (case insensitively) + /// Fales otherwise </summary> + function HasExtensionFull(const _Ext: string): Boolean; class function Combine(_Parts: TStringArray): TFilename; static; ///<summary> /// Same as Init </summary> @@ -2706,7 +2714,7 @@ try repeat if (Sr.Name = '.') or (Sr.Name = '..') then begin - // ignore + // ignore end else begin Filename := IncludeTrailingPathDelimiter(_DirName) + Sr.Name; if (Sr.Attr and SysUtils.faDirectory) <> 0 then begin @@ -3556,6 +3564,16 @@ Result := Length(Split); end; +function TFilename.HasExtensionFull(const _Ext: string): Boolean; +begin + Result := TFileSystem.HasFileExtFull(FFull, _Ext); +end; + +function TFilename.HasExtensionLast(const _Ext: string): Boolean; +begin + Result := TFileSystem.HasFileExtLast(FFull, _Ext); +end; + function TFilename.Parts(_Depth: Integer): string; var sa: TStringArray; Modified: trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2023-07-17 14:35:43 UTC (rev 4045) +++ trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2023-08-03 12:58:46 UTC (rev 4046) @@ -100,7 +100,8 @@ Red: Byte; {$IFDEF SUPPORTS_ENHANCED_RECORDS} function GetValues(_Idx: TValueIdxTriple): Byte; inline; - procedure SetValues(_Idx: TValueIdxTriple; _Value: Byte); inline; + procedure SetValues(_Idx: TValueIdxTriple; _Value: Byte); overload; inline; + procedure SetValues(_Red, _Green, _Blue: Byte); overload; function GetColor: TColor; ///<summary> /// Sets Blue, Green and Red for the given Color, supporting system colors in addition to RGB colors @@ -498,10 +499,34 @@ procedure TBitmap_AssignMono824(_Buffer: PByte; _bmp: TBitmap; _YIsReversed: Boolean); ///<summary> -/// Assign a buffer containg a bitmap in Mono 8 format to a 8 bit gray scale TBitmap </summary> -procedure TBitmap_AssignMono8(_Buffer: PByte; _bmp: TBitmap; _YIsReversed: Boolean); +/// Assign a buffer containing a bitmap in Mono 8 format to a 8 bit gray scale TBitmap </summary> +procedure TBitmap_AssignMono8(_Buffer: PByte; _bmp: TBitmap; _YIsReversed: Boolean); overload; +procedure TBitmap_AssignMono8(_Buffer: PByte; _bmp: TBitmap; _YIsReversed: Boolean; _RowStride: Int64); overload; +type + ///<summary> + /// Converts the value at the given position to a Byte and increments BufPtr to point to the + /// next value </summary> + TBufferBitsToMono8Func = function(var _BufPtr: Pointer): Byte; + TBufferBitsToMono8Meth = function(var _BufPtr: Pointer): Byte of object; + ///<summary> +/// Converts a 12 bit value at the given position to a Byte and increments BufPtr by 2 </summary> +function BufferBits12ToMono8(var _BufPtr: Pointer): Byte; + +///<summary> +/// Assign a buffer containing a bitmap in Monochrome format to a 8 bit gray scale TBitmap +/// @param BufferBitsToMono8Func is a callback function that converts the value at a given +/// position to a Byte and increments the position to point to +/// the next value. +/// @param RowStride (optional) is the number of bytes in Buffer for one row. If 0 it is assumed +/// that BufferBitsToMono8 will increment Buffer correctly </summary> +procedure TBitmap_AssignToMono8(_BufferBitsToMono8Func: TBufferBitsToMono8Func; + _Buffer: Pointer; _bmp: TBitmap; _YIsReversed: Boolean; _RowStride: Int64 = 0); overload; +procedure TBitmap_AssignToMono8(_BufferBitsToMono8Meth: TBufferBitsToMono8Meth; + _Buffer: Pointer; _bmp: TBitmap; _YIsReversed: Boolean; _RowStride: Int64 = 0); overload; + +///<summary> /// converts a pf24bit or pf32bit monochrome bitmap to a pf8bit monochrome bitmap </summary> function TBitmap_MonoToMono8(_bmp: TBitmap): TBitmap; overload; {$IFDEF SUPPORTS_INLINE} @@ -795,7 +820,16 @@ {$IFDEF SUPPORTS_INLINE} inline; {$ENDIF} + +{$IFDEF SUPPORTS_ENHANCED_RECORDS} ///<summary> +/// @param Hue is a value between 0 and 1 </summary> +procedure RainbowColor(_Hue: Double; out _Color: TdzRgbTriple); overload; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} +{$ENDIF} +///<summary> /// @param Brightness is a grayscale value </summary> function RainbowColor(_Brightness: Byte): TColor; overload; {$IFDEF SUPPORTS_INLINE} @@ -1429,6 +1463,13 @@ TdzRgbTripleValues(Self)[_Idx] := _Value; end; +procedure TdzRgbTriple.SetValues(_Red, _Green, _Blue: Byte); +begin + Red := _Red; + Green := _Green; + Blue := _Blue; +end; + procedure TdzRgbTriple.SetBrightness(_Value: Byte); begin Red := _Value; @@ -1916,26 +1957,121 @@ procedure TBitmap_AssignMono8(_Buffer: PByte; _bmp: TBitmap; _YIsReversed: Boolean); var + w: Integer; +begin + Assert(AssertPixelFormat(_bmp, pf8bit)); + w := _bmp.Width; + TBitmap_AssignMono8(_Buffer, _bmp, _YIsReversed, w); +end; + +procedure TBitmap_AssignMono8(_Buffer: PByte; _bmp: TBitmap; _YIsReversed: Boolean; _RowStride: Int64); +var + w: Integer; + h: Integer; y: Integer; ScanLine: PByte; begin Assert(AssertPixelFormat(_bmp, pf8bit)); + w := _bmp.Width; + h := _bmp.Height; + Assert(_RowStride >= w); + // Unfortunately the y coordinates of TBitmap are reversed (the picture is upside down). // So we can only copy the whole picture in one go, if the buffer is also upside down // (many cameras have this feature). If not, we have to copy it one line at a time. - if _YIsReversed then begin - ScanLine := _bmp.ScanLine[_bmp.Height - 1]; - Move(_Buffer^, ScanLine^, _bmp.Height * _bmp.Width); + if _YIsReversed and (_RowStride = w) then begin + ScanLine := _bmp.ScanLine[h - 1]; + Move(_Buffer^, ScanLine^, h * w); end else begin - for y := 0 to _bmp.Height - 1 do begin + for y := 0 to h - 1 do begin ScanLine := _bmp.ScanLine[y]; - Move(_Buffer^, ScanLine^, _bmp.Width); - Inc(_Buffer, _bmp.Width); + Move(_Buffer^, ScanLine^, w); + Inc(_Buffer, _RowStride); end; end; end; +function BufferBits12ToMono8(var _BufPtr: Pointer): Byte; +begin + Result := MulDiv(PUInt16(_BufPtr)^, 255, 1 shl 12 - 1); + IncPtr(_BufPtr, 2); +end; + +procedure TBitmap_AssignToMono8(_BufferBitsToMono8Func: TBufferBitsToMono8Func; + _Buffer: Pointer; _bmp: TBitmap; _YIsReversed: Boolean; _RowStride: Int64); overload; +var + y: Integer; + x: Integer; + w: Integer; + h: Integer; + ScanLine: PByte; + Buf: Pointer; +begin + Assert(AssertPixelFormat(_bmp, pf8bit)); + + w := _bmp.Width; + h := _bmp.Height; + + Assert((_RowStride = 0) or (_RowStride >= w)); + + for y := 0 to _bmp.Height - 1 do begin + if _YIsReversed then begin + ScanLine := _bmp.ScanLine[h - 1]; + end else begin + ScanLine := _bmp.ScanLine[y]; + end; + Buf := _Buffer; + for x := 0 to w - 1 do begin + ScanLine^ := _BufferBitsToMono8Func(Buf); + Inc(ScanLine); + end; + if _RowStride > 0 then begin + IncPtr(_Buffer, _RowStride); + end else begin + // we assume that BufferBitsToMono8Func inrements the buffer correctly + _Buffer := Buf; + end; + end; +end; + +procedure TBitmap_AssignToMono8(_BufferBitsToMono8Meth: TBufferBitsToMono8Meth; + _Buffer: Pointer; _bmp: TBitmap; _YIsReversed: Boolean; _RowStride: Int64 = 0); overload; +var + y: Integer; + x: Integer; + w: Integer; + h: Integer; + ScanLine: PByte; + Buf: Pointer; +begin + Assert(AssertPixelFormat(_bmp, pf8bit)); + + w := _bmp.Width; + h := _bmp.Height; + + Assert((_RowStride = 0) or (_RowStride >= w)); + + for y := 0 to _bmp.Height - 1 do begin + if _YIsReversed then begin + ScanLine := _bmp.ScanLine[h - 1]; + end else begin + ScanLine := _bmp.ScanLine[y]; + end; + Buf := _Buffer; + for x := 0 to w - 1 do begin + ScanLine^ := _BufferBitsToMono8Meth(Buf); + Inc(ScanLine); + end; + if _RowStride > 0 then begin + IncPtr(_Buffer, _RowStride); + end else begin + // we assume that _BufferBitsToMono8Meth inrements the buffer correctly + _Buffer := Buf; + end; + end; +end; + type PByteArray = SysUtils.PByteArray; TCopyScanline = procedure(_Width: Integer; _SrcLine: Pointer; _DestLine: Pointer); @@ -3896,6 +4032,26 @@ end; end; +{$IFDEF SUPPORTS_ENHANCED_RECORDS} +procedure RainbowColor(_Hue: Double; out _Color: TdzRgbTriple); +var + Value: Double; + IntValue: Integer; +begin + Value := EnsureRange(_Hue, 0, 1) * 6; + IntValue := Round(Frac(Value) * 255); + case Trunc(Value) of + 0: _Color.SetValues(255, IntValue, 0); + 1: _Color.SetValues(255 - IntValue, 255, 0); + 2: _Color.SetValues(0, 255, IntValue); + 3: _Color.SetValues(0, 255 - IntValue, 255); + 4: _Color.SetValues(IntValue, 0, 255); + else // 5 + _Color.SetValues(255, 0, 255 - IntValue); + end; +end; +{$ENDIF} + procedure RainbowColor(_Brightness: Byte; out _Red, _Green, _Blue: Byte); var Brightness: Integer; @@ -4250,4 +4406,7 @@ end; end. +// Here, Delphi 2007 sometimes throws a [DCC Error] F2084 Internal Error: AV06FA6FD9-R00000D1A-0 +// Usually it helps to do a full rebuild or delete the DCU output directory contents +// In one case the problem went away when I changed the order of units in the project file Modified: trunk/ExternalSource/dzlib/u_dzMiscUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzMiscUtils.pas 2023-07-17 14:35:43 UTC (rev 4045) +++ trunk/ExternalSource/dzlib/u_dzMiscUtils.pas 2023-08-03 12:58:46 UTC (rev 4046) @@ -74,7 +74,10 @@ function HexDumpString(const _s: AnsiString): string; ///<summary> converts a hexdump of a double back to a double value </summary> -procedure HexDumpToDbl(const _s: string; var _Value: Double); +procedure HexDumpToDbl(const _s: string; var _Value: Double); overload; +{$IFDEF SUPPORTS_UNICODE} +procedure HexDumpToDbl(const _s: AnsiString; var _Value: Double); overload; +{$ENDIF SUPPORTS_UNICODE} ///<summary> converts a hexdump of an extended back to an extended value </summary> procedure HexDumpToExtended(const _s: string; var _Value: Extended); @@ -497,6 +500,13 @@ end; end; +{$IFDEF SUPPORTS_UNICODE} +procedure HexDumpToDbl(const _s: AnsiString; var _Value: Double); +begin + HexDumpToDbl(string(_s), _Value); +end; +{$ENDIF SUPPORTS_UNICODE} + procedure HexDumpToExtended(const _s: string; var _Value: Extended); type TBuffer = array[0..SizeOf(_Value)] of Byte; Modified: trunk/ExternalSource/dzlib/u_dzStringUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzStringUtils.pas 2023-07-17 14:35:43 UTC (rev 4045) +++ trunk/ExternalSource/dzlib/u_dzStringUtils.pas 2023-08-03 12:58:46 UTC (rev 4046) @@ -59,7 +59,7 @@ /// Cuts off the string at the first #0 and returns the new length </summary> function StrTrimNul(var _s: AnsiString): Integer; ///<summary> use StrTrimNul </summary> -function StrTrimZero(var _s: AnsiString): integer; deprecated; // use StrTrimNul +function StrTrimZero(var _s: AnsiString): Integer; deprecated; // use StrTrimNul ///<summary> /// Converts an array of byte to a string, interpreting the bytes as AnsiString </summary> @@ -353,7 +353,10 @@ ///<summary> /// Replaces all control characters (ord(c) < ord(' ')) with ReplaceChar. /// If RemoveDuplicates is true, a sequence of control characters is replaced by a single ReplaceChar. </summary> -function ReplaceCtrlChars(const _s: string; _ReplaceChar: Char; _RemoveDuplicates: Boolean = True): string; +function ReplaceCtrlChars(const _s: string; _ReplaceChar: Char; _RemoveDuplicates: Boolean = True): string; overload; +{$IFDEF SUPPORTS_UNICODE} +function ReplaceCtrlChars(const _s: AnsiString; _ReplaceChar: AnsiChar; _RemoveDuplicates: Boolean = True): AnsiString; overload; +{$ENDIF SUPPORTS_UNICODE} ///<summary> /// Replaces all control characters (ord(c) < ord(' ')) with Spaces. @@ -389,11 +392,40 @@ /// @returns the Nth character of S or ' ' if S has less than N charaters. </summary> function nthCharOf(const _s: string; _n: Integer): Char; +{$IFDEF SUPPORTS_UNICODE} ///<summary> /// Extract the first word of S using the given delimiters. The word is deleted from S. /// See also ExtractStr. /// NOTE: Duplicate delimiters are ignored, so 'abc def' will be split into two words (which you /// would expect), but also 'abc'#9#9'def' is two words (which you might not expect) </summary> +function ExtractFirstWord(var _s: AnsiString; const _Delimiter: AnsiString): AnsiString; overload; +///<summary> +/// Extract the first word of S using the given delimiters. The word is deleted from S. +/// See also ExtractStr. +/// NOTE: Duplicate delimiters are ignored, so 'abc def' will be split into two words (which you +/// would expect), but also 'abc'#9#9'def' is two words (which you might not expect) </summary> +function ExtractFirstWord(var _s: AnsiString; _Delimiter: TCharSet): AnsiString; overload; +///<summary> +/// Extract the first word of S using the given delimiters. The word is deleted from S. +/// See also ExtractStr. +/// NOTE: Duplicate delimiters are ignored, so 'abc def' will be split into two words (which you +/// would expect), but also 'abc'#9#9'def' is two words (which you might not expect) +/// @returns true, if a word could be extracted, false otherwise </summary> +function ExtractFirstWord(var _s: AnsiString; const _Delimiter: AnsiString; out _FirstWord: AnsiString): Boolean; overload; +///<summary> +/// Extract the first word of S using the given delimiters. The word is deleted from S. +/// See also ExtractStr. +/// NOTE: Duplicate delimiters are ignored, so 'abc def' will be split into two words (which you +/// would expect), but also 'abc'#9#9'def' is two words (which you might not expect) +/// @returns true, if a word could be extracted, false otherwise </summary> +function ExtractFirstWord(var _s: AnsiString; _Delimiter: TCharSet; out _FirstWord: AnsiString): Boolean; overload; +{$ENDIF SUPPORTS_UNICODE} + +///<summary> +/// Extract the first word of S using the given delimiters. The word is deleted from S. +/// See also ExtractStr. +/// NOTE: Duplicate delimiters are ignored, so 'abc def' will be split into two words (which you +/// would expect), but also 'abc'#9#9'def' is two words (which you might not expect) </summary> function ExtractFirstWord(var _s: string; const _Delimiter: string): string; overload; ///<summary> /// Extract the first word of S using the given delimiters. The word is deleted from S. @@ -574,7 +606,7 @@ end; function nthWordStartAndEnd(const _s: string; _WordNo: Integer; - const _Delimiter: AnsiString; out _Start, _Ende: Integer): Boolean; overload; + const _Delimiter: string; out _Start, _Ende: Integer): Boolean; overload; var i: Integer; DelimiterSet: TCharSet; @@ -581,17 +613,23 @@ begin DelimiterSet := []; for i := 1 to Length(_Delimiter) do - Include(DelimiterSet, _Delimiter[i]); + Include(DelimiterSet, AnsiChar(_Delimiter[i])); Result := nthWordStartAndEnd(_s, _WordNo, DelimiterSet, _Start, _Ende); end; {$IFDEF SUPPORTS_UNICODE} -function nthWordStartAndEnd(const _s: string; _WordNo: Integer; - const _Delimiter: string; out _Start, _Ende: Integer): Boolean; overload; +function nthWordStartAndEnd(const _s: AnsiString; _WordNo: Integer; + const _Delimiter: AnsiString; out _Start, _Ende: Integer): Boolean; overload; begin - Result := nthWordStartAndEnd(_s, _WordNo, AnsiString(_Delimiter), _Start, _Ende); + Result := nthWordStartAndEnd(string(_s), _WordNo, string(_Delimiter), _Start, _Ende); end; + +function nthWordStartAndEnd(const _s: AnsiString; _WordNo: Integer; + const _Delimiter: TCharSet; out _Start, _Ende: Integer): Boolean; overload; +begin + Result := nthWordStartAndEnd(string(_s), _WordNo, _Delimiter, _Start, _Ende); +end; {$ENDIF SUPPORTS_UNICODE} function nthWord(const _s: string; _WordNo: Integer; const _Delimiter: string): string; @@ -652,6 +690,46 @@ end; end; +{$IFDEF SUPPORTS_UNICODE} +function ExtractFirstWord(var _s: AnsiString; _Delimiter: TCharSet): AnsiString; +begin + if not ExtractFirstWord(_s, _Delimiter, Result) then begin // s contained only Delimiters + Result := ''; + _s := ''; + end; +end; + +function ExtractFirstWord(var _s: AnsiString; const _Delimiter: AnsiString): AnsiString; +begin + if not ExtractFirstWord(_s, _Delimiter, Result) then begin // s contained only Delimiters + Result := ''; + _s := ''; + end; +end; + +function ExtractFirstWord(var _s: AnsiString; const _Delimiter: AnsiString; out _FirstWord: AnsiString): Boolean; +var + Start, Ende: Integer; +begin + Result := nthWordStartAndEnd(_s, 1, _Delimiter, Start, Ende); + if Result then begin + _FirstWord := Copy(_s, Start, Ende - Start); + _s := TailStr(_s, Ende + 1); + end; +end; + +function ExtractFirstWord(var _s: AnsiString; _Delimiter: TCharSet; out _FirstWord: AnsiString): Boolean; +var + Start, Ende: Integer; +begin + Result := nthWordStartAndEnd(_s, 1, _Delimiter, Start, Ende); + if Result then begin + _FirstWord := Copy(_s, Start, Ende - Start); + _s := TailStr(_s, Ende + 1); + end; +end; +{$ENDIF SUPPORTS_UNICODE} + function ExtractFirstN(var _s: string; _n: Integer): string; begin Result := Copy(_s, 1, _n); @@ -782,6 +860,13 @@ Dup := False; end; +{$IFDEF SUPPORTS_UNICODE} +function ReplaceCtrlChars(const _s: AnsiString; _ReplaceChar: AnsiChar; _RemoveDuplicates: Boolean = True): AnsiString; +begin + Result := AnsiString(ReplaceCtrlChars(string(_s), Char(_ReplaceChar), _RemoveDuplicates)); +end; +{$ENDIF SUPPORTS_UNICODE} + function ContainsOnlyCharsFrom(const _s: string; _ValidChars: TCharSet): Boolean; var i: Integer; Modified: trunk/ExternalSource/dzlib/u_dzVclUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2023-07-17 14:35:43 UTC (rev 4045) +++ trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2023-08-03 12:58:46 UTC (rev 4046) @@ -693,6 +693,10 @@ function TTabControl_GetSelectedObject(_TabControl: TTabControl; out _Obj: Pointer): Boolean; overload; function TTabControl_GetSelectedObject(_TabControl: TTabControl; out _Idx: Integer; out _Obj: Pointer): Boolean; overload; +///<sumamry> +/// disables and re-enables the timer so it starts again </summary> +procedure TTimer_Restart(_tim: TTimer); + ///<summary> Enables longer SimpleText (longer than 127 characters) /// Call once to enable. Works, by adding a single panel with owner drawing and /// setting the StatusBar's OnDrawPanel to a custom drawing method. @@ -707,7 +711,7 @@ /// Resize one panel a StatusBar to take up all the space the others don't need /// @param sb is the TStatusBar to work on /// @param PanelIdxToChange is the index of the panel whose size should be changed </summary> -procedure TStatusBar_Resize(_sb: TStatusBar; _PanelIdxToChange: integer); +procedure TStatusBar_Resize(_sb: TStatusBar; _PanelIdxToChange: Integer); ///<summary> /// Sets the text of a status bar panel and optionally adjusts its width to fit. @@ -3213,6 +3217,12 @@ _Obj := _TabControl.Tabs.Objects[_Idx]; end; +procedure TTimer_Restart(_tim: TTimer); +begin + _tim.Enabled := False; + _tim.Enabled := True; +end; + type // Note: This class is never instantiated, only the DrawPanel method will be used // without ever referencing the self pointer (which is NIL), so it should work @@ -3246,7 +3256,7 @@ _StatusBar.OnDrawPanel := Painter.DrawPanel; end; -procedure TStatusBar_Resize(_sb: TStatusBar; _PanelIdxToChange: integer); +procedure TStatusBar_Resize(_sb: TStatusBar; _PanelIdxToChange: Integer); var w: Integer; i: Integer; @@ -5523,7 +5533,7 @@ function TPopupMenu_AppendMenuItem(_pm: TPopupMenu; const _Caption: string): TMenuItem; overload; const - NilEvent: TMethod = (code: nil; data: nil); + NilEvent: TMethod = (Code: nil; Data: nil); begin Result := TPopupMenu_AppendMenuItem(_pm, _Caption, TNotifyEvent(NilEvent)); end; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tw...@us...> - 2023-10-28 13:01:19
|
Revision: 4076 http://sourceforge.net/p/gexperts/code/4076 Author: twm Date: 2023-10-28 13:01:16 +0000 (Sat, 28 Oct 2023) Log Message: ----------- dzlib updated to lastest sources Modified Paths: -------------- trunk/ExternalSource/dzlib/t_NullableNumber.tpl trunk/ExternalSource/dzlib/u_dzClassUtils.pas trunk/ExternalSource/dzlib/u_dzConvertUtils.pas trunk/ExternalSource/dzlib/u_dzFileUtils.pas trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas trunk/ExternalSource/dzlib/u_dzSortProvider.pas trunk/ExternalSource/dzlib/u_dzTypes.pas trunk/ExternalSource/dzlib/u_dzVclUtils.pas Modified: trunk/ExternalSource/dzlib/t_NullableNumber.tpl =================================================================== --- trunk/ExternalSource/dzlib/t_NullableNumber.tpl 2023-10-26 07:30:01 UTC (rev 4075) +++ trunk/ExternalSource/dzlib/t_NullableNumber.tpl 2023-10-28 13:01:16 UTC (rev 4076) @@ -89,6 +89,8 @@ /// <summary> invalid values are considered smaller than any valid values /// and equal to each other </summary> class function Compare(_a, _b: _NULLABLE_NUMBER_): Integer; static; + /// <summary> invalid values are considered equal to each other </summary> + class function IsSame(_a, _b: _NULLABLE_NUMBER_): Boolean; static; class function Invalid: _NULLABLE_NUMBER_; static; class function FromVariant(_a: Variant): _NULLABLE_NUMBER_; static; class function FromStr(const _s: string): _NULLABLE_NUMBER_; static; @@ -318,6 +320,21 @@ Result := -1; end; +class function _NULLABLE_NUMBER_.IsSame(_a, _b: _NULLABLE_NUMBER_): Boolean; +begin + if _a.IsValid then begin + if _b.IsValid then + Result := (_a.FValue = _b.FValue) + else + Result := False + end else begin + if _b.IsValid then + Result := False + else + Result := True; + end; +end; + function _NULLABLE_NUMBER_.Dump: string; begin Result := ToString('<invalid>'); // do not translate Modified: trunk/ExternalSource/dzlib/u_dzClassUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzClassUtils.pas 2023-10-26 07:30:01 UTC (rev 4075) +++ trunk/ExternalSource/dzlib/u_dzClassUtils.pas 2023-10-28 13:01:16 UTC (rev 4076) @@ -238,6 +238,44 @@ function TComponent_FindComponent(_Owner: TComponent; const _Name: string; _Recursive: Boolean; out _Found: TComponent; _CmpClass: TComponentClass = nil): Boolean; +{$IFDEF DELPHIX_TOKYO_UP} +///<summary> +/// Reads a maximum of Count bytes from the stream into the buffer and returns true if at least +/// one byte could be read. </summary> +function TStream_TryRead(_st: TStream; _Buffer: TBytes; _Offset, _Count: Int32; + out _BytesRead: Int32): Boolean; overload; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} + +///<summary> +/// Reads a maximum of Count bytes from the stream into the buffer and returns true if at least +/// one byte could be read. </summary> +function TStream_TryRead(_st: TStream; _Buffer: TBytes; _Offset, _Count: Int64; + out _BytesRead: Int64): Boolean; overload; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} +{$ENDIF} + +///<summary> +/// Reads a maximum of Count bytes from the stream into the buffer and returns true if at least +/// one byte could be read. </summary> +function TStream_TryRead(_st: TStream; var _Buffer; _Count: Int32; + out _BytesRead: Int32): Boolean; overload; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} + +///<summary> +/// Reads a maximum of Count bytes from the stream into the buffer and returns true if at least +/// one byte could be read. </summary> +function TStream_TryRead(_st: TStream; var _Buffer: TBytes; _Count: Int32; + out _BytesRead: Int32): Boolean; overload; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} + /// <summary> /// Write a string to the stream /// @param Stream is the TStream to write to. @@ -1095,6 +1133,36 @@ Result := _st.Values[Name]; end; +function TStream_TryRead(_st: TStream; var _Buffer: TBytes; _Count: Int32; + out _BytesRead: Int32): Boolean; overload; +begin + _BytesRead := _st.Read(_Buffer, _Count); + Result := (_BytesRead > 0); +end; + +function TStream_TryRead(_st: TStream; var _Buffer; _Count: Int32; + out _BytesRead: Int32): Boolean; overload; +begin + _BytesRead := _st.Read(_Buffer, _Count); + Result := (_BytesRead > 0); +end; + +{$IFDEF DELPHIX_TOKYO_UP} +function TStream_TryRead(_st: TStream; _Buffer: TBytes; _Offset, _Count: Int32; + out _BytesRead: Int32): Boolean; overload; +begin + _BytesRead := _st.Read(_Buffer, _Offset, _Count); + Result := (_BytesRead > 0); +end; + +function TStream_TryRead(_st: TStream; _Buffer: TBytes; _Offset, _Count: Int64; + out _BytesRead: Int64): Boolean; overload; +begin + _BytesRead := _st.Read64(_Buffer, _Offset, _Count); + Result := (_BytesRead > 0); +end; +{$ENDIF} + function TStream_WriteString(_Stream: TStream; const _s: RawByteString): Integer; var Len: Integer; Modified: trunk/ExternalSource/dzlib/u_dzConvertUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzConvertUtils.pas 2023-10-26 07:30:01 UTC (rev 4075) +++ trunk/ExternalSource/dzlib/u_dzConvertUtils.pas 2023-10-28 13:01:16 UTC (rev 4076) @@ -177,19 +177,25 @@ ///<summary> /// Reduces an Integer to a Byte value by cutting it off at 0 and 255 </summary> function ReduceToByte(const _Value: Integer): Byte; -{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + function ReduceToInt8(const _Value: Integer): Int8; -{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + function ReduceToUInt8(const _Value: Integer): UInt8; -{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + function ReduceToInt16(const _Value: Integer): Int16; -{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + function ReduceToUInt16(const _Value: Integer): UInt16; -{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + function ReduceToInt32(const _Value: Int64): Int32; -{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + function ReduceToUInt32(const _Value: Int64): UInt32; -{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> /// Converts a string of the form '-hh:mm:ss', 'hh:mm:ss', @@ -282,9 +288,9 @@ /// @returns true, if s could be converted, false otherwise /// NOTE: This is not thread safe in Delphi 6 because there it changes the global /// variable DecimalSeparator in SysUtils. </summary> -{$IFNDEF Win64} function TryStr2Float(const _s: string; out _flt: Extended; _DecSeparator: Char = '.'): Boolean; overload; -{$ENDIF} + +{$IF SizeOf(Extended) <> SizeOf(Double)} ///<summary> /// tries to convert a string to a float, returns false if it fails /// @param s is the string to convert @@ -295,6 +301,7 @@ /// NOTE: This is not thread safe in Delphi 6 because there it changes the global /// variable DecimalSeparator in SysUtils. </summary> function TryStr2Float(const _s: string; out _flt: Double; _DecSeparator: Char = '.'): Boolean; overload; +{$IFEND} function TryStr2Float(const _s: string; out _flt: Single; _DecSeparator: Char = '.'): Boolean; overload; ///<summary> @@ -386,17 +393,17 @@ ///<summary> /// returns the long word split into an array of byte -/// @param Value is the LongWord value to split +/// @param Value is the UInt32 value to split /// @param MsbFirst, if true the most significant byte is the first in the array (Motorola format) /// if false the least significatn byte is the first in the array (Intel format) </summary> -function LongWord2ByteArr(_Value: LongWord; _MsbFirst: Boolean = False): TBytes; +function LongWord2ByteArr(_Value: UInt32; _MsbFirst: Boolean = False): TBytes; ///<summary> -/// returns the the array of byte combined into a LongWord +/// returns the the array of byte combined into a UInt32 /// @param Value is the array to combine /// @param MsbFirst, if true the most significant byte is the first in the array (Motorola format) /// if false the least significatn byte is the first in the array (Intel format) </summary> -function ByteArr2LongWord(const _Arr: array of Byte; _MsbFirst: Boolean = False): LongWord; +function ByteArr2LongWord(const _Arr: array of Byte; _MsbFirst: Boolean = False): UInt32; ///<summary> /// returns a 16 bit in reversed byte order, e.g. $1234 => $3412) @@ -404,12 +411,13 @@ /// (This is just an alias for system.swap for consistency with Swap32.) ///</summary function Swap16(_Value: Word): Word; +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> /// returns a 32 bit value in reversed byte order e.g. $12345678 -> $78563412 /// aka converts intel (little endian) to motorola (big endian) byte order format </summary> -function Swap32(_Value: LongWord): LongWord; -function Swap32pas(_Value: LongWord): LongWord; +function Swap32(_Value: UInt32): UInt32; +function Swap32pas(_Value: UInt32): UInt32; ///<summary> /// returns a 64 bit value in reversed byte order e.g. $123456789ABCDEF0 -> $F0DEBC9A78563412 @@ -416,7 +424,7 @@ /// aka converts intel (little endian) to motorola (big endian) byte order format </summary> function Swap64(_Value: UInt64): UInt64; -function BitReverse32(v: LongWord): LongWord; +function BitReverse32(v: UInt32): UInt32; {$IFDEF SUPPORTS_ENHANCED_RECORDS} type @@ -670,9 +678,7 @@ u_dzStringUtils; function _(const _s: string): string; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} begin Result := dzDGetText(_s, 'dzlib'); end; @@ -1210,7 +1216,6 @@ Result := '.'; end; -{$IFNDEF Win64} function TryStr2Float(const _s: string; out _flt: Extended; _DecSeparator: Char = '.'): Boolean; var {$IF Declared(TFormatSettings)} @@ -1235,8 +1240,8 @@ end; {$IFEND} end; -{$ENDIF} +{$IF SizeOf(Extended) <> SizeOf(Double)} function TryStr2Float(const _s: string; out _flt: Double; _DecSeparator: Char = '.'): Boolean; var flt: Extended; @@ -1245,6 +1250,7 @@ if Result then _flt := flt; end; +{$IFEND} function TryStr2Float(const _s: string; out _flt: Single; _DecSeparator: Char = '.'): Boolean; var @@ -1319,7 +1325,7 @@ end; {$IFEND} -function LongWord2ByteArr(_Value: LongWord; _MsbFirst: Boolean = False): TBytes; +function LongWord2ByteArr(_Value: UInt32; _MsbFirst: Boolean = False): TBytes; begin SetLength(Result, SizeOf(_Value)); if _MsbFirst then begin @@ -1335,10 +1341,10 @@ end; end; -function ByteArr2LongWord(const _Arr: array of Byte; _MsbFirst: Boolean = False): LongWord; +function ByteArr2LongWord(const _Arr: array of Byte; _MsbFirst: Boolean = False): UInt32; begin if Length(_Arr) <> SizeOf(Result) then - raise Exception.CreateFmt(_('Length of byte array (%d) does not match size of a LongWord (%d)'), [Length(_Arr), SizeOf(Result)]); + raise Exception.CreateFmt(_('Length of byte array (%d) does not match size of a UInt32 (%d)'), [Length(_Arr), SizeOf(Result)]); if _MsbFirst then begin Result := _Arr[0] shl 24 + _Arr[1] shl 16 + _Arr[2] shl 8 + _Arr[3]; end else begin @@ -1347,9 +1353,6 @@ end; function Swap16(_Value: Word): Word; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} begin Result := swap(_Value); end; @@ -1359,15 +1362,22 @@ // rol ax, 8 //end; -function Swap32(_Value: LongWord): LongWord; -asm - bswap eax +function Swap32pas(_Value: UInt32): UInt32; +begin + Result := ((_Value shr 24) and $FF) + (((_Value shr 16) and $FF) shl 8) + (((_Value shr 8) and $FF) shl 16) + ((_Value and $FF) shl 24); end; -function Swap32pas(_Value: LongWord): LongWord; +{$IFDEF CPU64} +function Swap32(_Value: UInt32): UInt32; begin - Result := ((_Value shr 24) and $FF) + (((_Value shr 16) and $FF) shl 8) + (((_Value shr 8) and $FF) shl 16) + ((_Value and $FF) shl 24); + Result := Swap32pas(_Value); end; +{$ELSE} +function Swap32(_Value: UInt32): UInt32; +asm + bswap eax +end; +{$ENDIF} function Swap64(_Value: UInt64): UInt64; asm @@ -1377,7 +1387,7 @@ BSWAP EAX end; -function BitReverse32(v: LongWord): LongWord; +function BitReverse32(v: UInt32): UInt32; // source (C code): // https://apps.topcoder.com/forums/?module=Thread&threadID=514884&start=2 begin @@ -1487,7 +1497,7 @@ var Bytes: TByteArr8 absolute FValue; begin - Result := Bytes[_byteNo]; + Result := Bytes[_ByteNo]; end; procedure TBits64.SetByte(_ByteNo: TByteNumber; _Value: Byte); @@ -1582,14 +1592,19 @@ end; function TBits32.GetByte(_ByteNo: TByteNumber): Byte; +var + BitNo: TBitNumber; begin - Result := (FValue shr (_ByteNo * 8)) and $FF; + BitNo := _ByteNo * 8; + Result := (FValue shr BitNo) and $FF; end; procedure TBits32.SetByte(_ByteNo: TByteNumber; _Value: Byte); +var + BitNo: TBitNumber; begin - _ByteNo := _ByteNo * 8; - FValue := FValue and ($FFFFFFFF xor ($FF shl _ByteNo)) or (_Value shl _ByteNo); + BitNo := _ByteNo * 8; + FValue := FValue and ($FFFFFFFF xor ($FF shl BitNo)) or (_Value shl BitNo); end; procedure TBits32.Init(_Value: TValue); @@ -1738,14 +1753,19 @@ end; function TBits16.GetByte(_ByteNo: TByteNumber): Byte; +var + BitNo: TBitNumber; begin - Result := (FValue shr (_ByteNo * 8)) and $FF; + BitNo := _ByteNo * 8; + Result := (FValue shr BitNo) and $FF; end; procedure TBits16.SetByte(_ByteNo: TByteNumber; _Value: Byte); +var + BitNo: TBitNumber; begin - _ByteNo := _ByteNo * 8; - FValue := FValue and ($FFFF xor ($FF shl _ByteNo)) or (_Value shl _ByteNo); + BitNo := _ByteNo * 8; + FValue := FValue and ($FFFF xor ($FF shl BitNo)) or (_Value shl BitNo); end; class operator TBits16.Equal(_a, _b: TBits16): Boolean; Modified: trunk/ExternalSource/dzlib/u_dzFileUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzFileUtils.pas 2023-10-26 07:30:01 UTC (rev 4075) +++ trunk/ExternalSource/dzlib/u_dzFileUtils.pas 2023-10-28 13:01:16 UTC (rev 4076) @@ -117,15 +117,16 @@ /// @param List is a string list to which the files will be appended, may be nil /// @param IncludePath determines whether the List of filenames includes the full path or not </summary> class function Execute(const _Mask: string; _List: TStrings; - _MayHaveAttr: TFileAttributeSet = ALL_FILES_ATTRIB_SET; _IncludePath: Boolean = False; _Sort: Boolean = True): Integer; + _MayHaveAttr: TFileAttributeSet = ALL_FILES_ATTRIB_SET; _IncludePath: Boolean = False; + _Sort: Boolean = True; _Recursive: Boolean = False): Integer; /// <summary> /// creates a TSimpleDirEnumerator, calls its FindAll method and frees it /// @param List is a string list to which the files will be appended, may be nil /// @param IncludePath determines whether the List of filenames includes the full path or not </summary> class function EnumFilesOnly(const _Mask: string; _List: TStrings; - _IncludePath: Boolean = False; _Sort: Boolean = True): Integer; overload; + _IncludePath: Boolean = False; _Sort: Boolean = True; _Recursive: Boolean = False): Integer; overload; class function EnumFilesOnly(const _Mask: string; - _IncludePath: Boolean = False; _Sort: Boolean = True): TStringArray; overload; + _IncludePath: Boolean = False; _Sort: Boolean = True; _Recursive: Boolean = False): TStringArray; overload; ///<summary> /// Calls the given callback for all files matching the mask. To Abort, raise EAbort. </summary> class procedure EnumFilesOnly(const _Mask: string; _Callback: TOnFileEnumCallback; @@ -1026,7 +1027,8 @@ /// @returns True, if the last extension of Filename matches the given extension. /// Comparison is case insensitive /// False if the extensions don't machch. </summary> - class function HasFileExtLast(const _Filename: string; const _Ext: string): Boolean; + class function HasFileExtLast(const _Filename: string; const _Ext: string): Boolean; overload; + class function HasFileExtLast(const _Filename: string; const _Ext: TStringArray): Boolean; overload; ///<summary> /// Sets the file's date and time to the given time or to the current time @@ -1377,14 +1379,14 @@ end; end; -class function TSimpleDirEnumerator.EnumFilesOnly(const _Mask: string; _IncludePath, - _Sort: Boolean): TStringArray; +class function TSimpleDirEnumerator.EnumFilesOnly(const _Mask: string; _IncludePath: Boolean; + _Sort: Boolean; _Recursive: Boolean): TStringArray; var sl: TStringList; begin sl := TStringList.Create; try - EnumFilesOnly(_Mask, sl, _IncludePath, _Sort); + EnumFilesOnly(_Mask, sl, _IncludePath, _Sort, _Recursive); Result := TStringArray_FromStrings(sl); finally FreeAndNil(sl); @@ -1392,17 +1394,22 @@ end; class function TSimpleDirEnumerator.EnumFilesOnly(const _Mask: string; _List: TStrings; - _IncludePath, _Sort: Boolean): Integer; + _IncludePath, _Sort: Boolean; _Recursive: Boolean): Integer; begin - Result := Execute(_Mask, _List, [dfaArchive], _IncludePath, _Sort); + Result := Execute(_Mask, _List, [dfaArchive], _IncludePath, _Sort, _Recursive); end; class function TSimpleDirEnumerator.Execute(const _Mask: string; _List: TStrings; _MayHaveAttr: TFileAttributeSet = ALL_FILES_ATTRIB_SET; - _IncludePath: Boolean = False; _Sort: Boolean = True): Integer; + _IncludePath: Boolean = False; _Sort: Boolean = True; _Recursive: Boolean = False): Integer; var enum: TSimpleDirEnumerator; List: TStringList; + dirs: TStringArray; + BaseDirBS: string; + DirIdx: Integer; + MaskOnly: string; + SubDirBS: string; begin enum := TSimpleDirEnumerator.Create(_Mask, _MayHaveAttr); try @@ -1420,6 +1427,23 @@ finally FreeAndNil(enum); end; + if _Recursive then begin + BaseDirBS := itpd(ExtractFileDir(_Mask)); + MaskOnly := ExtractFileName(_Mask); + dirs := EnumDirsOnly(BaseDirBS + '*', True); + for DirIdx := Low(dirs) to High(dirs) do begin + SubDirBS := itpd(dirs[DirIdx]); + List := TStringList.Create; + try + TSimpleDirEnumerator.EnumFilesOnly(SubDirBS + MaskOnly, List, _IncludePath, _Sort, True); + if _Sort then + List.Sort; + _List.AddStrings(List); + finally + FreeAndNil(List); + end; + end; + end; end; function TSimpleDirEnumerator.FindAll(_List: TStrings = nil; _IncludePath: Boolean = False): Integer; @@ -1556,6 +1580,20 @@ Result := SameText(_Ext, ExtractFileExtFull(_Filename)); end; +class function TFileSystem.HasFileExtLast(const _Filename: string; + const _Ext: TStringArray): Boolean; +var + i: Integer; +begin + for i := Low(_Ext) to High(_Ext) do begin + if HasFileExtLast(_Filename, _Ext[i]) then begin + Result := True; + Exit; //==> + end; + end; + Result := False; +end; + class function TFileSystem.HasFileExtLast(const _Filename, _Ext: string): Boolean; begin Result := SameText(_Ext, ExtractFileExtLast(_Filename)); Modified: trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2023-10-26 07:30:01 UTC (rev 4075) +++ trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2023-10-28 13:01:16 UTC (rev 4076) @@ -21,6 +21,8 @@ {$IFNDEF NO_OPTIMIZE_DZ_GRAPHIC_UTILS_HINT} {$MESSAGE HINT 'optimization is off, consider turning it on for significantly better performance'} {$ENDIF} +// if optimization is turned off, we also turn off inlining +{$UNDEF SUPPORTS_INLINE} {$ELSE} // If optimization is on, we turn off assertions, just in case the programmer forgot. // The reason for this is that we have some assertions below that might significantly impact @@ -257,8 +259,13 @@ TDrawTextFlagSetNoAlign = set of TDrawTextFlagsNoAlign; ///<summary> -/// Calculates the Rect necessary for drawing the text. -/// @returns the calculated height </summary> +/// Uses WinApi.DrawText to draw the given text on the canvas. +/// @param Flags determines how the text is drawn. if it contains dtfCalcRect, this function +/// does not draw the text but only calculates the Rect necessary for drawing it. +/// @returns 0, if the call to WinApi.DrawText fails +/// the calculated height of the text in logical units. +/// If dtfBottomSingle or dtfVCenterSingle is specified, the return value is the offset +/// from Rect.top to the bottom of the drawn text. </summary> function TCanvas_DrawText(_Canvas: TCanvas; const _Text: string; var _Rect: TRect; _Flags: TDrawTextFlagSet): Integer; {$IFDEF SUPPORTS_INLINE} inline; @@ -499,7 +506,8 @@ procedure TBitmap_AssignMono824(_Buffer: PByte; _bmp: TBitmap; _YIsReversed: Boolean); ///<summary> -/// Assign a buffer containing a bitmap in Mono 8 format to a 8 bit gray scale TBitmap </summary> +/// Assign a buffer containing a bitmap in Mono 8 format to a 8 bit gray scale TBitmap +/// @NOTE: The bitmap is assumed to already have the correct size and pixel format </summary> procedure TBitmap_AssignMono8(_Buffer: PByte; _bmp: TBitmap; _YIsReversed: Boolean); overload; procedure TBitmap_AssignMono8(_Buffer: PByte; _bmp: TBitmap; _YIsReversed: Boolean; _RowStride: Int64); overload; @@ -509,10 +517,15 @@ /// next value </summary> TBufferBitsToMono8Func = function(var _BufPtr: Pointer): Byte; TBufferBitsToMono8Meth = function(var _BufPtr: Pointer): Byte of object; + TBufferBitsToRgb8Func = function(var _BufPtr: Pointer): TdzRgbTriple; + TBufferBitsToRgb8Meth = function(var _BufPtr: Pointer): TdzRgbTriple of object; ///<summary> /// Converts a 12 bit value at the given position to a Byte and increments BufPtr by 2 </summary> function BufferBits12ToMono8(var _BufPtr: Pointer): Byte; +///<summary> +/// Converts a 12 bit value at the given position to a rainbow color and increments BufPtr by 2 </summary> +function BufferBits12ToRgb8(var _BufPtr: Pointer): TdzRgbTriple; ///<summary> /// Assign a buffer containing a bitmap in Monochrome format to a 8 bit gray scale TBitmap @@ -526,6 +539,11 @@ procedure TBitmap_AssignToMono8(_BufferBitsToMono8Meth: TBufferBitsToMono8Meth; _Buffer: Pointer; _bmp: TBitmap; _YIsReversed: Boolean; _RowStride: Int64 = 0); overload; +procedure TBitmap_AssignToRgb8(_BufferBitsToRgb8Func: TBufferBitsToRgb8Func; + _Buffer: Pointer; _bmp: TBitmap; _YIsReversed: Boolean; _RowStride: Int64 = 0); overload; +procedure TBitmap_AssignToRgb8(_BufferBitsToRgb8Meth: TBufferBitsToRgb8Meth; + _Buffer: Pointer; _bmp: TBitmap; _YIsReversed: Boolean; _RowStride: Int64 = 0); overload; + ///<summary> /// converts a pf24bit or pf32bit monochrome bitmap to a pf8bit monochrome bitmap </summary> function TBitmap_MonoToMono8(_bmp: TBitmap): TBitmap; overload; @@ -817,37 +835,28 @@ ///<summary> /// @param Hue is a value between 0 and 1 </summary> function RainbowColor(_Hue: Double): TColor; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{{*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} -{$IFDEF SUPPORTS_ENHANCED_RECORDS} ///<summary> /// @param Hue is a value between 0 and 1 </summary> procedure RainbowColor(_Hue: Double; out _Color: TdzRgbTriple); overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} -{$ENDIF} +// Note: Cannot be declared as inline + ///<summary> /// @param Brightness is a grayscale value </summary> function RainbowColor(_Brightness: Byte): TColor; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{{*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + procedure RainbowColor(_Brightness: Byte; out _Red, _Green, _Blue: Byte); overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{{*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + procedure RainbowColor(_Brightness: Byte; out _Pixel: TdzRgbTriple); overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{{*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + function RainbowColor(_MinHue, _MaxHue, _Hue: Integer): TColor; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{{*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + function TryStr2Color(const _s: string; out _Color: TColor): Boolean; function TPicture_TryLoadMatchingFile(_pic: TPicture; const _FileMask: string): Boolean; @@ -1998,6 +2007,15 @@ IncPtr(_BufPtr, 2); end; +function BufferBits12ToRgb8(var _BufPtr: Pointer): TdzRgbTriple; +var + Value: Double; +begin + Value := PUInt16(_BufPtr)^ / (1 shl 12 - 1); + RainbowColor(Value, Result); + IncPtr(_BufPtr, 2); +end; + procedure TBitmap_AssignToMono8(_BufferBitsToMono8Func: TBufferBitsToMono8Func; _Buffer: Pointer; _bmp: TBitmap; _YIsReversed: Boolean; _RowStride: Int64); overload; var @@ -2072,6 +2090,80 @@ end; end; +procedure TBitmap_AssignToRgb8(_BufferBitsToRgb8Func: TBufferBitsToRgb8Func; + _Buffer: Pointer; _bmp: TBitmap; _YIsReversed: Boolean; _RowStride: Int64 = 0); +var + y: Integer; + x: Integer; + w: Integer; + h: Integer; + ScanLine: PdzRgbTriple; + Buf: Pointer; +begin + Assert(AssertPixelFormat(_bmp, pf24bit)); + + w := _bmp.Width; + h := _bmp.Height; + + Assert((_RowStride = 0) or (_RowStride >= w)); + + for y := 0 to _bmp.Height - 1 do begin + if _YIsReversed then begin + ScanLine := _bmp.ScanLine[h - 1]; + end else begin + ScanLine := _bmp.ScanLine[y]; + end; + Buf := _Buffer; + for x := 0 to w - 1 do begin + ScanLine^ := _BufferBitsToRgb8Func(Buf); + Inc(ScanLine); + end; + if _RowStride > 0 then begin + IncPtr(_Buffer, _RowStride); + end else begin + // we assume that _BufferBitsToRgb8Func inrements the buffer correctly + _Buffer := Buf; + end; + end; +end; + +procedure TBitmap_AssignToRgb8(_BufferBitsToRgb8Meth: TBufferBitsToRgb8Meth; + _Buffer: Pointer; _bmp: TBitmap; _YIsReversed: Boolean; _RowStride: Int64 = 0); +var + y: Integer; + x: Integer; + w: Integer; + h: Integer; + ScanLine: PdzRgbTriple; + Buf: Pointer; +begin + Assert(AssertPixelFormat(_bmp, pf24bit)); + + w := _bmp.Width; + h := _bmp.Height; + + Assert((_RowStride = 0) or (_RowStride >= w)); + + for y := 0 to _bmp.Height - 1 do begin + if _YIsReversed then begin + ScanLine := _bmp.ScanLine[h - 1]; + end else begin + ScanLine := _bmp.ScanLine[y]; + end; + Buf := _Buffer; + for x := 0 to w - 1 do begin + ScanLine^ := _BufferBitsToRgb8Meth(Buf); + Inc(ScanLine); + end; + if _RowStride > 0 then begin + IncPtr(_Buffer, _RowStride); + end else begin + // we assume that _BufferBitsToRgb8Meth inrements the buffer correctly + _Buffer := Buf; + end; + end; +end; + type PByteArray = SysUtils.PByteArray; TCopyScanline = procedure(_Width: Integer; _SrcLine: Pointer; _DestLine: Pointer); @@ -4032,7 +4124,13 @@ end; end; -{$IFDEF SUPPORTS_ENHANCED_RECORDS} +procedure TdzRgbTriple_SetValues(_Triple: TdzRgbTriple; _Red, _Green, _Blue: Byte); +begin + _Triple.Red := _Red; + _Triple.Green := _Green; + _Triple.Blue := _Blue; +end; + procedure RainbowColor(_Hue: Double; out _Color: TdzRgbTriple); var Value: Double; @@ -4041,16 +4139,15 @@ Value := EnsureRange(_Hue, 0, 1) * 6; IntValue := Round(Frac(Value) * 255); case Trunc(Value) of - 0: _Color.SetValues(255, IntValue, 0); - 1: _Color.SetValues(255 - IntValue, 255, 0); - 2: _Color.SetValues(0, 255, IntValue); - 3: _Color.SetValues(0, 255 - IntValue, 255); - 4: _Color.SetValues(IntValue, 0, 255); + 0: TdzRgbTriple_SetValues(_Color, 255, IntValue, 0); + 1: TdzRgbTriple_SetValues(_Color, 255 - IntValue, 255, 0); + 2: TdzRgbTriple_SetValues(_Color, 0, 255, IntValue); + 3: TdzRgbTriple_SetValues(_Color, 0, 255 - IntValue, 255); + 4: TdzRgbTriple_SetValues(_Color, IntValue, 0, 255); else // 5 - _Color.SetValues(255, 0, 255 - IntValue); + TdzRgbTriple_SetValues(_Color, 255, 0, 255 - IntValue); end; end; -{$ENDIF} procedure RainbowColor(_Brightness: Byte; out _Red, _Green, _Blue: Byte); var Modified: trunk/ExternalSource/dzlib/u_dzSortProvider.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzSortProvider.pas 2023-10-26 07:30:01 UTC (rev 4075) +++ trunk/ExternalSource/dzlib/u_dzSortProvider.pas 2023-10-28 13:01:16 UTC (rev 4076) @@ -134,7 +134,14 @@ function TdzIntegerArraySortProvider.doCompare(_IndexA, _IndexB: Integer): Integer; begin +{$IFOPT R+} +{$DEFINE WAS_R_PLUS} +{$R-} +{$ENDIF} Result := CompareValue(FOriginal^[_IndexA], FOriginal^[_IndexB]); +{$IFDEF WAS_R_PLUS} +{$R+} +{$ENDIF} end; { TdzSortProvider } Modified: trunk/ExternalSource/dzlib/u_dzTypes.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzTypes.pas 2023-10-26 07:30:01 UTC (rev 4075) +++ trunk/ExternalSource/dzlib/u_dzTypes.pas 2023-10-28 13:01:16 UTC (rev 4076) @@ -186,6 +186,8 @@ type TMethodPointer = procedure of object; +const + NilEvent: TMethod = (Code: nil; Data: nil); type TRectLTWH = record Modified: trunk/ExternalSource/dzlib/u_dzVclUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2023-10-26 07:30:01 UTC (rev 4075) +++ trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2023-10-28 13:01:16 UTC (rev 4076) @@ -763,12 +763,21 @@ end; {$ENDIF DELPHI2009_UP} -///<summary> sets the control and all its child controls Enabled property and changes their -/// caption to reflect this -/// @param Control is the TControl to change -/// @param Enabled is a boolean with the new value for the Enabled property. </summary> +///<summary> +/// sets the control and all its child controls Enabled property and changes their +/// caption to reflect this +/// @param Control is the TControl to change +/// @param Enabled is a boolean with the new value for the Enabled property. </summary> procedure TControl_SetEnabled(_Control: TControl; _Enabled: Boolean); +///<summary> +/// Sets the Enabled property for all controls in the given array. +/// @param Controls is the array of controls to process +/// @param Enabled is the value to set the Enabled property to +/// @param Recursive determines if also controls that are placed on the given controls should be +/// processed. Defaults to False. </summary> +procedure TControls_SetEnabled(_Controls: array of TControl; _Enabled: Boolean; _Recursive: Boolean = False); + ///<summary> Calls protected TControl.Resize (which calls TControl.OnResize if assigned) </summary> procedure TControl_Resize(_Control: TControl); @@ -1523,7 +1532,7 @@ /// lvrCaptions means resize so the captions fit /// lvrContent menas resize so the contents fit /// both can be combined. </summary> -procedure TListView_ResizeColumn(_lc: TListColumn; _Options: TLIstViewResizeOptionSet); +procedure TListView_ResizeColumn(_lc: TListColumn; _Options: TLIstViewResizeOptionSet = [lvrCaptions, lvrContent]); ///<summary> /// Resize all columns of a TListView in vsReport ViewStyle /// @param lc is the TListColumn to resize @@ -1854,7 +1863,6 @@ {$IFDEF dzMESSAGEDEBUG} u_dzWmMessageToString, {$ENDIF dzMESSAGEDEBUG} - u_dzSortProvider, u_dzLineBuilder, u_dzTypesUtils, u_dzOsUtils, @@ -2774,6 +2782,11 @@ end; end; +const + // 2 pixels right and left, like in TStringGrid.DrawCell + // plus 1 additional pixel that seems to be necessary since Windows 10 + DrawCellAdditionalPixels = 3; + procedure HandleRow(_Grid: TGridHack; _Col, _Row: Integer; var _MinWidth: Integer); var ColWidth: Integer; @@ -2884,7 +2897,7 @@ if goVertLine in Grid.Options then Inc(MinWidth, Grid.GridLineWidth); - Inc(MinWidth, 4); // 2 pixels to the left and right, as in TStringGrid.DrawCell + Inc(MinWidth, DrawCellAdditionalPixels * 2); if not (roReduceMinWidth in _Options) then begin if MinWidth < Grid.DefaultColWidth then @@ -3003,8 +3016,12 @@ if dgColLines in Grid.Options then // there is one more grid line than there are columns Inc(Result, Grid.GridLineWidth); - if dgIndicator in Grid.Options then - Inc(Result, 21); // ColWidht[0] does not work :-( + if dgIndicator in Grid.Options then begin + Inc(Result, 21); + if dgColLines in Grid.Options then + // an additional line for the indicator + Inc(Result, Grid.GridLineWidth); + end; end; procedure TDbGrid_Resize(_Grid: TCustomDbGrid; _Options: TResizeOptionSet = []; @@ -3014,7 +3031,8 @@ Grid: TDbGridHack; i: Integer; TotalWidth: Integer; - sp: TdzIntegerArraySortProvider; + GridClientWidth: Integer; + MaxWidth: Integer; WidestIdx: Integer; Additional: Integer; begin @@ -3022,7 +3040,11 @@ SetLength(MinWidths, Grid.Columns.Count); TotalWidth := 0; for i := 0 to Grid.Columns.Count - 1 do begin - MinWidths[i] := Grid.Columns[i].DefaultWidth; + // Unfortunately DefaultWidth reads Width which we set later in this procedure + // and therefore DefaultWidth will increase every time this procedure is called. + // So we can only set MinWidths[] to _MinWidth. +// MinWidths[i] := Grid.Columns[i].DefaultWidth; + MinWidths[i] := _MinWidth; Inc(TotalWidth, MinWidths[i]); end; @@ -3030,24 +3052,35 @@ Additional := TDbGrid_CalcAdditionalWidth(_Grid); if dgColLines in Grid.Options then Inc(Additional, Grid.GridLineWidth * Grid.Columns.Count); - Inc(Additional, 4 * Grid.Columns.Count); // 2 pixels right and left, like in TStringGrid.DrawCell + Inc(Additional, DrawCellAdditionalPixels * 2 * Grid.Columns.Count); Inc(TotalWidth, Additional); - sp := TdzIntegerArraySortProvider.Create(MinWidths); - try - while TotalWidth > _Grid.ClientWidth do begin - WidestIdx := sp.GetRealPos(High(MinWidths)); - if MinWidths[WidestIdx] <= _MinWidth then + GridClientWidth := _Grid.ClientWidth; + if TotalWidth > GridClientWidth then begin + while TotalWidth > GridClientWidth do begin + // Get the widest column and reduce its size to the _MinWidth value. + // Repeat this until that widest column has reached _MinWidht or + // until all columns fit into the grid's ClientWidth + MaxWidth := MinWidths[0]; + WidestIdx := 0; + for i := 1 to High(MinWidths) do begin + if MinWidths[i] > MaxWidth then begin + MaxWidth := MinWidths[i]; + WidestIdx := i; + end; + end; + if MaxWidth <= _MinWidth then begin + // The widest column already has the minimum width Break; - Dec(TotalWidth, MinWidths[WidestIdx] - _MinWidth); + end; + Dec(TotalWidth, MaxWidth - _MinWidth); MinWidths[WidestIdx] := _MinWidth; - if TotalWidth < _Grid.ClientWidth then begin - MinWidths[WidestIdx] := MinWidths[WidestIdx] + (_Grid.ClientWidth - TotalWidth); + if TotalWidth < GridClientWidth then begin + // All columns now fit into the ClientWidth + // -> add any slack to the widest one and exit the loop + MinWidths[WidestIdx] := MinWidths[WidestIdx] + (GridClientWidth - TotalWidth); Break; end; - sp.Update; end; - finally - FreeAndNil(sp); end; end; TDbGrid_Resize(_Grid, _Options, MinWidths); @@ -3057,6 +3090,7 @@ var Col, Row: Integer; Grid: TDbGridHack; + GridCanvas: TCanvas; MinWidth: Integer; ColWidth: Integer; ColText: string; @@ -3071,6 +3105,7 @@ cw: Integer; begin Grid := TDbGridHack(_Grid); + GridCanvas := Grid.Canvas; MaxCol := Grid.ColCount - 1 - Grid.IndicatorOffset; MinCol := 0; SetLength(ColWidths, MaxCol + 1); @@ -3084,26 +3119,30 @@ MinWidth := _MinWidths[Col]; if not (roIgnoreHeader in _Options) then begin ColText := DBColumn.Title.Caption; - ColWidth := Grid.Canvas.TextWidth(ColText); + GridCanvas.Font := Grid.TitleFont; + ColWidth := GridCanvas.TextWidth(ColText); if ColWidth > MinWidth then MinWidth := ColWidth; end; for Row := FirstRow to MaxRow do begin ColText := Grid.GetEditText(Col + Grid.IndicatorOffset, Row); - ColWidth := Grid.Canvas.TextWidth(ColText); + GridCanvas.Font := Grid.Font; + ColWidth := GridCanvas.TextWidth(ColText); if ColWidth > MinWidth then MinWidth := ColWidth; end; if dgColLines in Grid.Options then Inc(MinWidth, Grid.GridLineWidth); - Inc(MinWidth, 4); // 2 pixels right and left, like in TStringGrid.DrawCell + Inc(MinWidth, DrawCellAdditionalPixels * 2); ColWidths[Col] := MinWidth; Inc(SumWidths, MinWidth); end; if roUseGridWidth in _Options then begin cw := Grid.ClientWidth; - if Grid.ScrollBars in [ssBoth, ssVertical] then - Dec(cw, GetSystemMetrics(SM_CXVSCROLL)); + // Apparently for a DbGrid the visibility of the vertical scroll bar is not reflected in + // the grid's Scrollbars property, so to be on the safe side, we assume that it is visible + // if Grid.ScrollBars in [ssBoth, ssVertical] then + Dec(cw, GetSystemMetrics(SM_CXVSCROLL)); if SumWidths < cw then begin Additional := (cw - SumWidths) div (MaxCol + 1); for Col := MinCol to MaxCol do begin @@ -3322,9 +3361,19 @@ raise EdzStatusBarNoMatchingPanel.CreateFmt(_('Could not find status bar panel with text "%s"'), [_Text]); end; -procedure SetControlEnabled(_Control: TControl; _Enabled: Boolean); +procedure TControls_SetEnabled(_Controls: array of TControl; _Enabled: Boolean; _Recursive: Boolean = False); +var + i: Integer; + ctrl: TControl; begin - TControl_SetEnabled(_Control, _Enabled); + for i := Low(_Controls) to High(_Controls) do begin + ctrl := _Controls[i]; + if _Recursive and (ctrl is TWinControl) then begin + TControl_SetEnabled(ctrl, _Enabled); + end else begin + ctrl.Enabled := _Enabled; + end; + end; end; procedure TControl_SetEnabled(_Control: TControl; _Enabled: Boolean); @@ -5532,8 +5581,6 @@ end; function TPopupMenu_AppendMenuItem(_pm: TPopupMenu; const _Caption: string): TMenuItem; overload; -const - NilEvent: TMethod = (Code: nil; Data: nil); begin Result := TPopupMenu_AppendMenuItem(_pm, _Caption, TNotifyEvent(NilEvent)); end; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tw...@us...> - 2024-04-06 15:10:10
|
Revision: 4228 http://sourceforge.net/p/gexperts/code/4228 Author: twm Date: 2024-04-06 15:10:08 +0000 (Sat, 06 Apr 2024) Log Message: ----------- updated to current dzlib version Modified Paths: -------------- trunk/ExternalSource/dzlib/t_NullableNumber.tpl trunk/ExternalSource/dzlib/u_dzClassUtils.pas trunk/ExternalSource/dzlib/u_dzConvertUtils.pas trunk/ExternalSource/dzlib/u_dzFileUtils.pas trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas trunk/ExternalSource/dzlib/u_dzMiscUtils.pas trunk/ExternalSource/dzlib/u_dzNullableExtended.pas trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas trunk/ExternalSource/dzlib/u_dzNullableTypesUtils.pas trunk/ExternalSource/dzlib/u_dzOsUtils.pas trunk/ExternalSource/dzlib/u_dzStringArrayUtils.pas trunk/ExternalSource/dzlib/u_dzStringUtils.pas trunk/ExternalSource/dzlib/u_dzTranslator.pas trunk/ExternalSource/dzlib/u_dzTypes.pas trunk/ExternalSource/dzlib/u_dzVclUtils.pas Modified: trunk/ExternalSource/dzlib/t_NullableNumber.tpl =================================================================== --- trunk/ExternalSource/dzlib/t_NullableNumber.tpl 2024-04-06 14:46:33 UTC (rev 4227) +++ trunk/ExternalSource/dzlib/t_NullableNumber.tpl 2024-04-06 15:10:08 UTC (rev 4228) @@ -21,9 +21,9 @@ {$IFNDEF __DZ_NULLABLE_NUMBER_TEMPLATE_SECOND_PASS__} type - _NULLABLE_NUMBER_ = record + TdzNullableNumber = record private - FIsValid: IInterface; + FIsValid: INullableTypesFlagInterface; FValue: _NULLABLE_TYPE_BASE_; public procedure Invalidate; @@ -45,55 +45,55 @@ function Abs: _NULLABLE_TYPE_BASE_; function Format(const _FormatStr: string): string; overload; function Format(const _FormatStr: string; const _Settings: TFormatSettings): string; overload; - class operator Negative(_a: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; - class operator Positive(_a: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; - class operator Inc(_a: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; - class operator Dec(_a: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; + class operator Negative(_a: TdzNullableNumber): TdzNullableNumber; + class operator Positive(_a: TdzNullableNumber): TdzNullableNumber; + class operator Inc(_a: TdzNullableNumber): TdzNullableNumber; + class operator Dec(_a: TdzNullableNumber): TdzNullableNumber; - class operator Add(_a, _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; - class operator Add(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): _NULLABLE_NUMBER_; - class operator Add(_a: _NULLABLE_TYPE_BASE_; _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; + class operator Add(_a, _b: TdzNullableNumber): TdzNullableNumber; + class operator Add(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): TdzNullableNumber; + class operator Add(_a: _NULLABLE_TYPE_BASE_; _b: TdzNullableNumber): TdzNullableNumber; - class operator Subtract(_a, _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; - class operator Subtract(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): _NULLABLE_NUMBER_; - class operator Subtract(_a: _NULLABLE_TYPE_BASE_; _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; + class operator Subtract(_a, _b: TdzNullableNumber): TdzNullableNumber; + class operator Subtract(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): TdzNullableNumber; + class operator Subtract(_a: _NULLABLE_TYPE_BASE_; _b: TdzNullableNumber): TdzNullableNumber; - class operator Multiply(_a, _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; - class operator Multiply(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): _NULLABLE_NUMBER_; - class operator Multiply(_a: _NULLABLE_TYPE_BASE_; _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; + class operator Multiply(_a, _b: TdzNullableNumber): TdzNullableNumber; + class operator Multiply(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): TdzNullableNumber; + class operator Multiply(_a: _NULLABLE_TYPE_BASE_; _b: TdzNullableNumber): TdzNullableNumber; - class operator Divide(_a, _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; - class operator Divide(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): _NULLABLE_NUMBER_; - class operator Divide(_a: _NULLABLE_TYPE_BASE_; _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; + class operator Divide(_a, _b: TdzNullableNumber): TdzNullableNumber; + class operator Divide(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): TdzNullableNumber; + class operator Divide(_a: _NULLABLE_TYPE_BASE_; _b: TdzNullableNumber): TdzNullableNumber; - class operator Implicit(_Value: _NULLABLE_TYPE_BASE_): _NULLABLE_NUMBER_; - class operator Implicit(_a: _NULLABLE_NUMBER_): _NULLABLE_TYPE_BASE_; + class operator Implicit(_Value: _NULLABLE_TYPE_BASE_): TdzNullableNumber; + class operator Implicit(_a: TdzNullableNumber): _NULLABLE_TYPE_BASE_; - class operator Explicit(const _s: string): _NULLABLE_NUMBER_; - class operator Explicit(_a: _NULLABLE_NUMBER_): string; + class operator Explicit(const _s: string): TdzNullableNumber; + class operator Explicit(_a: TdzNullableNumber): string; - class operator LessThan(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): Boolean; - class operator LessThanOrEqual(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): Boolean; - class operator GreaterThan(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): Boolean; - class operator GreaterThanOrEqual(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): Boolean; - class operator Equal(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): Boolean; - class operator NotEqual(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): Boolean; + class operator LessThan(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): Boolean; + class operator LessThanOrEqual(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): Boolean; + class operator GreaterThan(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): Boolean; + class operator GreaterThanOrEqual(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): Boolean; + class operator Equal(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): Boolean; + class operator NotEqual(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): Boolean; - class operator LessThan(_a, _b: _NULLABLE_NUMBER_): Boolean; - class operator LessThanOrEqual(_a, _b: _NULLABLE_NUMBER_): Boolean; - class operator GreaterThan(_a, _b: _NULLABLE_NUMBER_): Boolean; - class operator GreaterThanOrEqual(_a, _b: _NULLABLE_NUMBER_): Boolean; - class operator Equal(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_NUMBER_): Boolean; - class operator NotEqual(_a, _b: _NULLABLE_NUMBER_): Boolean; + class operator LessThan(_a, _b: TdzNullableNumber): Boolean; + class operator LessThanOrEqual(_a, _b: TdzNullableNumber): Boolean; + class operator GreaterThan(_a, _b: TdzNullableNumber): Boolean; + class operator GreaterThanOrEqual(_a, _b: TdzNullableNumber): Boolean; + class operator Equal(_a: TdzNullableNumber; _b: TdzNullableNumber): Boolean; + class operator NotEqual(_a, _b: TdzNullableNumber): Boolean; /// <summary> invalid values are considered smaller than any valid values /// and equal to each other </summary> - class function Compare(_a, _b: _NULLABLE_NUMBER_): Integer; static; + class function Compare(_a, _b: TdzNullableNumber): Integer; static; /// <summary> invalid values are considered equal to each other </summary> - class function IsSame(_a, _b: _NULLABLE_NUMBER_): Boolean; static; - class function Invalid: _NULLABLE_NUMBER_; static; - class function FromVariant(_a: Variant): _NULLABLE_NUMBER_; static; - class function FromStr(const _s: string): _NULLABLE_NUMBER_; static; + class function IsSame(_a, _b: TdzNullableNumber): Boolean; static; + class function Invalid: TdzNullableNumber; static; + class function FromVariant(_a: Variant): TdzNullableNumber; static; + class function FromStr(const _s: string): TdzNullableNumber; static; end; {$ENDIF __DZ_NULLABLE_NUMBER_TEMPLATE_SECOND_PASS__} @@ -113,29 +113,29 @@ {$IFDEF __DZ_NULLABLE_NUMBER_TEMPLATE_SECOND_PASS__} -{ _NULLABLE_NUMBER_ } +{ TdzNullableNumber } -class operator _NULLABLE_NUMBER_.Negative(_a: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Negative(_a: TdzNullableNumber): TdzNullableNumber; begin Result := -_a.Value; end; -class operator _NULLABLE_NUMBER_.Positive(_a: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Positive(_a: TdzNullableNumber): TdzNullableNumber; begin Result := _a.Value; end; -class operator _NULLABLE_NUMBER_.Inc(_a: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Inc(_a: TdzNullableNumber): TdzNullableNumber; begin Result := _a.Value + 1; end; -class operator _NULLABLE_NUMBER_.Dec(_a: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Dec(_a: TdzNullableNumber): TdzNullableNumber; begin Result := _a.Value - 1; end; -class operator _NULLABLE_NUMBER_.Add(_a, _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Add(_a, _b: TdzNullableNumber): TdzNullableNumber; begin if not _a.IsValid or not _b.IsValid then raise EInvalidValue.Create(_('Cannot add two nullable values if one of them is not valid.')); @@ -142,7 +142,7 @@ Result := _a.Value + _b.Value; end; -class operator _NULLABLE_NUMBER_.Add(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Add(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): TdzNullableNumber; begin if not _a.IsValid then raise EInvalidValue.Create(_('Cannot add to a nullable value if it is not valid')); @@ -149,7 +149,7 @@ Result := _a.Value + _b; end; -class operator _NULLABLE_NUMBER_.Add(_a: _NULLABLE_TYPE_BASE_; _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Add(_a: _NULLABLE_TYPE_BASE_; _b: TdzNullableNumber): TdzNullableNumber; begin if not _b.IsValid then raise EInvalidValue.Create(_('Cannot add to a nullable value if it is not valid')); @@ -156,7 +156,7 @@ Result := _a + _b.Value; end; -class operator _NULLABLE_NUMBER_.Subtract(_a, _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Subtract(_a, _b: TdzNullableNumber): TdzNullableNumber; begin if not _a.IsValid or not _b.IsValid then raise EInvalidValue.Create(_('Cannot subtract two nullable values if one of them is not valid')); @@ -163,7 +163,7 @@ Result := _a.Value - _b.Value; end; -class operator _NULLABLE_NUMBER_.Subtract(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Subtract(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): TdzNullableNumber; begin if not _a.IsValid then raise EInvalidValue.Create(_('Cannot subtract from a nullable value if it is not valid')); @@ -170,7 +170,7 @@ Result := _a.Value - _b; end; -class operator _NULLABLE_NUMBER_.Subtract(_a: _NULLABLE_TYPE_BASE_; _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Subtract(_a: _NULLABLE_TYPE_BASE_; _b: TdzNullableNumber): TdzNullableNumber; begin if not _b.IsValid then raise EInvalidValue.Create(_('Cannot subtract from a value if it is not valid')); @@ -177,7 +177,7 @@ Result := _a - _b.Value; end; -class operator _NULLABLE_NUMBER_.Multiply(_a, _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Multiply(_a, _b: TdzNullableNumber): TdzNullableNumber; begin if not _a.IsValid or not _b.IsValid then raise EInvalidValue.Create(_('Cannot multiply two nullable values if one of them is not valid')); @@ -184,7 +184,7 @@ Result := _a.Value * _b.Value; end; -class operator _NULLABLE_NUMBER_.Multiply(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Multiply(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): TdzNullableNumber; begin if not _a.IsValid then raise EInvalidValue.Create(_('Cannot multiply a nullable value if it is not valid')); @@ -191,7 +191,7 @@ Result := _a.Value * _b; end; -class operator _NULLABLE_NUMBER_.Multiply(_a: _NULLABLE_TYPE_BASE_; _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Multiply(_a: _NULLABLE_TYPE_BASE_; _b: TdzNullableNumber): TdzNullableNumber; begin if not _b.IsValid then raise EInvalidValue.Create(_('Cannot multiply a nullable value if it is not valid')); @@ -198,7 +198,7 @@ Result := _a * _b.Value; end; -class operator _NULLABLE_NUMBER_.Divide(_a, _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Divide(_a, _b: TdzNullableNumber): TdzNullableNumber; var Res: _NULLABLE_TYPE_BASE_; begin @@ -208,7 +208,7 @@ Result := Res; end; -class operator _NULLABLE_NUMBER_.Divide(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Divide(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): TdzNullableNumber; var Res: _NULLABLE_TYPE_BASE_; begin @@ -218,7 +218,7 @@ Result := Res; end; -class operator _NULLABLE_NUMBER_.Divide(_a: _NULLABLE_TYPE_BASE_; _b: _NULLABLE_NUMBER_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Divide(_a: _NULLABLE_TYPE_BASE_; _b: TdzNullableNumber): TdzNullableNumber; var Res: _NULLABLE_TYPE_BASE_; begin @@ -228,7 +228,7 @@ Result := Res; end; -procedure _NULLABLE_NUMBER_.AssignStr(const _s: string; const _FormatSettings: TFormatSettings); +procedure TdzNullableNumber.AssignStr(const _s: string; const _FormatSettings: TFormatSettings); begin if SameText('NULL', _s) then FIsValid := nil @@ -238,7 +238,7 @@ FIsValid := nil; end; -procedure _NULLABLE_NUMBER_.AssignStr(const _s: string; _DecSeparator: Char); +procedure TdzNullableNumber.AssignStr(const _s: string; _DecSeparator: Char); var FormatSettings: TFormatSettings; begin @@ -257,12 +257,12 @@ end; end; -procedure _NULLABLE_NUMBER_.AssignStr(const _s: string); +procedure TdzNullableNumber.AssignStr(const _s: string); begin AssignStr(_s, UserLocaleFormatSettings^); end; -class operator _NULLABLE_NUMBER_.Explicit(const _s: string): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Explicit(const _s: string): TdzNullableNumber; begin if TryStrToNumber(_s, Result.FValue, UserLocaleFormatSettings^) then Result.FIsValid := GetNullableTypesFlagInterface @@ -270,7 +270,7 @@ Result.FIsValid := nil; end; -class operator _NULLABLE_NUMBER_.Explicit(_a: _NULLABLE_NUMBER_): string; +class operator TdzNullableNumber.Explicit(_a: TdzNullableNumber): string; begin if _a.IsValid then Result := NumberToStr(_a.Value) @@ -278,28 +278,28 @@ Result := ''; end; -class function _NULLABLE_NUMBER_.FromVariant(_a: Variant): _NULLABLE_NUMBER_; +class function TdzNullableNumber.FromVariant(_a: Variant): TdzNullableNumber; begin Result.AssignVariant(_a); end; -class function _NULLABLE_NUMBER_.FromStr(const _s: string): _NULLABLE_NUMBER_; +class function TdzNullableNumber.FromStr(const _s: string): TdzNullableNumber; begin Result.AssignStr(_s); end; -class operator _NULLABLE_NUMBER_.Implicit(_Value: _NULLABLE_TYPE_BASE_): _NULLABLE_NUMBER_; +class operator TdzNullableNumber.Implicit(_Value: _NULLABLE_TYPE_BASE_): TdzNullableNumber; begin Result.FValue := _Value; Result.FIsValid := GetNullableTypesFlagInterface; end; -class operator _NULLABLE_NUMBER_.Implicit(_a: _NULLABLE_NUMBER_): _NULLABLE_TYPE_BASE_; +class operator TdzNullableNumber.Implicit(_a: TdzNullableNumber): _NULLABLE_TYPE_BASE_; begin Result := _a.Value; end; -procedure _NULLABLE_NUMBER_.AssignVariant(_a: Variant); +procedure TdzNullableNumber.AssignVariant(_a: Variant); begin if TryVar2Number(_a, FValue) then FIsValid := GetNullableTypesFlagInterface @@ -307,7 +307,7 @@ FIsValid := nil; end; -class function _NULLABLE_NUMBER_.Compare(_a, _b: _NULLABLE_NUMBER_): Integer; +class function TdzNullableNumber.Compare(_a, _b: TdzNullableNumber): Integer; begin if _a.IsValid then begin if _b.IsValid then @@ -320,7 +320,7 @@ Result := -1; end; -class function _NULLABLE_NUMBER_.IsSame(_a, _b: _NULLABLE_NUMBER_): Boolean; +class function TdzNullableNumber.IsSame(_a, _b: TdzNullableNumber): Boolean; begin if _a.IsValid then begin if _b.IsValid then @@ -335,12 +335,12 @@ end; end; -function _NULLABLE_NUMBER_.Dump: string; +function TdzNullableNumber.Dump: string; begin Result := ToString('<invalid>'); // do not translate end; -function _NULLABLE_NUMBER_.ToString(const _Default: string): string; +function TdzNullableNumber.ToString(const _Default: string): string; begin if IsValid then Result := NumberToStr(FValue) @@ -348,22 +348,22 @@ Result := _Default; end; -function _NULLABLE_NUMBER_.Abs: _NULLABLE_TYPE_BASE_; +function TdzNullableNumber.Abs: _NULLABLE_TYPE_BASE_; begin Result := System.Abs(Value); end; -function _NULLABLE_NUMBER_.Format(const _FormatStr: string): string; +function TdzNullableNumber.Format(const _FormatStr: string): string; begin Result := SysUtils.Format(_FormatStr, [Value]); end; -function _NULLABLE_NUMBER_.Format(const _FormatStr: string; const _Settings: TFormatSettings): string; +function TdzNullableNumber.Format(const _FormatStr: string; const _Settings: TFormatSettings): string; begin Result := SysUtils.Format(_FormatStr, [Value], _Settings); end; -function _NULLABLE_NUMBER_.ToVariant: Variant; +function TdzNullableNumber.ToVariant: Variant; begin if IsValid then Result := Value @@ -371,7 +371,7 @@ Result := Variants.Null; end; -function _NULLABLE_NUMBER_.GetValue(out _Value: _NULLABLE_TYPE_BASE_): Boolean; +function TdzNullableNumber.GetValue(out _Value: _NULLABLE_TYPE_BASE_): Boolean; begin Result := IsValid; if Result then @@ -378,67 +378,67 @@ _Value := FValue; end; -procedure _NULLABLE_NUMBER_.Invalidate; +procedure TdzNullableNumber.Invalidate; begin FIsValid := nil; end; -function _NULLABLE_NUMBER_.IsValid: Boolean; +function TdzNullableNumber.IsValid: Boolean; begin Result := FIsValid <> nil; end; -class operator _NULLABLE_NUMBER_.LessThan(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): Boolean; +class operator TdzNullableNumber.LessThan(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): Boolean; begin Result := CompareValue(_a.Value, _b) < 0; end; -class operator _NULLABLE_NUMBER_.LessThanOrEqual(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): Boolean; +class operator TdzNullableNumber.LessThanOrEqual(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): Boolean; begin Result := CompareValue(_a.Value, _b) <= 0; end; -class operator _NULLABLE_NUMBER_.GreaterThan(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): Boolean; +class operator TdzNullableNumber.GreaterThan(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): Boolean; begin Result := CompareValue(_a.Value, _b) > 0; end; -class operator _NULLABLE_NUMBER_.GreaterThanOrEqual(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): Boolean; +class operator TdzNullableNumber.GreaterThanOrEqual(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): Boolean; begin Result := CompareValue(_a.Value, _b) >= 0; end; -class operator _NULLABLE_NUMBER_.Equal(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): Boolean; +class operator TdzNullableNumber.Equal(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): Boolean; begin Result := SameValue(_a.Value, _b); end; -class operator _NULLABLE_NUMBER_.NotEqual(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_TYPE_BASE_): Boolean; +class operator TdzNullableNumber.NotEqual(_a: TdzNullableNumber; _b: _NULLABLE_TYPE_BASE_): Boolean; begin Result := not SameValue(_a.Value, _b); end; -class operator _NULLABLE_NUMBER_.LessThan(_a, _b: _NULLABLE_NUMBER_): Boolean; +class operator TdzNullableNumber.LessThan(_a, _b: TdzNullableNumber): Boolean; begin Result := (Compare(_a, _b) < 0); end; -class operator _NULLABLE_NUMBER_.LessThanOrEqual(_a, _b: _NULLABLE_NUMBER_): Boolean; +class operator TdzNullableNumber.LessThanOrEqual(_a, _b: TdzNullableNumber): Boolean; begin Result := (Compare(_a, _b) <= 0); end; -class operator _NULLABLE_NUMBER_.GreaterThan(_a, _b: _NULLABLE_NUMBER_): Boolean; +class operator TdzNullableNumber.GreaterThan(_a, _b: TdzNullableNumber): Boolean; begin Result := (Compare(_a, _b) > 0); end; -class operator _NULLABLE_NUMBER_.GreaterThanOrEqual(_a, _b: _NULLABLE_NUMBER_): Boolean; +class operator TdzNullableNumber.GreaterThanOrEqual(_a, _b: TdzNullableNumber): Boolean; begin Result := (Compare(_a, _b) >= 0); end; -class operator _NULLABLE_NUMBER_.Equal(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_NUMBER_): Boolean; +class operator TdzNullableNumber.Equal(_a: TdzNullableNumber; _b: TdzNullableNumber): Boolean; begin if _a.IsValid then begin if _b.IsValid then begin @@ -459,17 +459,17 @@ end; end; -class operator _NULLABLE_NUMBER_.NotEqual(_a: _NULLABLE_NUMBER_; _b: _NULLABLE_NUMBER_): Boolean; +class operator TdzNullableNumber.NotEqual(_a: TdzNullableNumber; _b: TdzNullableNumber): Boolean; begin Result := not (_a = _b); end; -class function _NULLABLE_NUMBER_.Invalid: _NULLABLE_NUMBER_; +class function TdzNullableNumber.Invalid: TdzNullableNumber; begin Result.Invalidate; end; -function _NULLABLE_NUMBER_.Value: _NULLABLE_TYPE_BASE_; +function TdzNullableNumber.Value: _NULLABLE_TYPE_BASE_; begin if not IsValid then raise EInvalidValue.CreateFmt(_('%s is invalid'), [_NULLABLE_TYPE_NAME_]); Modified: trunk/ExternalSource/dzlib/u_dzClassUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzClassUtils.pas 2024-04-06 14:46:33 UTC (rev 4227) +++ trunk/ExternalSource/dzlib/u_dzClassUtils.pas 2024-04-06 15:10:08 UTC (rev 4228) @@ -410,7 +410,7 @@ function TIniFile_TryReadFloat(const _Filename: string; const _Section, _Ident: string; out _Value: Extended): Boolean; overload; function TIniFile_TryReadFloat(const _Filename: string; const _Section, _Ident: string; out _Value: Double): Boolean; overload; function TIniFile_TryReadFloat(const _Filename: string; const _Section, _Ident: string; out _Value: Single): Boolean; overload; -function TIniFile_ReadFloat(_Ini: TCustomIniFile; const _Section, _Ident: string; out _Value: Extended): Boolean; overload deprecated; // use TryReadFloat instead +function TIniFile_ReadFloat(_Ini: TCustomIniFile; const _Section, _Ident: string; out _Value: Extended): Boolean; overload; deprecated; // use TryReadFloat instead function TIniFile_ReadFloat(_Ini: TCustomIniFile; const _Section, _Ident: string): Extended; overload; function TIniFile_ReadFloat(const _Filename: string; const _Section, _Ident: string): Extended; overload; Modified: trunk/ExternalSource/dzlib/u_dzConvertUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzConvertUtils.pas 2024-04-06 14:46:33 UTC (rev 4227) +++ trunk/ExternalSource/dzlib/u_dzConvertUtils.pas 2024-04-06 15:10:08 UTC (rev 4228) @@ -290,7 +290,6 @@ /// variable DecimalSeparator in SysUtils. </summary> function TryStr2Float(const _s: string; out _flt: Extended; _DecSeparator: Char = '.'): Boolean; overload; -{$IF SizeOf(Extended) <> SizeOf(Double)} ///<summary> /// tries to convert a string to a float, returns false if it fails /// @param s is the string to convert @@ -301,7 +300,6 @@ /// NOTE: This is not thread safe in Delphi 6 because there it changes the global /// variable DecimalSeparator in SysUtils. </summary> function TryStr2Float(const _s: string; out _flt: Double; _DecSeparator: Char = '.'): Boolean; overload; -{$IFEND} function TryStr2Float(const _s: string; out _flt: Single; _DecSeparator: Char = '.'): Boolean; overload; ///<summary> @@ -455,6 +453,9 @@ function Bool2Str(_b: Boolean): string; type + TBitGrouping = (bgNone, bgNibble, bgByte, bgWord, bgLongWord); + +type TBitNumber64 = 0..63; TByteNumber64 = 0..7; @@ -480,6 +481,7 @@ class function Create(_Value: TValue): TBits64; static; class function AllSet: TBits64; static; class function NoneSet: TBits64; static; + function Dump: string; procedure Init(_Value: TValue); function IsBitSet(_BitNo: TBitNumber): Boolean; procedure SetBit(_BitNo: TBitNumber; _BitValue: Boolean); @@ -492,7 +494,7 @@ function Value: TValue; function GetByte(_ByteNo: TByteNumber): Byte; procedure SetByte(_ByteNo: TByteNumber; _Value: Byte); - function AsString: string; + function AsString(_Grouped: TBitGrouping = bgNone): string; class operator BitwiseAnd(_a, _b: TBits64): TBits64; class operator BitwiseOr(_a, _b: TBits64): TBits64; class operator BitwiseXor(_a, _b: TBits64): TBits64; @@ -528,6 +530,7 @@ class function Create(_Value: TValue): TBits32; static; class function AllSet: TBits32; static; class function NoneSet: TBits32; static; + function Dump: string; procedure Init(_Value: TValue); function IsBitSet(_BitNo: TBitNumber): Boolean; procedure SetBit(_BitNo: TBitNumber; _BitValue: Boolean); @@ -540,7 +543,7 @@ function Value: TValue; function GetByte(_ByteNo: TByteNumber): Byte; procedure SetByte(_ByteNo: TByteNumber; _Value: Byte); - function AsString: string; + function AsString(_Grouped: TBitGrouping = bgNone): string; class operator BitwiseAnd(_a, _b: TBits32): TBits32; class operator BitwiseOr(_a, _b: TBits32): TBits32; class operator BitwiseXor(_a, _b: TBits32): TBits32; @@ -576,6 +579,7 @@ class function Create(_Value: TValue): TBits16; static; class function AllSet: TBits16; static; class function NoneSet: TBits16; static; + function Dump: string; procedure Init(_Value: TValue); function IsBitSet(_BitNo: TBitNumber): Boolean; function IsAnyBitSet: Boolean; @@ -589,7 +593,7 @@ function Value: TValue; function GetByte(_ByteNo: TByteNumber): Byte; procedure SetByte(_ByteNo: TByteNumber; _Value: Byte); - function AsString: string; + function AsString(_Grouped: TBitGrouping = bgNone): string; class operator BitwiseAnd(_a, _b: TBits16): TBits16; class operator BitwiseOr(_a, _b: TBits16): TBits16; class operator BitwiseXor(_a, _b: TBits16): TBits16; @@ -623,6 +627,7 @@ class function Create(_Value: TValue): TBits8; static; class function AllSet: TBits8; static; class function NoneSet: TBits8; static; + function Dump: string; procedure Init(_Value: TValue); function IsBitSet(_BitNo: TBitNumber): Boolean; function IsAnyBitSet: Boolean; @@ -636,7 +641,7 @@ function Value: TValue; function GetByte(_ByteNo: TByteNumber): Byte; procedure SetByte(_ByteNo: TByteNumber; _Value: Byte); - function AsString: string; + function AsString(_Grouped: TBitGrouping = bgNone): string; // according to the documentation: // > For a logical operator and a bitwise operator using the same symbol, // > the logical operator is used only when the operands are booleans. @@ -1241,7 +1246,6 @@ {$IFEND} end; -{$IF SizeOf(Extended) <> SizeOf(Double)} function TryStr2Float(const _s: string; out _flt: Double; _DecSeparator: Char = '.'): Boolean; var flt: Extended; @@ -1250,7 +1254,6 @@ if Result then _flt := flt; end; -{$IFEND} function TryStr2Float(const _s: string; out _flt: Single; _DecSeparator: Char = '.'): Boolean; var @@ -1507,14 +1510,42 @@ Bytes[_ByteNo] := _Value; end; -function TBits64.AsString: string; +function TBits64.Dump: string; +begin + Result := AsString(bgByte); +end; + +procedure GroupBits(var _s: string; _Grouped: TBitGrouping); var i: Integer; + Step: Integer; begin + case _Grouped of + bgNibble: Step := 4; + bgByte: Step := 8; + bgWord: Step := 16; + bgLongWord: Step := 32; + else + Step := 64; + end; + + i := Length(_s) - Step + 1; + while i > 1 do begin + Insert(' ', _s, i); + Dec(i, Step); + end; +end; + +function TBits64.AsString(_Grouped: TBitGrouping = bgNone): string; +var + i: Integer; +begin Result := DupeString('0', Bits); - for i := High downto Low do + for i := High downto Low do begin if IsBitSet(i) then Result[Bits - i] := '1'; + end; + GroupBits(Result, _Grouped); end; class operator TBits64.BitwiseAnd(_a, _b: TBits64): TBits64; @@ -1549,14 +1580,21 @@ Result.Init($FFFFFFFF); end; -function TBits32.AsString: string; +function TBits32.Dump: string; +begin + Result := AsString(bgByte); +end; + +function TBits32.AsString(_Grouped: TBitGrouping = bgNone): string; var i: Integer; begin Result := DupeString('0', Bits); - for i := High downto Low do + for i := High downto Low do begin if IsBitSet(i) then Result[Bits - i] := '1'; + end; + GroupBits(Result, _Grouped); end; class function TBits32.Create(_Value: TValue): TBits32; @@ -1662,14 +1700,21 @@ Result.Init($FFFF); end; -function TBits16.AsString: string; +function TBits16.Dump: string; +begin + Result := AsString(bgByte); +end; + +function TBits16.AsString(_Grouped: TBitGrouping = bgNone): string; var i: Integer; begin Result := DupeString('0', Bits); - for i := High downto Low do + for i := High downto Low do begin if IsBitSet(i) then Result[Bits - i] := '1'; + end; + GroupBits(Result, _Grouped); end; class function TBits16.Create(_Value: TValue): TBits16; @@ -1775,14 +1820,21 @@ { TBits8 } -function TBits8.AsString: string; +function TBits8.Dump: string; +begin + Result := AsString(bgByte); +end; + +function TBits8.AsString(_Grouped: TBitGrouping = bgNone): string; var i: Integer; begin Result := DupeString('0', Bits); - for i := High downto Low do + for i := High downto Low do begin if IsBitSet(i) then Result[Bits - i] := '1'; + end; + GroupBits(Result, _Grouped); end; class function TBits8.AllSet: TBits8; @@ -1990,6 +2042,21 @@ Result := True; end; +{$IFDEF DEBUG} +procedure AssertBitsDump; +var + bits64: TBits64; + bits32: TBits32; + bits16: TBits16; + bits8: TBits8; +begin + bits64.Dump; + bits32.Dump; + bits16.Dump; + bits8.Dump; +end; +{$ENDIF DEBUG} + initialization {$IF Declared(TFormatSettings)} DZ_FORMAT_DECIMAL_POINT := u_dzStringUtils.GetUserDefaultLocaleSettings; @@ -1996,8 +2063,11 @@ DZ_FORMAT_DECIMAL_POINT.DecimalSeparator := '.'; DZ_FORMAT_DECIMAL_POINT.ThousandSeparator := #0; {$IFEND} - +{$IFDEF DEBUG} Assert(AssertYNStringLength); Assert(AssertSwap32); Assert(AssertBitReverse32); + + AssertBitsDump; +{$ENDIF DEBUG} end. Modified: trunk/ExternalSource/dzlib/u_dzFileUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzFileUtils.pas 2024-04-06 14:46:33 UTC (rev 4227) +++ trunk/ExternalSource/dzlib/u_dzFileUtils.pas 2024-04-06 15:10:08 UTC (rev 4228) @@ -1270,7 +1270,7 @@ /// if Rewrite fails, File is zeroed /// @raise exception, if rewrite fails </summary> procedure TextFile_AssignAndRewrite(var _File: TextFile; const _Filename: string); -function TextFile_IsOpen(const _File: TextFile): Boolean; +function TextFile_IsOpen(var _File: TextFile): Boolean; procedure TextFile_Close(var _File: TextFile); implementation @@ -1981,6 +1981,15 @@ end; end; +{$if not declared(MOVEFILE_WRITE_THROUGH)} +const + MOVEFILE_WRITE_THROUGH = $00000008; +{$ifend} +{$if not declared(MOVEFILE_FAIL_IF_NOT_TRACKABLE)} +const + MOVEFILE_FAIL_IF_NOT_TRACKABLE = $00000020; +{$ifend} + class function TFileSystem.MoveFileEx(const _Source, _Dest: string; _Flags: TMoveFileExFlagSet; _ErrorHandling: TErrorHandlingEnum = ehRaiseException): Boolean; var @@ -3418,7 +3427,7 @@ end; end; -function TextFile_IsOpen(const _File: TextFile): Boolean; +function TextFile_IsOpen(var _File: TextFile): Boolean; begin Result := (TTextRec(_File).Mode <> 0); end; Modified: trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2024-04-06 14:46:33 UTC (rev 4227) +++ trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2024-04-06 15:10:08 UTC (rev 4228) @@ -128,52 +128,34 @@ function GetRgbBrightness(_Red, _Green, _Blue: Byte; _Channel: TRgbBrightnessChannelEnum): Byte; function CalcBytesPerPixel(_PixelFormat: TPixelFormat): Integer; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function CalcBytesPerLine(_Width, _BytesPerPixel: Integer): Integer; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + function CalcBytesPerLine(_Width: Integer; _PixelFormat: TPixelFormat): Integer; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + function CalcBytesPerLine(_Width: Integer; _bmp: TBitmap): Integer; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} procedure IncPtr(var _Ptr: Pointer; _Offset: IntPtr); -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function AddToPtr(const _Ptr: Pointer; _Offset: IntPtr): Pointer; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function PtrDiff(const _Ptr1, _Ptr2: Pointer): IntPtr; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function TdzRgbTriple_GetFastLuminance(const _Triple: TdzRgbTriple): Byte; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} procedure TdzRgbTriple_SetColor(var _Triple: TdzRgbTriple; _Color: TColor); -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function GetFastLuminance(const _Red, _Green, _Blue: Byte): Byte; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} type TdzRgbTripleArray = packed array[0..MaxInt div SizeOf(TdzRgbTriple) - 1] of TdzRgbTriple; @@ -206,15 +188,11 @@ ///<summary> Returns the bounding box of the active clipping region </summary> function TCanvas_GetClipRect(_Canvas: TCanvas): TRect; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> Sets a clipping rect, returns true, if the region is not empty, false if it is empty </summary> function TCanvas_SetClipRect(_Canvas: TCanvas; _Rect: TRect): Boolean; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} type TDrawTextFlags = ( @@ -267,36 +245,24 @@ /// If dtfBottomSingle or dtfVCenterSingle is specified, the return value is the offset /// from Rect.top to the bottom of the drawn text. </summary> function TCanvas_DrawText(_Canvas: TCanvas; const _Text: string; var _Rect: TRect; _Flags: TDrawTextFlagSet): Integer; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function TCanvas_DrawTextSingleLine(_Canvas: TCanvas; const _Text: string; var _Rect: TRect; _HAlign: TDrawTextHorizontalAlignment; _VAlign: TDrawTextVerticalAlignment; _Flags: TDrawTextFlagSetNoAlign): Integer; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} procedure TCanvas_DrawLine(_cnv: TCanvas; _x1, _y1, _x2, _y2: Integer); overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} procedure TCanvas_DrawLine(_cnv: TCanvas; _pnt1, _pnt2: TPoint); overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} procedure TCanvas_DrawHorizontalLine(_cnv: TCanvas; _x1, _x2, _y: Integer); -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} procedure TCanvas_DrawVerticalLine(_cnv: TCanvas; _x, _y1, _y2: Integer); -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> calls Windows.SaveDC and returns an interface which will automatically call /// Windows.RestoreDC when destroyed </summary> @@ -311,95 +277,70 @@ /// @param Tip is the coordinates of the vertex point /// @param Height is the height of the triangle, if negative, the triangle is painted upside down </summary> procedure TCanvas_DrawTriangle(_Canvas: TCanvas; _Tip: TPoint; _Height: Integer); -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function TCanvas_BitBlt(_Canvas: TCanvas; _DestPos: TPoint; _Size: TPoint; _Src: TBitmap; _SrcPos: TPoint; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function TCanvas_BitBlt(_Canvas: TCanvas; _DestPos: TPoint; _Size: TPoint; _Src: TBitmap; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function TCanvas_BitBlt(_Canvas: TCanvas; _DestRect: TRect; _Src: TBitmap; _SrcPos: TPoint; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function TCanvas_BitBlt(_Canvas: TCanvas; _DestPos: TPoint; _Src: TBitmap; _SrcPos: TPoint; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function TCanvas_BitBlt(_Canvas: TCanvas; _DestPos: TPoint; _Src: TBitmap; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> abbreviation for StretchBlt that takes TCanvas and TPoint values. </summary> function dzStretchBlt(_DestCnv: TCanvas; _DestTopLeft: TPoint; _DestSize: TPoint; _SrcCnv: TCanvas; _SrcTopLeft: TPoint; _SrcSize: TPoint; _Rop: DWORD = SRCCOPY): BOOL; overload; -{$IFDEF SUPPORTS_INLINE}inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function dzStretchBlt(_DestCnv: TCanvas; _DestLeft, _DestTop: Integer; _DestSize: TPoint; _SrcCnv: TCanvas; _SrcTopLeft: TPoint; _SrcSize: TPoint; _Rop: DWORD = SRCCOPY): BOOL; overload; -{$IFDEF SUPPORTS_INLINE}inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> abbreviation for StretchBlt that takes TCanvas, TBitmap and TPoint values. </summary> function dzStretchBlt(_DestCnv: TCanvas; _DestTopLeft: TPoint; _DestSize: TPoint; _SrcBmp: TBitmap; _SrcTopLeft: TPoint; _SrcSize: TPoint; _Rop: DWORD = SRCCOPY): BOOL; overload; -{$IFDEF SUPPORTS_INLINE}inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> abbreviation for StretchBlt that takes TCanvas, TBitmap and TPoint values. </summary> function dzStretchBlt(_DestCnv: TCanvas; _DestLeft, _DestTop: Integer; _DestSize: TPoint; _SrcBmp: TBitmap; _SrcTopLeft: TPoint; _SrcSize: TPoint; _Rop: DWORD = SRCCOPY): BOOL; overload; -{$IFDEF SUPPORTS_INLINE}inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> abbreviation for StretchBlt that takes two TBitmap and TPoint values. </summary> function dzStretchBlt(_DestBmp: TBitmap; _DestTopLeft: TPoint; _DestSize: TPoint; _SrcBmp: TBitmap; _SrcTopLeft: TPoint; _SrcSize: TPoint; _Rop: DWORD = SRCCOPY): BOOL; overload; -{$IFDEF SUPPORTS_INLINE}inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> abbreviation for StretchBlt that takes TRect </summary> function dzStretchBlt(_DestHandle: Hdc; _DestRect: TRect; _SrcHandle: Hdc; _SrcRect: TRect; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> abbreviation for StretchBlt that takes TCanvas and TRect </summary> function dzStretchBlt(_DestCnv: TCanvas; _DestRect: TRect; _SrcHandle: Hdc; _SrcRect: TRect; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> abbreviation for StretchBlt that takes TRect and TBitmap </summary> function dzStretchBlt(_DestHandle: Hdc; _DestRect: TRect; _Src: TBitmap; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> abbreviation for StretchBlt that takes TCanvas, TRect and TBitmap </summary> function dzStretchBlt(_DestCnv: TCanvas; _DestRect: TRect; _Src: TBitmap; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> /// Abbreviation for StretchBlt that takes two TBitmap, resizes and keeps the spect ratio, @@ -407,89 +348,64 @@ /// The original stretchmode and the brush origin are preserved. /// https://msdn.microsoft.com/en-us/library/windows/desktop/dd145089(v=vs.85).aspx </summary> function dzStretchBlt(_DestBmp, _SrcBmp: TBitmap; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> abbreviation for BitBlt that takes TPoint / TRect and TBitmap parameters </summary> function dzBitBlt(_DestHandle: Hdc; _DestPos: TPoint; _Size: TPoint; _Src: TBitmap; _SrcPos: TPoint; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function dzBitBlt(_DestHandle: Hdc; _DestPos: TPoint; _Size: TPoint; _Src: TBitmap; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function dzBitBlt(_DestHandle: Hdc; _DestRect: TRect; _Src: TBitmap; _SrcPos: TPoint; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function dzBitBlt(_DestHandle: Hdc; _DestPos: TPoint; _Src: TBitmap; _SrcPos: TPoint; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function dzBitBlt(_DestHandle: Hdc; _DestPos: TPoint; _Src: TBitmap; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} procedure TBitmap_SetSize(_bmp: TBitmap; _Width, _Height: Integer); -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function TBitmap_BitBlt(_DestBmp: TBitmap; _DestPos: TPoint; _Size: TPoint; _Src: TBitmap; _SrcPos: TPoint; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + function TBitmap_BitBlt(_DestBmp: TBitmap; _DestPos: TPoint; _Size: TPoint; _Src: TBitmap; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + function TBitmap_BitBlt(_DestBmp: TBitmap; _DestRect: TRect; _Src: TBitmap; _SrcPos: TPoint; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + function TBitmap_BitBlt(_DestBmp: TBitmap; _DestPos: TPoint; _Src: TBitmap; _SrcPos: TPoint; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + function TBitmap_BitBlt(_DestBmp: TBitmap; _DestPos: TPoint; _Src: TBitmap; _Rop: DWORD = SRCCOPY): LongBool; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> load a jpeg file and assign it to the bitmap </summary> procedure TBitmap_LoadJpg(_bmp: TBitmap; const _JpgFn: string); overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + {$IF Declared(TBitmap32)} procedure TBitmap_LoadJpg(_bmp: TBitmap32; const _JpgFn: string); overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} {$IFEND} ///<summary> save a bitmap as a jpeg file </summary> procedure TBitmap_SaveJpg(_bmp: TBitmap; const _JpgFn: string); -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> /// Assign a buffer containg a bitmap in BGR 8 format to the TBitmap </summary> @@ -547,24 +463,19 @@ ///<summary> /// converts a pf24bit or pf32bit monochrome bitmap to a pf8bit monochrome bitmap </summary> function TBitmap_MonoToMono8(_bmp: TBitmap): TBitmap; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + procedure TBitmap_MonoToMono8(_InBmp, _OutBmp: TBitmap); overload; ///<summary> /// Makes the given bitmap pf8Bit grayscale </summary> procedure TBitmap_MakeMono8(_bmp: TBitmap); -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> /// Create an empty Mono8 TBitmap </summary> function TBitmap_CreateMono8: TBitmap; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> /// Calculates the positive y coordinate for the given x coordinate for an ellipse @@ -574,9 +485,7 @@ /// @param y returns the y coordinate if it can be calculated /// @returns true if the x coordinate was inside the ellipse, false if not </summary> function TryCalcEllipsePoint(_a, _b, _x: Extended; out _y: Extended): Boolean; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> /// Calculates both y coordinates for the given x coordinate for an ellipse @@ -587,9 +496,7 @@ /// @param y1, y2 return the y coordinates if they can be calculated /// @returns true if the x coordinate was inside the ellipse, false if not </summary> function TryCalcEllipsePoints(_x0, _y0, _a, _b, _x: Extended; out _y1, _y2: Extended): Boolean; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> /// Blurs a rectangular area in the given bitmap. @@ -615,9 +522,7 @@ procedure TBitmap8_Sharpen(_SrcBmp, _DstBmp: TBitmap; _Alpha: Single); overload; procedure TBitmap24_Sharpen(_SrcBmp, _DstBmp: TBitmap; _Alpha: Single); overload; procedure TBitmap_Sharpen(_SrcBmp, _DstBmp: TBitmap; _Alpha: Single); overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> /// Sharpens a bitmap, pixelformat must be pf24bit @@ -629,9 +534,7 @@ procedure TBitmap8_Sharpen(_SrcBmp, _DstBmp: TBitmap; const _AlphaMap: TSingleMatrix); overload; procedure TBitmap24_Sharpen(_SrcBmp, _DstBmp: TBitmap; const _AlphaMap: TSingleMatrix); overload; procedure TBitmap_Sharpen(_SrcBmp, _DstBmp: TBitmap; const _AlphaMap: TSingleMatrix); overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> /// Balances the brightness of the SrcBmp bitmap and returns the result in the DstBmp bitmap @@ -784,10 +687,8 @@ FHighCutOff: Byte; FDivisor: Integer; procedure StretchColor(var _Color: Byte); -{$IFDEF SUPPORTS_INLINE} - inline; -{$ENDIF} - public +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + public constructor Create(_LowCutoff, _HighCutoff: Byte); procedure FilterCallback(_x, _y: Integer; var _Pixel: TdzRgbTriple); overload; procedure FilterCallback(_x, _y: Integer; var _Pixel: Byte); overload; @@ -798,10 +699,8 @@ private FMoveBy: Integer; procedure MoveColor(var _Color: Byte); -{$IFDEF SUPPORTS_INLINE} - inline; -{$ENDIF} - public +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} + public constructor Create(_MoveBy: Integer); procedure FilterCallback(_x, _y: Integer; var _Pixel: TdzRgbTriple); overload; procedure FilterCallback(_x, _y: Integer; var _Pixel: Byte); overload; @@ -815,15 +714,11 @@ ///<summary> // Calculates the (perceived) brightness of an RGB color value (luminance) </summary> function ColorBrightness(_Red, _Green, _Blue: Byte): Byte; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> // Calculates the (perceived) brightness of a TColor value (luminance) </summary> function ColorBrightness(_Color: TColor): Byte; overload; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> /// @returns clWhite or clBlack depending on the brightness (luminance) of the color </summary> @@ -835,7 +730,7 @@ ///<summary> /// @param Hue is a value between 0 and 1 </summary> function RainbowColor(_Hue: Double): TColor; overload; -{{*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} ///<summary> /// @param Hue is a value between 0 and 1 </summary> @@ -845,18 +740,17 @@ ///<summary> /// @param Brightness is a grayscale value </summary> function RainbowColor(_Brightness: Byte): TColor; overload; -{{*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} procedure RainbowColor(_Brightness: Byte; out _Red, _Green, _Blue: Byte); overload; -{{*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} procedure RainbowColor(_Brightness: Byte; out _Pixel: TdzRgbTriple); overload; -{{*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} function RainbowColor(_MinHue, _MaxHue, _Hue: Integer): TColor; overload; -{{*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} - function TryStr2Color(const _s: string; out _Color: TColor): Boolean; function TPicture_TryLoadMatchingFile(_pic: TPicture; const _FileMask: string): Boolean; @@ -876,9 +770,7 @@ u_dzFileUtils; function _(const _s: string): string; -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} begin Result := dzDGetText(_s, 'dzlib'); end; @@ -1708,9 +1600,7 @@ {$ENDIF} procedure TBitmap_SetSize(_bmp: TBitmap; _Width, _Height: Integer); -{$IFDEF SUPPORTS_INLINE} -inline; -{$ENDIF} +{(*}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{*)} begin {$IFDEF SUPPPORTS_BITMAP_SETSIZE} _bmp.SetSize(_Width, _Height); @@ -2614,14 +2504,16 @@ BytesPerLine: Integer; begin Assert(Assigned(_SrcBmp)); + Assert(Assigned(_DstBmp)); _SrcBmp.PixelFormat := pf24bit; - _DstBmp.PixelFormat := pf24bit; w := _SrcBmp.Width; h := _SrcBmp.Height; + + _DstBmp.PixelFormat := pf24bit; TBitmap_SetSize(_DstBmp, w, h); - if h = 0 then + if (h = 0) or (w = 0) then Exit; //==> BytesPerLine := ((w * 8 * BytesPerPixel + 31) and not 31) div 8; @@ -2660,16 +2552,17 @@ BytesPerLine: Integer; begin Assert(Assigned(_SrcBmp)); + Assert(Assigned(_DstBmp)); _SrcBmp.PixelFormat := pf8bit; + w := _SrcBmp.Width; + h := _SrcBmp.Height; _DstBmp.Assign(nil); _DstBmp.PixelFormat := pf8bit; - w := _SrcBmp.Width; - h := _SrcBmp.Height; _DstBmp.Palette := MakeGrayPalette; TBitmap_SetSize(_DstBmp, w, h); - if h = 0 then + if (h = 0) or (w = 0) then Exit; //==> BytesPerLine := ((w * 8 * BytesPerPixel + 31) and not 31) div 8; Modified: trunk/ExternalSource/dzlib/u_dzMiscUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzMiscUtils.pas 2024-04-06 14:46:33 UTC (rev 4227) +++ trunk/ExternalSource/dzlib/u_dzMiscUtils.pas 2024-04-06 15:10:08 UTC (rev 4228) @@ -271,17 +271,22 @@ function HKeyToString(_HKey: HKey): string; begin - case _HKey of - HKEY_CLASSES_ROOT: Result := 'HKEY_CLASSES_ROOT'; // do not translate - HKEY_CURRENT_USER: Result := 'HKEY_CURRENT_USER'; // do not translate - HKEY_LOCAL_MACHINE: Result := 'HKEY_LOCAL_MACHINE'; // do not translate - HKEY_USERS: Result := 'HKEY_USERS'; // do not translate - HKEY_PERFORMANCE_DATA: Result := 'HKEY_PERFORMANCE_DATA'; // do not translate - HKEY_CURRENT_CONFIG: Result := 'HKEY_CURRENT_CONFIG'; // do not translate - HKEY_DYN_DATA: Result := 'HKEY_DYN_DATA'; // do not translate + if _HKey = HKEY_CLASSES_ROOT then + Result := 'HKEY_CLASSES_ROOT' // do not translate + else if _HKey = HKEY_CURRENT_USER then + Result := 'HKEY_CURRENT_USER' // do not translate + else if _HKey = HKEY_LOCAL_MACHINE then + Result := 'HKEY_LOCAL_MACHINE' // do not translate + else if _HKey = HKEY_USERS then + Result := 'HKEY_USERS' // do not translate + else if _HKey = HKEY_PERFORMANCE_DATA then + Result := 'HKEY_PERFORMANCE_DATA' // do not translate + else if _HKey = HKEY_CURRENT_CONFIG then + Result := 'HKEY_CURRENT_CONFIG' // do not translate + else if _HKey = HKEY_DYN_DATA then + Result := 'HKEY_DYN_DATA' // do not translate else Result := Format(_('unknown Registry Root Key %x'), [_HKey]); - end; end; function RegDataTypeToString(_DataType: TRegDataType): string; Modified: trunk/ExternalSource/dzlib/u_dzNullableExtended.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzNullableExtended.pas 2024-04-06 14:46:33 UTC (rev 4227) +++ trunk/ExternalSource/dzlib/u_dzNullableExtended.pas 2024-04-06 15:10:08 UTC (rev 4228) @@ -28,7 +28,7 @@ {$INCLUDE 't_NullableNumber.tpl'} type - TNullableExtended = _NULLABLE_NUMBER_; + TNullableExtended = TdzNullableNumber; TdzNullableExtended = TNullableExtended deprecated; {$ENDIF DELPHI2007_UP} @@ -39,6 +39,18 @@ {$INCLUDE 't_NullableNumber.tpl'} +{$IFDEF DEBUG} +procedure AssertDumpAvailable; +var + e: TNullableExtended; +begin + e.Dump; +end; + +initialization + AssertDumpAvailable; +{$ENDIF DEBUG} {$ENDIF DELPHI2007_UP} end. + Modified: trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas 2024-04-06 14:46:33 UTC (rev 4227) +++ trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas 2024-04-06 15:10:08 UTC (rev 4228) @@ -13,22 +13,24 @@ uses SysUtils, u_dzTranslator, + u_dzNullableTypesUtils, u_dzNullableExtended; type TNullableTimespan = record private - FIsValid: IInterface; + FIsValid: INullableTypesFlagInterface; ///<summary> - /// Note: This used to be a double, encoded like in TDateTime but since that turned out - /// to have rather severe rounding errors I now use an Int64 each for days and - /// Microseconds. The actual timespan is always the sum of both. - /// They should always have the same sign. </summary> + /// @NOTE: This used to be a double, encoded like in TDateTime but since that turned out + /// to have rather severe rounding errors I now use an Int64 each for days and + /// Microseconds. The actual timespan is always the sum of both. + /// They should always have the same sign. </summary> FFullDays: Int64; FMicroSeconds: Int64; procedure CheckIsValid; procedure SetDaysAndMicroseconds(_FullDays: Int64; _MicroSeconds: Int64); inline; public + function Dump: string; procedure Invalidate; function IsValid: Boolean; function InDays: Double; @@ -75,23 +77,33 @@ function GetMilliSeconds(out _MilliSeconds: Integer): Boolean; overload; deprecated; // use TryGetMillSeconds procedure GetDaysHoursMinutesSeconds(out _Days, _Hours, _Minutes, _Seconds: Int64); overload; procedure GetDaysHoursMinutesSeconds(out _Days, _Hours, _Minutes: Int64; out _Seconds: Double); overload; - ///<summary> Generates a string of the form 'hh<separator>mm' - /// @param Separator is used to separate the hour and minute part, - /// if Separator is #0, no separator is used. - /// @param NullValue is the value used if the TNullableTimespan value is not valid. </summary> + ///<summary> + /// Generates a string of the form 'hh<separator>mm' + /// @param Separator is used to separate the hour and minute part, + /// if Separator is #0, no separator will be used. + /// @param NullValue is the value used if the TNullableTimespan value is not valid. </summary> function ToHHmm(_Separator: Char = #0; const _NullValue: string = ''): string; - ///<summary> Converts the value to a string representation of InHours with the given - /// number of decimals. Returns an NullValue, if invalid.</summary> + ///<summary> + /// Converts the value to a string representation of InHours with the given + /// number of decimals. Returns NullValue, if invalid.</summary> function ToHourStr(_Decimals: Integer = 1; const _NullValue: string = ''): string; - function ForDisplay: string; - ///<summary> Calculates the value from the given Days, Hours, Minutes, Seconds and - /// Milliseconds. All these values can be higher than the usual maximum value - /// eg. you could passs 26 hours and 100 seconds and still get a valid - /// result of 1 day, 2 hours, 1 Minute and 40 seconds. - /// Note: you cannot assign month's or years because they vary in length </summary> + ///<summary> + /// Generates a string for displaying the value. + /// @param Full defines whether the string should only use the two most significant values (False) + /// or all values (True). Defaults to False. + /// Most significatn means that it will contain the days and hours, if days is > 0, + /// hours and minutes if hours > 0, minutes and seconds otherwise. </summary> + function ForDisplay(_Full: Boolean = False): string; + ///<summary> + /// Calculates the value from the given Days, Hours, Minutes, Seconds and Milliseconds. + /// All these values can be higher than the usual maximum value e.g. you could passs + /// 26 hours and 100 seconds and still get a valid esult of 1 day, 2 hours, 1 Minute + /// and 40 seconds. + /// @NOTE: you cannot assign month's or years because they vary in length </summary> procedure Assign(_Days, _Hours, _Minutes, _Seconds, _MilliSeconds: Word); - ///<summary> Note that Days is not a TDateTime value representing a date but just a number - /// of days with possibly fractions. </summary> + ///<summary> + /// @Note: Days is not a TDateTime value representing a date but just a number + /// of days with possibly fractions. </summary> procedure AssignDays(_Days: Double); procedure AssignHours(_Hours: Extended); overload; procedure AssignHours(_Hours: TNullableExtended); overload; @@ -151,8 +163,7 @@ Math, DateUtils, u_dzConvertUtils, - u_dzDateUtils, - u_dzNullableTypesUtils; + u_dzDateUtils; function _(const _s: string): string; inline; begin @@ -316,7 +327,7 @@ procedure TNullableTimespan.Assign(_Days, _Hours, _Minutes, _Seconds, _MilliSeconds: Word); begin SetDaysAndMicroseconds(_Days, _Hours * MicrosecondsPerHour + _Minutes * MicrosecondsPerMinute - + _Seconds + MicrosecondsPerSecond + _MilliSeconds * MicrosecondsPerMillisecond); + + _Seconds * MicrosecondsPerSecond + _MilliSeconds * MicrosecondsPerMillisecond); end; function TNullableTimespan.TryGetDays(out _Days: Double): Boolean; @@ -598,7 +609,7 @@ Result := Result + _ToAppend; end; -function TNullableTimespan.ForDisplay: string; +function TNullableTimespan.ForDisplay(_Full: Boolean = False): string; var d: Int64; h: Int64; @@ -606,16 +617,20 @@ s: Double; begin if IsValid then begin - Result := ''; GetDaysHoursMinutesSeconds(d, h, m, s); - if d > 0 then - Result := AppendToStr(Result, Format(_('%d days'), [d])); - if h > 0 then - Result := AppendToStr(Result, Format(_('%d hours'), [h])); - if (d = 0) then - Result := AppendToStr(Result, Format(_('%d minutes'), [m])); - if (d = 0) and (h = 0) then - Result := AppendToStr(Result, Format(_('%.2f seconds'), [s])); + if _Full then begin + Result := Format(_('%d days %d hours %d minutes %.3f seconds'), [d, h, m, s]); + end else begin + Result := ''; + if d > 0 then + Result... [truncated message content] |
From: <tw...@us...> - 2024-08-10 14:03:35
|
Revision: 4289 http://sourceforge.net/p/gexperts/code/4289 Author: twm Date: 2024-08-10 14:03:32 +0000 (Sat, 10 Aug 2024) Log Message: ----------- updated dzlib to latest version Modified Paths: -------------- trunk/ExternalSource/dzlib/dzlib.inc trunk/ExternalSource/dzlib/u_dzConvertUtils.pas trunk/ExternalSource/dzlib/u_dzFileStreams.pas trunk/ExternalSource/dzlib/u_dzFileUtils.pas trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas trunk/ExternalSource/dzlib/u_dzTypInfo.pas trunk/ExternalSource/dzlib/u_dzTypes.pas trunk/ExternalSource/dzlib/u_dzVclUtils.pas Added Paths: ----------- trunk/ExternalSource/dzlib/u_dzTypeInfoUtils.pas Modified: trunk/ExternalSource/dzlib/dzlib.inc =================================================================== --- trunk/ExternalSource/dzlib/dzlib.inc 2024-07-08 15:51:56 UTC (rev 4288) +++ trunk/ExternalSource/dzlib/dzlib.inc 2024-08-10 14:03:32 UTC (rev 4289) @@ -25,6 +25,7 @@ {$DEFINE SUPPORTS_DEPRECATED_TYPES} {$DEFINE HAS_UNIT_WIDESTRINGS} {$DEFINE OPENDIALOG_EXCUTE_HAS_HANDLE} + {$DEFINE ENUM_NAMES_ARE_UTF8} {$ENDIF} {$IFDEF DELPHI2006_UP} @@ -55,6 +56,7 @@ // THandleStream.FHandle is declared as THandle (before that it's an Integer) {$DEFINE THANDLESTREAM_HANDLE_IS_THANDLE} {$DEFINE HAS_TOBJECT_TOSTRING} + {$DEFINE HAS_UTF8TOWIDESTRING} {$ENDIF} {$IFDEF DELPHI2010_UP} Modified: trunk/ExternalSource/dzlib/u_dzConvertUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzConvertUtils.pas 2024-07-08 15:51:56 UTC (rev 4288) +++ trunk/ExternalSource/dzlib/u_dzConvertUtils.pas 2024-08-10 14:03:32 UTC (rev 4289) @@ -47,7 +47,8 @@ TBaseN = 2..36; const - MaxLongWord = $FFFFFFFF; + MaxLongWord = $FFFFFFFF deprecated; // use u_dzTypes MaxUInt32 + MaxInt64 = $7FFFFFFFFFFFFFFF deprecated; // use u_dzTypes MaxInt64 const /// <summary> @@ -254,6 +255,11 @@ /// @raises EStringConvertError if s can not be converted </summary> function Str2Int64(const _s: string; const _Source: string): Int64; overload; +function TryStr2Int64(const _s: string; var _Value: Int64): Boolean; overload; +{$IFDEF SUPPORTS_UNICODE} +function TryStr2Int64(const _s: AnsiString; var _Value: Int64): Boolean; overload; +{$ENDIF SUPPORTS_UNICODE} + ///<summary> /// tries to guess the decimal separator </summary> function GuessDecimalSeparator(const _s: string): Char; @@ -1177,6 +1183,24 @@ end; {$ENDIF SUPPORTS_UNICODE} +function TryStr2Int64(const _s: string; var _Value: Int64): Boolean; overload; +var + e: Integer; + v: Integer; +begin + Val(_s, v, e); + Result := (e = 0); + if Result then + _Value := v; +end; + +{$IFDEF SUPPORTS_UNICODE} +function TryStr2Int64(const _s: AnsiString; var _Value: Int64): Boolean; overload; +begin + Result := TryStr2Int64(string(_s), _Value); +end; +{$ENDIF SUPPORTS_UNICODE} + function Str2Int64(const _s: string; _Default: Int64): Int64; var e: Integer; Modified: trunk/ExternalSource/dzlib/u_dzFileStreams.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzFileStreams.pas 2024-07-08 15:51:56 UTC (rev 4288) +++ trunk/ExternalSource/dzlib/u_dzFileStreams.pas 2024-08-10 14:03:32 UTC (rev 4289) @@ -126,6 +126,13 @@ /// * CreateDisposition := fcCreateTruncateIfExists; /// raises an exception on error </summary> procedure OpenCreateWriteNoSharing; + ///<summary> + /// Opens a new file for writing only (or truncates an existing file): + /// * AccessMode := [faWrite]; + /// * ShareMode := fsShareRead; + /// * CreateDisposition := fcCreateTruncateIfExists; + /// raises an exception on error </summary> + procedure OpenCreateWriteShareRead; ///<summary> Opens the file and seeks to the end. Returns the new position (that is: The file length). </summary> function Append: LongInt; ///<summary> @@ -346,6 +353,14 @@ Open; end; +procedure TdzFile.OpenCreateWriteShareRead; +begin + CreateDisposition := fcCreateTruncateIfExists; + ShareMode := [fsRead]; + AccessMode := [faWrite]; + Open; +end; + procedure TdzFile.Open; var LastError: Cardinal; Modified: trunk/ExternalSource/dzlib/u_dzFileUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzFileUtils.pas 2024-07-08 15:51:56 UTC (rev 4288) +++ trunk/ExternalSource/dzlib/u_dzFileUtils.pas 2024-08-10 14:03:32 UTC (rev 4289) @@ -935,7 +935,7 @@ /// Uses kernel32.GetFullPathName and then compares the result using SameText. /// Note that this does not handle all possible cases, e.g. two files with totally different /// names could be the same due to hard links, soft links or multiple UNC paths pointing to - // the same directory. </summary> + /// the same directory. </summary> class function IsSameFilename(const _fn1, _fn2: string): Boolean; ///<summary> Modified: trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2024-07-08 15:51:56 UTC (rev 4288) +++ trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2024-08-10 14:03:32 UTC (rev 4289) @@ -772,6 +772,7 @@ pngimage, // support for TImage.LoadGraphics for PNG files {$ENDIF} GraphUtil, + u_dzTypeInfoUtils, u_dzFileUtils; function _(const _s: string): string; @@ -1708,8 +1709,8 @@ Assert(Assigned(_bmp), 'bitmap is not assigned'); Result := (_bmp.PixelFormat = _Expected); if not Result then begin - ActualName := GetEnumName(TypeInfo(TPixelFormat), Ord(_bmp.PixelFormat)); - ExpectedName := GetEnumName(TypeInfo(TPixelFormat), Ord(_Expected)); + ActualName := SafeGetEnumName(TypeInfo(TPixelFormat), Ord(_bmp.PixelFormat)); + ExpectedName := SafeGetEnumName(TypeInfo(TPixelFormat), Ord(_Expected)); Assert(False, 'unexpected PixelFormat ' + ActualName + ' (expected ' + ExpectedName + ')'); end; end; Modified: trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas 2024-07-08 15:51:56 UTC (rev 4288) +++ trunk/ExternalSource/dzlib/u_dzNullableTimespan.pas 2024-08-10 14:03:32 UTC (rev 4289) @@ -142,6 +142,7 @@ class operator Multiply(_a: TNullableTimespan; _b: Extended): TNullableTimespan; class function Zero: TNullableTimespan; static; + class function OneDay: TNullableTimespan; static; class function FromDays(_Days: Double): TNullableTimespan; static; class function FromHours(_Hours: Extended): TNullableTimespan; overload; static; class function FromHours(_Hours: TNullableExtended): TNullableTimespan; overload; static; @@ -640,6 +641,11 @@ Result.AssignZero; end; +class function TNullableTimespan.OneDay: TNullableTimespan; +begin + Result.AssignDays(1); +end; + class operator TNullableTimespan.GreaterThanOrEqual(_a, _b: TNullableTimespan): Boolean; begin Result := not (_a < _b); Modified: trunk/ExternalSource/dzlib/u_dzTypInfo.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzTypInfo.pas 2024-07-08 15:51:56 UTC (rev 4288) +++ trunk/ExternalSource/dzlib/u_dzTypInfo.pas 2024-08-10 14:03:32 UTC (rev 4289) @@ -16,7 +16,7 @@ TypInfo, u_dzTranslator; - // I am not going to proved support for Variant properties here. I hate Variants. +// I am not going to provide support for Variant properties here. I hate Variants. const ///<summary> property types that can be converted to string </summary> @@ -88,6 +88,9 @@ {$IFDEF DELPHI2007_UP} +uses + u_dzTypes; + function _(const _s: string): string; inline; begin Result := dzlibGetText(_s); @@ -353,3 +356,4 @@ {$ENDIF DELPHI2007_UP} end. + Added: trunk/ExternalSource/dzlib/u_dzTypeInfoUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzTypeInfoUtils.pas (rev 0) +++ trunk/ExternalSource/dzlib/u_dzTypeInfoUtils.pas 2024-08-10 14:03:32 UTC (rev 4289) @@ -0,0 +1,92 @@ +unit u_dzTypeInfoUtils; + +{$INCLUDE 'dzlib.inc'} + +interface + +uses + SysUtils, + TypInfo; + +function SafeGetEnumName(TypeInfo: PTypeInfo; Value: Integer): string; + +implementation + +uses + u_dzTypes; + +function SafeGetEnumName(TypeInfo: PTypeInfo; Value: Integer): string; + + procedure IncPtr(var _p: Pointer); + begin + _p := Pointer(Intptr(_p) + 1); + end; + + // P must point to the length field (that is the first byte) of a ShortString + function AfterShortString(const P: Pointer): Pointer; + begin + Result := Pointer(Intptr(P) + PByte(P)^ + 1); + end; + +{$IFDEF ENUM_NAMES_ARE_UTF8} + +{$IFNDEF HAS_UTF8TOWIDESTRING} + function UTF8ToWideString(const _Utf8: RawByteString): WideString; + begin + Result := UTF8Decode(_Utf8); + end; +{$ENDIF} + +// Older Unicode Delphi versions did not have a UTF8ToString overload for a pointer parameter +{$IFNDEF DELPHIX_ATHENS_UP} + function _UTF8ToString(P: Pointer): WideString; + var + Len: Byte; + Buf: UTF8String; + begin + Result := ''; + Len := PByte(P)^; + if Len <> 0 then begin + SetLength(Buf, Len); + IncPtr(P); + Move(PByte(P)^, Buf[1], Len); + Result := UTF8ToWideString(Buf); + end; + end; +{$ENDIF} +{$ENDIF} + +var + P: Pointer; + T: PTypeData; +begin + if TypeInfo^.Kind = tkInteger then begin + Result := IntToStr(Value); + Exit; + end; + T := GetTypeData(GetTypeData(TypeInfo)^.BaseType^); + if (TypeInfo = System.TypeInfo(Boolean)) or (T^.MinValue < 0) then begin + { LongBool/WordBool/ByteBool have MinValue < 0 and arbitrary + content in Value; Boolean has Value in [0, 1] } + Result := BooleanIdents[Value <> 0]; + if SameText(HexDisplayPrefix, '0x') then + Result := LowerCase(Result); + end else begin + if (Value < T.MinValue) or (Value > T.MaxValue) then + Result := Format('OutOfBounds(%d)', [Value]) + else begin + P := @T^.NameList; + while Value <> 0 do begin + P := AfterShortString(P); + Dec(Value); + end; +{$IFDEF ENUM_NAMES_ARE_UTF8} + Result := _UTF8ToString(P); +{$ELSE} + Result := PShortString(P)^; +{$ENDIF} + end; + end; +end; + +end. Modified: trunk/ExternalSource/dzlib/u_dzTypes.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzTypes.pas 2024-07-08 15:51:56 UTC (rev 4288) +++ trunk/ExternalSource/dzlib/u_dzTypes.pas 2024-08-10 14:03:32 UTC (rev 4289) @@ -169,16 +169,59 @@ {$IFEND} TStringArray = TStringDynArray; TRawByteStringArray = array of RawByteString; - TIntegerArray = array of Integer; - PIntegerArray = ^TIntegerArray; - TSingleArray = array of Single; - PSingleArray = ^TSingleArray; - TDoubleArray = array of Double; - PDoubleArray = ^TDoubleArray; - TExtendedArray = array of Extended; - PExtendedArray = ^TExtendedArray; - TExtendedDynArray = TExtendedArray; + +{$IF not declared(TInt32DynArray)} + TInt32DynArray = array of Int32; +{$IFEND} +{$IF not declared(PInt32DynArray)} + PInt32DynArray = ^TInt32DynArray; +{$IFEND} +{$IF not declared(TIntegerDynArray)} + TIntegerDynArray = TInt32DynArray + {$IFDEF SUPPORTS_DEPRECATED_TYPES} deprecated {$ENDIF}; // use TInt32DynArray instead +{$IFEND} +{$IF not declared(PIntegerDynArray)} + PIntegerDynArray = PInt32DynArray + {$IFDEF SUPPORTS_DEPRECATED_TYPES} deprecated {$ENDIF}; // use PInt32DynArray instead +{$IFEND} + TIntegerArray = TInt32DynArray + {$IFDEF SUPPORTS_DEPRECATED_TYPES} deprecated {$ENDIF}; // use TInt32DynArray or TIntegerDynArray instead + PIntegerArray = PInt32DynArray + {$IFDEF SUPPORTS_DEPRECATED_TYPES} deprecated {$ENDIF}; // use PInt32DynArray or PIntegerDynArray instead + +{$IF not declared(TSingleDynArray)} + TSingleDynArray = array of Single; +{$IFEND} +{$IF not declared(PSingleDynArray)} + PSingleDynArray = ^TSingleDynArray; +{$IFEND} + TSingleArray = TSingleDynArray + {$IFDEF SUPPORTS_DEPRECATED_TYPES} deprecated {$ENDIF}; // use TSingleDynArray instead + PSingleArray = PSingleDynArray + {$IFDEF SUPPORTS_DEPRECATED_TYPES} deprecated {$ENDIF}; // use PSingleDynArray instead + +{$IF not declared(TDoubleDynArray)} + TDoubleDynArray = array of Double; +{$IFEND} +{$IF not declared(PDoubleDynArray)} + PDoubleDynArray = ^TDoubleDynArray; +{$IFEND} + TDoubleArray = TDoubleDynArray + {$IFDEF SUPPORTS_DEPRECATED_TYPES} deprecated {$ENDIF}; // use TDoubleDynArray instead + PDoubleArray = PDoubleDynArray + {$IFDEF SUPPORTS_DEPRECATED_TYPES} deprecated {$ENDIF}; // use PDoubleDynArray instead + +{$IF not declared(TExtendedDynArray)} + TExtendedDynArray = array of Extended; +{$IFEND} +{$IF not declared(PExtendedDynArray)} PExtendedDynArray = ^TExtendedDynArray; +{$IFEND} + TExtendedArray = TExtendedDynArray + {$IFDEF SUPPORTS_DEPRECATED_TYPES} deprecated {$ENDIF}; // use TExtendedDynArray instead + PExtendedArray = PExtendedDynArray + {$IFDEF SUPPORTS_DEPRECATED_TYPES} deprecated {$ENDIF}; // use PExtendedDynArray instead + {$IF not Declared(TBytes)} TBytes = array of Byte; {$IFEND} Modified: trunk/ExternalSource/dzlib/u_dzVclUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2024-07-08 15:51:56 UTC (rev 4288) +++ trunk/ExternalSource/dzlib/u_dzVclUtils.pas 2024-08-10 14:03:32 UTC (rev 4289) @@ -1163,6 +1163,20 @@ function TRadioGroup_GetSelectedObject(_rg: TCustomRadioGroup; out _Obj: Pointer): Boolean; overload; function TRadioGroup_GetSelectedObject(_rg: TCustomRadioGroup; out _ObjAsInt: Integer): Boolean; overload; +///<summary> +/// If Highlighted is True, highlights the RadioGroup's Idx'th button, otherwise it un-highlights it, +/// Highlighting the button means setting its Font.Color to the given Color, and un-higlighting +/// means to set its ParentFont property to True </summary> +procedure TRadioGroup_HighlightButton(_rg: TRadioGroup; _Idx: Integer; _Highlighted: Boolean; + _Color: TColor = clRed); + +///<summary> +/// Highlights the currently selected button of the ReadioGroup if it is not the given DefaultIdx. +/// Highlighting the button means setting its Font.Color to the given Color, and un-higlighting +/// means to set its ParentFont property to True </summary> +procedure TRadioGroup_HighlightIfNotDefault(_rg: TRadioGroup; _DefaultIdx: Integer; + _Color: TColor = clRed); + ///<summary> Writes a TPicture object to a String. The Format is /// <pictureformat>#26<picturedata> </summary> function TPicture_WriteToString(_Pic: TPicture): string; @@ -1635,6 +1649,34 @@ ///<summary> Sets the Caption value of a TCheckbox or TRadioButton (which both descend from TButtonControl) </summary> procedure TButtonControl_SetCaption(_bctrl: TButtonControl; const _Value: string); +///<summary> +/// If Highlight is True, hightlightes the button, ohterweise un-highlights it. +/// Highlighting the button means setting its Font.Color to the given Color, and un-higlighting +/// means to set its ParentFont property to True </summary> +procedure TButtonControl_Highlight(_bctrl: TButtonControl; _Highlighted: Boolean; _Color: TColor = clRed); + +///<summary> +/// Highlights the button if its Checked property does not have the default value. +/// Otherwise un-highlights it. +/// Highlighting the button means setting its Font.Color to the given Color, and un-higlighting +/// means to set its ParentFont property to True </summary> +procedure TButtonControl_HighlightIfNotDefault(_bctrl: TButtonControl; _Default: Boolean; + _Color: TColor = clRed); + +///<summary> +/// Highlights the button if is checked. +/// Otherwise un-highlights it. +/// Highlighting the button means setting its Font.Color to the given Color, and un-higlighting +/// means to set its ParentFont property to True </summary> +procedure TButtonControl_HighlightIfChecked(_bctrl: TButtonControl; _Color: TColor = clRed); + +///<summary> +/// Highlights the button if is no checked. +/// Otherwise un-highlights it. +/// Highlighting the button means setting its Font.Color to the given Color, and un-higlighting +/// means to set its ParentFont property to True </summary> +procedure TButtonControl_HighlightIfNotChecked(_bctrl: TButtonControl; _Color: TColor = clRed); + {$IFNDEF DELPHI2009_UP} //Delphi 2009 introduced TCustomButton as the common Ancestor of TButton and TBitBtn. type @@ -4322,6 +4364,27 @@ _ObjAsInt := Integer(Obj); //FI:W541 Casting from Integer to Pointer type (or vice versa) end; +procedure TRadioGroup_HighlightButton(_rg: TRadioGroup; _Idx: Integer; _Highlighted: Boolean; + _Color: TColor = clRed); +begin + if (_Idx < 0) or (_Idx >= _rg.Items.Count) then + Exit; //==> + + TButtonControl_Highlight(TRadioGroup_GetButton(_rg, _Idx), _Highlighted, _Color); +end; + +procedure TRadioGroup_HighlightIfNotDefault(_rg: TRadioGroup; _DefaultIdx: Integer; + _Color: TColor = clRed); +var + Idx: Integer; + i: Integer; +begin + Idx := _rg.ItemIndex; + for i := 0 to _rg.Items.Count - 1 do begin + TRadioGroup_HighlightButton(_rg, i, (i = Idx) and not (i = _DefaultIdx)); + end; +end; + function TRichEdit_WriteToString(_Re: TRichEdit): string; var st: TMemoryStream; @@ -5708,6 +5771,43 @@ THackButtonControl(_bctrl).Caption := _Value; end; +procedure TButtonControl_Highlight(_bctrl: TButtonControl; _Highlighted: Boolean; _Color: TColor = clRed); +var + bctrl: TButtonControlHack absolute _bctrl; +begin + if not Assigned(bctrl) then + Exit; //==> + + if _Highlighted then + bctrl.Font.Color := _Color + else + bctrl.ParentFont := True; +end; + +procedure TButtonControl_HighlightIfNotDefault(_bctrl: TButtonControl; _Default: Boolean; + _Color: TColor = clRed); +var + bctrl: TButtonControlHack absolute _bctrl; +begin + if not Assigned(bctrl) then + Exit; //==> + + if bctrl.Checked <> _Default then + bctrl.Font.Color := _Color + else + bctrl.ParentFont := True; +end; + +procedure TButtonControl_HighlightIfChecked(_bctrl: TButtonControl; _Color: TColor = clRed); +begin + TButtonControl_HighlightIfNotDefault(_bctrl, False, _Color); +end; + +procedure TButtonControl_HighlightIfNotChecked(_bctrl: TButtonControl; _Color: TColor = clRed); +begin + TButtonControl_HighlightIfNotDefault(_bctrl, True, _Color); +end; + type TButtonPopupMenuLink = class(TComponent) private This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |